remote-mcp-kernel 0.1.0-alpha.2

A microkernel-based MCP (Model Context Protocol) server with OAuth authentication and multiple transport protocols
Documentation
//! Core microkernel server implementation
//!
//! This module contains the main MicrokernelServer implementation
//! demonstrating the microkernel design pattern.

use axum::Router;
use std::net::SocketAddr;

use crate::{
    error::AppResult,
    handlers::{McpServerHandler, SseHandler, SseHandlerConfig, StreamableHttpHandler},
};
use oauth_provider_rs::{DefaultClientManager, OAuthProvider, OAuthProviderTrait, OAuthStorage};

/// Microkernel server builder that composes independent handlers
///
/// This builder demonstrates the microkernel principle where services
/// are composed from independent, single-responsibility components.
/// Now supports any OAuth provider, storage backend, and MCP server through trait abstraction.
pub struct MicrokernelServer<
    P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static,
    S: OAuthStorage + Clone + 'static,
    M: McpServerHandler = crate::handlers::McpServer,
> {
    oauth_provider: Option<OAuthProvider<P, S>>,
    streamable_handler: Option<StreamableHttpHandler<M>>,
    sse_handler: Option<SseHandler<M>>,
    sse_config: SseHandlerConfig,
}

impl<
    P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static,
    S: OAuthStorage + Clone + 'static,
    M: McpServerHandler,
> MicrokernelServer<P, S, M>
{
    /// Create a new microkernel server builder
    pub fn new() -> Self {
        Self {
            oauth_provider: None,
            streamable_handler: None,
            sse_handler: None,
            sse_config: SseHandlerConfig::default(),
        }
    }

    /// Add OAuth provider handler
    pub fn with_oauth_provider(mut self, oauth_provider: OAuthProvider<P, S>) -> Self {
        self.oauth_provider = Some(oauth_provider);
        self
    }

    /// Add streamable HTTP handler
    pub fn with_streamable_handler(mut self, streamable_handler: StreamableHttpHandler<M>) -> Self {
        self.streamable_handler = Some(streamable_handler);
        self
    }

    /// Add SSE handler with configuration
    pub fn with_sse_handler(
        mut self,
        sse_handler: SseHandler<M>,
        config: SseHandlerConfig,
    ) -> Self {
        self.sse_handler = Some(sse_handler);
        self.sse_config = config;
        self
    }

    /// Create SSE handler with MCP server and configuration
    pub fn with_mcp_sse_handler(mut self, mcp_server: M, config: SseHandlerConfig) -> Self {
        let sse_handler = SseHandler::new(mcp_server);
        self.sse_handler = Some(sse_handler);
        self.sse_config = config;
        self
    }

    /// Create streamable HTTP handler with MCP server
    pub fn with_mcp_streamable_handler(mut self, mcp_server: M) -> Self {
        let streamable_handler = StreamableHttpHandler::new(mcp_server);
        self.streamable_handler = Some(streamable_handler);
        self
    }

    /// Build the composed router from all registered handlers
    ///
    /// This method demonstrates the microkernel composition principle
    /// where independent components are combined into a unified service.
    pub fn build_router(self) -> AppResult<Router> {
        let mut router = Router::new();

        // Compose OAuth handler if present
        if let Some(oauth_provider) = self.oauth_provider {
            let oauth_router = oauth_provider.router();
            router = router.merge(oauth_router);
            tracing::debug!("✓ OAuth provider router composed");
        }

        // Compose Streamable HTTP handler if present
        if let Some(streamable_handler) = self.streamable_handler {
            let streamable_router = streamable_handler.router();
            router = router.merge(streamable_router);
            tracing::debug!("✓ Streamable HTTP handler router composed");
        }

        // Compose SSE handler if present
        if let Some(sse_handler) = self.sse_handler {
            let sse_router = sse_handler.router(self.sse_config)?;
            router = router.merge(sse_router);
            tracing::debug!("✓ SSE handler router composed");
        }

        Ok(router)
    }

    /// Start the microkernel server
    pub async fn serve(self, bind_address: SocketAddr) -> AppResult<()> {
        let router = self.build_router()?;

        let listener = tokio::net::TcpListener::bind(bind_address)
            .await
            .map_err(|e| crate::error::AppError::Internal(format!("Failed to bind: {}", e)))?;

        tracing::info!("🏛️  Microkernel server listening on {}", bind_address);

        axum::serve(listener, router)
            .await
            .map_err(|e| crate::error::AppError::Internal(format!("Server error: {}", e)))?;

        Ok(())
    }
}

impl<
    P: OAuthProviderTrait<S, DefaultClientManager<S>>,
    S: OAuthStorage + Clone + 'static,
    M: McpServerHandler,
> Default for MicrokernelServer<P, S, M>
{
    fn default() -> Self {
        Self::new()
    }
}