feat!: remove SSE transport support (#562)

SSE transport has been removed from the MCP specification in favor of
streamable HTTP. This removes all SSE-specific transport code:

- Remove `transport-sse-client` and `transport-sse-server` features
- Remove `SseClientTransport` and `SseServer` types
- Remove SSE-specific examples (`counter_sse`, `counter_sse_directly`)
- Migrate auth examples from SSE to streamable HTTP
- Update tests to remove SSE transport usage
- Update documentation

BREAKING CHANGE: The following have been removed:
- `transport-sse-client` feature
- `transport-sse-client-reqwest` feature
- `transport-sse-server` feature
- `SseClientTransport` type
- `SseServer` type
- `sse_client` and `sse_server` modules

Users should migrate to streamable HTTP transport which provides
equivalent functionality. See `StreamableHttpClientTransport` and
`StreamableHttpService` for the replacement APIs.

Ref: https://github.com/modelcontextprotocol/rust-sdk/pull/561#issuecomment-3576551699
This commit is contained in:
adam jones 2025-12-02 01:40:13 +00:00 • committed by GitHub
commit eb5a7f7408
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,7 +3,6 @@ use std::env;
use rmcp::{
ServiceExt,
transport::{
sse_server::{SseServer, SseServerConfig},
stdio,
streamable_http_server::{StreamableHttpService, session::local::LocalSessionManager},
},
@ -12,7 +11,6 @@ use rmcp::{
mod common;
use common::progress_demo::ProgressDemo;
const SSE_BIND_ADDRESS: &str = "127.0.0.1:8000";
const HTTP_BIND_ADDRESS: &str = "127.0.0.1:8001";
#[tokio::main]
@ -24,14 +22,10 @@ async fn main() -> anyhow::Result<()> {
match transport_mode.as_str() {
"stdio" => run_stdio().await,
"sse" => run_sse().await,
"http" | "streamhttp" => run_streamable_http().await,
"all" => run_all_transports().await,
_ => {
eprintln!(
"Usage: {} [stdio|sse|http|all]",
env::args().next().unwrap()
);
eprintln!("Usage: {} [stdio|http|all]", env::args().next().unwrap());
std::process::exit(1);
}
}
@ -47,47 +41,6 @@ async fn run_stdio() -> anyhow::Result<()> {
Ok(())
}
async fn run_sse() -> anyhow::Result<()> {
println!("Running SSE server");
let config = SseServerConfig {
bind: SSE_BIND_ADDRESS.parse()?,
sse_path: "/sse".to_string(),
post_path: "/message".to_string(),
ct: tokio_util::sync::CancellationToken::new(),
sse_keep_alive: None,
};
let (sse_server, router) = SseServer::new(config);
// Start the HTTP server for SSE
let listener = tokio::net::TcpListener::bind(sse_server.config.bind).await?;
let ct = sse_server.config.ct.child_token();
let server = axum::serve(listener, router).with_graceful_shutdown(async move {
ct.cancelled().await;
tracing::info!("SSE server cancelled");
});
tokio::spawn(async move {
if let Err(e) = server.await {
tracing::error!(error = %e, "SSE server shutdown with error");
}
});
// Start the MCP service with SSE transport
let ct = sse_server.with_service(ProgressDemo::new);
tracing::info!(
"Progress Demo SSE server started at http://{}/sse",
SSE_BIND_ADDRESS
);
tracing::info!("Press Ctrl+C to shutdown");
tokio::signal::ctrl_c().await?;
ct.cancel();
Ok(())
}
async fn run_streamable_http() -> anyhow::Result<()> {
println!("Running Streamable HTTP server");
let service = StreamableHttpService::new(
@ -114,18 +67,6 @@ async fn run_streamable_http() -> anyhow::Result<()> {
async fn run_all_transports() -> anyhow::Result<()> {
println!("Running all transports");
// Start SSE server
let sse_config = SseServerConfig {
bind: SSE_BIND_ADDRESS.parse()?,
sse_path: "/sse".to_string(),
post_path: "/message".to_string(),
ct: tokio_util::sync::CancellationToken::new(),
sse_keep_alive: None,
};
let (sse_server, sse_router) = SseServer::new(sse_config);
let sse_listener = tokio::net::TcpListener::bind(sse_server.config.bind).await?;
let sse_ct = sse_server.config.ct.child_token();
// Start Streamable HTTP server
let http_service = StreamableHttpService::new(
@ -136,19 +77,6 @@ async fn run_all_transports() -> anyhow::Result<()> {
let http_router = axum::Router::new().nest_service("/mcp", http_service);
let http_listener = tokio::net::TcpListener::bind(HTTP_BIND_ADDRESS).await?;
// Start SSE HTTP server
let sse_http_server =
axum::serve(sse_listener, sse_router).with_graceful_shutdown(async move {
sse_ct.cancelled().await;
tracing::info!("SSE server cancelled");
});
tokio::spawn(async move {
if let Err(e) = sse_http_server.await {
tracing::error!(error = %e, "SSE server shutdown with error");
}
});
// Start Streamable HTTP server
tokio::spawn(async move {
let _ = axum::serve(http_listener, http_router)
@ -156,11 +84,13 @@ async fn run_all_transports() -> anyhow::Result<()> {
.await;
});
// Start MCP service with SSE
let mcp_sse_ct = sse_server.with_service(ProgressDemo::new);
tracing::info!(
"Progress Demo HTTP server started at http://{}/mcp",
HTTP_BIND_ADDRESS
);
tracing::info!("Press Ctrl+C to shutdown");
tokio::signal::ctrl_c().await?;
mcp_sse_ct.cancel();
Ok(())
}