remote_mcp_kernel/handlers/
streamable_http.rs

1//! Streamable HTTP endpoint with OAuth authorization
2//!
3//! This module provides a streamable HTTP endpoint that requires OAuth authentication
4//! to access MCP services using the centralized middleware.
5
6use axum::{Router, middleware};
7use rmcp::transport::streamable_http_server::{
8    StreamableHttpService, session::local::LocalSessionManager,
9};
10
11use crate::handlers::McpServerHandler;
12use oauth_provider_rs::http_integration::middleware::simple_auth_middleware;
13
14/// Streamable HTTP handler with OAuth authorization
15#[derive(Clone)]
16pub struct StreamableHttpHandler<M: McpServerHandler> {
17    mcp_server: M,
18}
19
20impl<M: McpServerHandler> StreamableHttpHandler<M> {
21    /// Create new streamable HTTP handler with MCP server
22    pub fn new(mcp_server: M) -> Self {
23        Self { mcp_server }
24    }
25
26    /// Create router with streamable HTTP endpoint protected by OAuth
27    pub fn router(self) -> Router {
28        let mcp_server = self.mcp_server.clone();
29        let session_manager = LocalSessionManager::default();
30        let service = StreamableHttpService::new(
31            move || Ok(mcp_server.clone()),
32            session_manager.into(),
33            Default::default(),
34        );
35
36        Router::new()
37            .nest_service("/mcp/streamable", service)
38            .layer(middleware::from_fn(simple_auth_middleware))
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use crate::handlers::McpServer;
46    use oauth_provider_rs::{
47        http_integration::utils::validate_token_simple, provider_trait::OAuthProviderConfig,
48    };
49
50    #[tokio::test]
51    async fn test_streamable_http_handler_creation() {
52        let github_config = OAuthProviderConfig::with_oauth_config(
53            "test_client_id".to_string(),
54            "test_client_secret".to_string(),
55            "http://localhost:8081/oauth/callback".to_string(),
56            "read:user".to_string(),
57            "github".to_string(),
58        );
59
60        let mcp_server = McpServer::new();
61        let _handler = StreamableHttpHandler::new(mcp_server);
62
63        // Handler should be created successfully - no assertion needed
64    }
65
66    #[tokio::test]
67    async fn test_token_validation() {
68        // Empty token should be invalid
69        assert!(validate_token_simple("").await.is_err());
70
71        // Non-empty token should be valid (in this simple implementation)
72        assert!(validate_token_simple("some_token").await.is_ok());
73    }
74}