Skip to content

Commit a0b4487

Browse files
committed
refactor: implement explicit type names for multi-framework support
- Add explicit framework-specific exports: AxumSseServer, ActixSseServer - Add explicit exports for StreamableHttpService: AxumStreamableHttpService, ActixStreamableHttpService - Maintain convenience aliases that resolve to preferred implementation based on features - Update tests to use explicit type names with feature gates while maximizing code reuse - Add comprehensive module documentation explaining type export strategy - Ensure backwards compatibility while providing clear framework selection - Remove unused TransportReceiver type aliases from both implementations - Fix port conflicts in JavaScript tests by using separate ports for Axum and actix-web - Add /mcp scope wrapper for actix-web streamable HTTP test to match expected routing This resolves type confusion when both frameworks are enabled and makes it explicit which implementation is being used in tests and user code.
1 parent 97a955c commit a0b4487

File tree

7 files changed

+322
-173
lines changed

7 files changed

+322
-173
lines changed

crates/rmcp/src/transport.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,37 @@
1010
//! | streamable http | [`streamable_http_client::StreamableHttpClientTransport`] | [`streamable_http_server::StreamableHttpService`] |
1111
//! | sse | [`sse_client::SseClientTransport`] | [`sse_server::SseServer`] |
1212
//!
13-
//!## Helper Transport Types
13+
//! ## Framework Support
14+
//!
15+
//! Several transport types support multiple web frameworks through feature flags:
16+
//!
17+
//! ### SSE Server Transport
18+
//! - **Convenience alias**: [`SseServer`] - resolves to the appropriate implementation based on enabled features
19+
//! - **Explicit types**: [`AxumSseServer`], [`ActixSseServer`] - use specific framework implementations
20+
//!
21+
//! ### Streamable HTTP Server Transport
22+
//! - **Convenience alias**: [`StreamableHttpService`] - resolves to the appropriate implementation based on enabled features
23+
//! - **Explicit types**: [`AxumStreamableHttpService`], [`ActixStreamableHttpService`] - use specific framework implementations
24+
//!
25+
//! #### Type Resolution Strategy
26+
//! The convenience aliases resolve as follows:
27+
//! - When `actix-web` feature is enabled: aliases point to actix-web implementations
28+
//! - When only `axum` feature is enabled: aliases point to axum implementations
29+
//!
30+
//! #### Usage Examples
31+
//! ```rust,ignore
32+
//! // Using convenience aliases (recommended for most cases)
33+
//! use rmcp::transport::{SseServer, StreamableHttpService};
34+
//! let server = SseServer::serve("127.0.0.1:8080".parse()?).await?;
35+
//!
36+
//! // Using explicit types (when you need a specific implementation)
37+
//! #[cfg(feature = "axum")]
38+
//! use rmcp::transport::AxumSseServer;
39+
//! #[cfg(feature = "axum")]
40+
//! let server = AxumSseServer::serve("127.0.0.1:8080".parse()?).await?;
41+
//! ```
42+
//!
43+
//! ## Helper Transport Types
1444
//! Thers are several helper transport types that can help you to create transport quickly.
1545
//!
1646
//! ### [Worker Transport](`worker::WorkerTransport`)
@@ -105,10 +135,21 @@ pub use sse_client::SseClientTransport;
105135
#[cfg(feature = "transport-sse-server")]
106136
#[cfg_attr(docsrs, doc(cfg(feature = "transport-sse-server")))]
107137
pub mod sse_server;
138+
139+
// Re-export convenience alias
108140
#[cfg(all(feature = "transport-sse-server", any(feature = "axum", feature = "actix-web")))]
109141
#[cfg_attr(docsrs, doc(cfg(all(feature = "transport-sse-server", any(feature = "axum", feature = "actix-web")))))]
110142
pub use sse_server::SseServer;
111143

