Skip to main content

rmcp_actix_web/
lib.rs

1//! # rmcp-actix-web
2//!
3#![warn(missing_docs)]
4//! actix-web transport implementations for RMCP (Rust Model Context Protocol).
5//!
6//! This crate provides HTTP-based transport layers for the [Model Context Protocol (MCP)][mcp],
7//! offering a complete alternative to the default Axum-based transports in the main [RMCP crate][rmcp].
8//! If you're already using actix-web in your application or prefer its API, this crate allows
9//! you to integrate MCP services seamlessly without introducing additional web frameworks.
10//!
11//! [mcp]: https://modelcontextprotocol.io/
12//! [rmcp]: https://crates.io/crates/rmcp
13//!
14//! ## Features
15//!
16//! - **[Streamable HTTP Transport][StreamableHttpService]**: Bidirectional communication with session management
17//! - **Full MCP Compatibility**: Implements the complete MCP specification
18//! - **Drop-in Replacement**: Same service implementations work with either Axum or actix-web transports
19//! - **Production Ready**: Built on battle-tested actix-web framework
20//!
21//! ## Quick Start
22//!
23//! ### Streamable HTTP Server Example
24//!
25//! ```rust,no_run
26//! use rmcp_actix_web::transport::{StreamableHttpService, AuthorizationHeader};
27//! use rmcp::transport::streamable_http_server::session::local::LocalSessionManager;
28//! use rmcp::{ServerHandler, model::ServerInfo};
29//! use actix_web::{App, HttpServer};
30//! use std::{sync::Arc, time::Duration};
31//!
32//! # #[derive(Clone)]
33//! # struct MyMcpService;
34//! # impl ServerHandler for MyMcpService {
35//! #     fn get_info(&self) -> ServerInfo { ServerInfo::default() }
36//! # }
37//! # impl MyMcpService {
38//! #     fn new() -> Self { Self }
39//! # }
40//! #[actix_web::main]
41//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
42//!     // Create service OUTSIDE HttpServer::new() to share across workers
43//!     let http_service = StreamableHttpService::builder()
44//!         .service_factory(Arc::new(|| Ok(MyMcpService::new())))
45//!         .session_manager(Arc::new(LocalSessionManager::default()))
46//!         .stateful_mode(true)
47//!         .sse_keep_alive(Duration::from_secs(30))
48//!         .build();
49//!
50//!     HttpServer::new(move || {
51//!         App::new()
52//!             // Clone service for each worker (shares the same LocalSessionManager)
53//!             .service(http_service.clone().scope())
54//!     })
55//!     .bind("127.0.0.1:8080")?
56//!     .run()
57//!     .await?;
58//!
59//!     Ok(())
60//! }
61//! ```
62//!
63//! ## Examples
64//!
65//! See the `examples/` directory for complete working examples:
66//! - `counter_streamable_http.rs` - Streamable HTTP server example
67//! - `composition_streamable_http_example.rs` - StreamableHttp with custom mounting
68//! - `authorization_proxy_example.rs` - Authorization header forwarding example
69//!
70//! ## Framework-Level Composition
71//!
72//! The transport supports framework-level composition aligned with RMCP patterns,
73//! allowing you to mount MCP services at custom paths within existing actix-web applications.
74//!
75//! ### Service Composition
76//!
77//! ```rust,no_run
78//! use rmcp_actix_web::transport::{StreamableHttpService, AuthorizationHeader};
79//! use rmcp::transport::streamable_http_server::session::local::LocalSessionManager;
80//! use actix_web::{App, web};
81//! use std::{sync::Arc, time::Duration};
82//!
83//! # use rmcp::{ServerHandler, model::ServerInfo};
84//! # #[derive(Clone)]
85//! # struct MyService;
86//! # impl ServerHandler for MyService {
87//! #     fn get_info(&self) -> ServerInfo { ServerInfo::default() }
88//! # }
89//! # impl MyService { fn new() -> Self { Self } }
90//! # use actix_web::HttpServer;
91//! # #[actix_web::main]
92//! # async fn main() -> std::io::Result<()> {
93//! // Create service OUTSIDE HttpServer::new() to share across workers
94//! let http_service = StreamableHttpService::builder()
95//!     .service_factory(Arc::new(|| Ok(MyService::new())))
96//!     .session_manager(Arc::new(LocalSessionManager::default()))
97//!     .stateful_mode(true)
98//!     .sse_keep_alive(Duration::from_secs(30))
99//!     .build();
100//!
101//! HttpServer::new(move || {
102//!     // Mount at custom path using scope() (cloned for each worker)
103//!     App::new()
104//!         .service(web::scope("/api/v1/calculator").service(http_service.clone().scope()))
105//! }).bind("127.0.0.1:8080")?.run().await
106//! # }
107//! ```
108//!
109//
110//! See the `examples/` directory for complete working examples of composition patterns.
111//!
112//! ## Performance Considerations
113//!
114//! - Streamable HTTP maintains persistent sessions which may use more memory
115//! - Uses efficient async I/O through actix-web's actor system
116//! - Framework-level composition adds minimal overhead
117//!
118//! ## Feature Flags
119//!
120//! - `transport-streamable-http` (default): Enables StreamableHttp transport
121
122pub mod transport;