use axum::{Router, middleware};
use rmcp::transport::streamable_http_server::{
StreamableHttpService, session::local::LocalSessionManager,
};
use crate::handlers::McpServer;
use oauth_provider_rs::{DefaultClientManager, OAuthProviderTrait, OAuthStorage, http_integration::middleware::simple_auth_middleware};
#[derive(Clone)]
pub struct StreamableHttpHandler<
P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static,
S: OAuthStorage + Clone + 'static,
> {
mcp_server: McpServer<P, S>,
}
impl<P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static, S: OAuthStorage + Clone + 'static>
StreamableHttpHandler<P, S>
{
pub fn new(mcp_server: McpServer<P, S>) -> Self {
Self { mcp_server }
}
pub fn router(self) -> Router {
let mcp_server = self.mcp_server.clone();
let session_manager = LocalSessionManager::default();
let service = StreamableHttpService::new(
move || Ok(mcp_server.clone()),
session_manager.into(),
Default::default(),
);
Router::new()
.nest_service("/mcp/streamable", service)
.layer(middleware::from_fn(simple_auth_middleware))
}
}
#[cfg(test)]
mod tests {
use super::*;
use oauth_provider_rs::{GitHubOAuthConfig, GitHubOAuthProvider, OAuthProvider, http_integration::utils::validate_token_simple};
#[tokio::test]
async fn test_streamable_http_handler_creation() {
let github_config = GitHubOAuthConfig {
client_id: "test_client_id".to_string(),
client_secret: "test_client_secret".to_string(),
redirect_uri: "http://localhost:8081/oauth/callback".to_string(),
scope: "read:user".to_string(),
provider_name: "github".to_string(),
};
let oauth_provider = OAuthProvider::new(GitHubOAuthProvider::new_github(github_config));
let mcp_server = McpServer::new(oauth_provider);
let _handler = StreamableHttpHandler::new(mcp_server);
}
#[tokio::test]
async fn test_token_validation() {
assert!(validate_token_simple("").await.is_err());
assert!(validate_token_simple("some_token").await.is_ok());
}
}