144+
// Re-export explicit types
145+
#[cfg(all(feature = "transport-sse-server", feature = "axum"))]
146+
#[cfg_attr(docsrs, doc(cfg(all(feature = "transport-sse-server", feature = "axum"))))]
147+
pub use sse_server::AxumSseServer;
148+
149+
#[cfg(all(feature = "transport-sse-server", feature = "actix-web"))]
150+
#[cfg_attr(docsrs, doc(cfg(all(feature = "transport-sse-server", feature = "actix-web"))))]
151+
pub use sse_server::ActixSseServer;
152+
112153
#[cfg(feature = "auth")]
113154
#[cfg_attr(docsrs, doc(cfg(feature = "auth")))]
114155
pub mod auth;
@@ -122,9 +163,25 @@ pub use auth::{AuthError, AuthorizationManager, AuthorizationSession, Authorized
122163
#[cfg(feature = "transport-streamable-http-server-session")]
123164
#[cfg_attr(docsrs, doc(cfg(feature = "transport-streamable-http-server-session")))]
124165
pub mod streamable_http_server;
166+
167+
// Re-export configuration
125168
#[cfg(feature = "transport-streamable-http-server")]
126169
#[cfg_attr(docsrs, doc(cfg(feature = "transport-streamable-http-server")))]
127-
pub use streamable_http_server::tower::{StreamableHttpServerConfig, StreamableHttpService};
170+
pub use streamable_http_server::StreamableHttpServerConfig;
171+
172+
// Re-export the preferred implementation
173+
#[cfg(all(feature = "transport-streamable-http-server", any(feature = "axum", feature = "actix-web")))]
174+
#[cfg_attr(docsrs, doc(cfg(all(feature = "transport-streamable-http-server", any(feature = "axum", feature = "actix-web")))))]
175+
pub use streamable_http_server::StreamableHttpService;
176+
177+
// Re-export explicit types
178+
#[cfg(all(feature = "transport-streamable-http-server", feature = "axum"))]
179+
#[cfg_attr(docsrs, doc(cfg(all(feature = "transport-streamable-http-server", feature = "axum"))))]
180+
pub use streamable_http_server::AxumStreamableHttpService;
181+
182+
#[cfg(all(feature = "transport-streamable-http-server", feature = "actix-web"))]
183+
#[cfg_attr(docsrs, doc(cfg(all(feature = "transport-streamable-http-server", feature = "actix-web"))))]
184+
pub use streamable_http_server::ActixStreamableHttpService;
128185

129186
#[cfg(feature = "transport-streamable-http-client")]
130187
#[cfg_attr(docsrs, doc(cfg(feature = "transport-streamable-http-client")))]

crates/rmcp/src/transport/sse_server/actix_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use crate::{
1818
};
1919

2020
use super::common::{SseServerConfig, SessionId, session_id, DEFAULT_AUTO_PING_INTERVAL};
21+
use crate::transport::common::http_header::HEADER_X_ACCEL_BUFFERING;
2122

2223
type TxStore =
2324
Arc<tokio::sync::RwLock<HashMap<SessionId, tokio::sync::mpsc::Sender<ClientJsonRpcMessage>>>>;
24-
pub type TransportReceiver = ReceiverStream<RxJsonRpcMessage<RoleServer>>;
2525

2626
#[derive(Clone, Debug)]
2727
struct AppData {
@@ -169,7 +169,7 @@ async fn sse_handler(
169169
Ok(HttpResponse::Ok()
170170
.content_type("text/event-stream")
171171
.insert_header(("Cache-Control", "no-cache"))
172-
.insert_header(("X-Accel-Buffering", "no"))
172+
.insert_header((HEADER_X_ACCEL_BUFFERING, "no"))
173173
.streaming(sse_stream))
174174
}
175175

crates/rmcp/src/transport/sse_server/axum_impl.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use super::common::{SseServerConfig, SessionId, session_id, DEFAULT_AUTO_PING_IN
2525

2626
type TxStore =
2727
Arc<tokio::sync::RwLock<HashMap<SessionId, tokio::sync::mpsc::Sender<ClientJsonRpcMessage>>>>;
28-
pub type TransportReceiver = ReceiverStream<RxJsonRpcMessage<RoleServer>>;
2928

3029
#[derive(Clone)]
3130
struct App {

crates/rmcp/src/transport/sse_server/mod.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,56 @@
1+
//! SSE Server Transport Module
2+
//!
3+
//! This module provides Server-Sent Events (SSE) transport implementations for MCP.
4+
//!
5+
//! # Type Export Strategy
6+
//!
7+
//! This module exports framework-specific implementations with explicit names:
8+
//! - `AxumSseServer` - The Axum-based SSE server implementation
9+
//! - `ActixSseServer` - The actix-web-based SSE server implementation
10+
//!
11+
//! For convenience, a type alias `SseServer` is provided that resolves to:
12+
//! - `ActixSseServer` when the `actix-web` feature is enabled
13+
//! - `AxumSseServer` when only the `axum` feature is enabled
14+
//!
15+
//! # Examples
16+
//!
17+
//! Using the convenience alias (recommended for most use cases):
18+
//! ```ignore
19+
//! use rmcp::transport::SseServer;
20+
//! let server = SseServer::serve("127.0.0.1:8080".parse()?).await?;
21+
//! ```
22+
//!
23+
//! Using explicit types (when you need a specific implementation):
24+
//! ```ignore
25+
//! #[cfg(feature = "axum")]
26+
//! use rmcp::transport::AxumSseServer;
27+
//! #[cfg(feature = "axum")]
28+
//! let server = AxumSseServer::serve("127.0.0.1:8080".parse()?).await?;
29+
//! ```
30+
131
#[cfg(feature = "transport-sse-server")]
232
pub mod common;
333

4-
// When only axum is enabled
5-
#[cfg(all(feature = "transport-sse-server", feature = "axum", not(feature = "actix-web")))]
34+
// Axum implementation
35+
#[cfg(all(feature = "transport-sse-server", feature = "axum"))]
636
mod axum_impl;
737

8-
#[cfg(all(feature = "transport-sse-server", feature = "axum", not(feature = "actix-web")))]
9-
pub use axum_impl::*;
38+
#[cfg(all(feature = "transport-sse-server", feature = "axum"))]
39+
pub use axum_impl::SseServer as AxumSseServer;
1040

11-
// When actix-web is enabled (with or without axum)
41+
// Actix-web implementation
1242
#[cfg(all(feature = "transport-sse-server", feature = "actix-web"))]
1343
mod actix_impl;
1444

1545
#[cfg(all(feature = "transport-sse-server", feature = "actix-web"))]
16-
pub use actix_impl::*;
46+
pub use actix_impl::SseServer as ActixSseServer;
1747

18-
// When both are enabled, also provide axum implementation under different name
19-
#[cfg(all(feature = "transport-sse-server", feature = "axum", feature = "actix-web"))]
20-
pub mod axum_impl;
48+
// Convenience type alias
49+
#[cfg(all(feature = "transport-sse-server", feature = "actix-web"))]
50+
pub type SseServer = ActixSseServer;
2151

22-
#[cfg(all(feature = "transport-sse-server", feature = "axum", feature = "actix-web"))]
23-
pub use axum_impl::SseServer as AxumSseServer;
52+
#[cfg(all(feature = "transport-sse-server", feature = "axum", not(feature = "actix-web")))]
53+
pub type SseServer = AxumSseServer;
2454

2555
// Re-export common types when transport-sse-server is enabled
2656
#[cfg(feature = "transport-sse-server")]

0 commit comments

Comments
 (0)