remote_mcp_kernel/microkernel/
core.rs

1//! Core microkernel server implementation
2//!
3//! This module contains the main MicrokernelServer implementation
4//! demonstrating the microkernel design pattern.
5
6use axum::Router;
7use std::net::SocketAddr;
8
9use crate::{
10    error::AppResult,
11    handlers::{McpServerHandler, SseHandler, SseHandlerConfig, StreamableHttpHandler},
12};
13use oauth_provider_rs::{DefaultClientManager, OAuthProvider, OAuthProviderTrait, OAuthStorage};
14
15/// Microkernel server builder that composes independent handlers
16///
17/// This builder demonstrates the microkernel principle where services
18/// are composed from independent, single-responsibility components.
19/// Now supports any OAuth provider, storage backend, and MCP server through trait abstraction.
20pub struct MicrokernelServer<
21    P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static,
22    S: OAuthStorage + Clone + 'static,
23    M: McpServerHandler = crate::handlers::McpServer,
24> {
25    oauth_provider: Option<OAuthProvider<P, S>>,
26    streamable_handler: Option<StreamableHttpHandler<M>>,
27    sse_handler: Option<SseHandler<M>>,
28    sse_config: SseHandlerConfig,
29}
30
31impl<
32    P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static,
33    S: OAuthStorage + Clone + 'static,
34    M: McpServerHandler,
35> MicrokernelServer<P, S, M>
36{
37    /// Create a new microkernel server builder
38    pub fn new() -> Self {
39        Self {
40            oauth_provider: None,
41            streamable_handler: None,
42            sse_handler: None,
43            sse_config: SseHandlerConfig::default(),
44        }
45    }
46
47    /// Add OAuth provider handler
48    pub fn with_oauth_provider(mut self, oauth_provider: OAuthProvider<P, S>) -> Self {
49        self.oauth_provider = Some(oauth_provider);
50        self
51    }
52
53    /// Add streamable HTTP handler
54    pub fn with_streamable_handler(mut self, streamable_handler: StreamableHttpHandler<M>) -> Self {
55        self.streamable_handler = Some(streamable_handler);
56        self
57    }
58
59    /// Add SSE handler with configuration
60    pub fn with_sse_handler(
61        mut self,
62        sse_handler: SseHandler<M>,
63        config: SseHandlerConfig,
64    ) -> Self {
65        self.sse_handler = Some(sse_handler);
66        self.sse_config = config;
67        self
68    }
69
70    /// Create SSE handler with MCP server and configuration
71    pub fn with_mcp_sse_handler(mut self, mcp_server: M, config: SseHandlerConfig) -> Self {
72        let sse_handler = SseHandler::new(mcp_server);
73        self.sse_handler = Some(sse_handler);
74        self.sse_config = config;
75        self
76    }
77
78    /// Create streamable HTTP handler with MCP server
79    pub fn with_mcp_streamable_handler(mut self, mcp_server: M) -> Self {
80        let streamable_handler = StreamableHttpHandler::new(mcp_server);
81        self.streamable_handler = Some(streamable_handler);
82        self
83    }
84
85    /// Build the composed router from all registered handlers
86    ///
87    /// This method demonstrates the microkernel composition principle
88    /// where independent components are combined into a unified service.
89    pub fn build_router(self) -> AppResult<Router> {
90        let mut router = Router::new();
91
92        // Compose OAuth handler if present
93        if let Some(oauth_provider) = self.oauth_provider {
94            let oauth_router = oauth_provider.router();
95            router = router.merge(oauth_router);
96            tracing::debug!("✓ OAuth provider router composed");
97        }
98
99        // Compose Streamable HTTP handler if present
100        if let Some(streamable_handler) = self.streamable_handler {
101            let streamable_router = streamable_handler.router();
102            router = router.merge(streamable_router);
103            tracing::debug!("✓ Streamable HTTP handler router composed");
104        }
105
106        // Compose SSE handler if present
107        if let Some(sse_handler) = self.sse_handler {
108            let sse_router = sse_handler.router(self.sse_config)?;
109            router = router.merge(sse_router);
110            tracing::debug!("✓ SSE handler router composed");
111        }
112
113        Ok(router)
114    }
115
116    /// Start the microkernel server
117    pub async fn serve(self, bind_address: SocketAddr) -> AppResult<()> {
118        let router = self.build_router()?;
119
120        let listener = tokio::net::TcpListener::bind(bind_address)
121            .await
122            .map_err(|e| crate::error::AppError::Internal(format!("Failed to bind: {}", e)))?;
123
124        tracing::info!("🏛️  Microkernel server listening on {}", bind_address);
125
126        axum::serve(listener, router)
127            .await
128            .map_err(|e| crate::error::AppError::Internal(format!("Server error: {}", e)))?;
129
130        Ok(())
131    }
132}
133
134impl<
135    P: OAuthProviderTrait<S, DefaultClientManager<S>>,
136    S: OAuthStorage + Clone + 'static,
137    M: McpServerHandler,
138> Default for MicrokernelServer<P, S, M>
139{
140    fn default() -> Self {
141        Self::new()
142    }
143}