use axum::Router;
use std::net::SocketAddr;
use crate::{
error::AppResult,
handlers::{McpServerHandler, SseHandler, SseHandlerConfig, StreamableHttpHandler},
};
use oauth_provider_rs::{DefaultClientManager, OAuthProvider, OAuthProviderTrait, OAuthStorage};
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>
{
pub fn new() -> Self {
Self {
oauth_provider: None,
streamable_handler: None,
sse_handler: None,
sse_config: SseHandlerConfig::default(),
}
}
pub fn with_oauth_provider(mut self, oauth_provider: OAuthProvider<P, S>) -> Self {
self.oauth_provider = Some(oauth_provider);
self
}
pub fn with_streamable_handler(mut self, streamable_handler: StreamableHttpHandler<M>) -> Self {
self.streamable_handler = Some(streamable_handler);
self
}
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
}
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
}
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
}
pub fn build_router(self) -> AppResult<Router> {
let mut router = Router::new();
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");
}
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");
}
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)
}
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()
}
}