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:
parent
3dee024325
commit
eb5a7f7408
3 changed files with 164 additions and 1688 deletions
|
|
@ -11,9 +11,9 @@ use rmcp::{
|
|||
ServiceExt,
|
||||
model::ClientInfo,
|
||||
transport::{
|
||||
SseClientTransport,
|
||||
StreamableHttpClientTransport,
|
||||
auth::{AuthClient, OAuthState},
|
||||
sse_client::SseClientConfig,
|
||||
streamable_http_client::StreamableHttpClientTransportConfig,
|
||||
},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
|
@ -25,7 +25,6 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|||
|
||||
const MCP_SERVER_URL: &str = "http://localhost:3000/mcp";
|
||||
const MCP_REDIRECT_URI: &str = "http://localhost:8080/callback";
|
||||
const MCP_SSE_URL: &str = "http://localhost:3000/mcp/sse";
|
||||
const CALLBACK_PORT: u16 = 8080;
|
||||
const CALLBACK_HTML: &str = include_str!("callback.html");
|
||||
|
||||
|
|
@ -150,14 +149,10 @@ async fn main() -> Result<()> {
|
|||
.into_authorization_manager()
|
||||
.ok_or_else(|| anyhow::anyhow!("Failed to get authorization manager"))?;
|
||||
let client = AuthClient::new(reqwest::Client::default(), am);
|
||||
let transport = SseClientTransport::start_with_client(
|
||||
let transport = StreamableHttpClientTransport::with_client(
|
||||
client,
|
||||
SseClientConfig {
|
||||
sse_endpoint: MCP_SSE_URL.into(),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
StreamableHttpClientTransportConfig::with_uri(MCP_SERVER_URL),
|
||||
);
|
||||
|
||||
// Create client and connect to MCP server
|
||||
let client_service = ClientInfo::default();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rmcp::{
|
|||
ProgressNotificationParam,
|
||||
},
|
||||
service::{NotificationContext, RoleClient},
|
||||
transport::{SseClientTransport, StreamableHttpClientTransport, TokioChildProcess},
|
||||
transport::{StreamableHttpClientTransport, TokioChildProcess},
|
||||
};
|
||||
use tokio::{process::Command, time::sleep};
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
|
@ -20,7 +20,6 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|||
#[derive(Debug, Clone, ValueEnum)]
|
||||
enum TransportType {
|
||||
Stdio,
|
||||
Sse,
|
||||
Http,
|
||||
All,
|
||||
}
|
||||
|
|
@ -37,10 +36,6 @@ struct Args {
|
|||
#[arg(short, long, default_value_t = 10)]
|
||||
records: u32,
|
||||
|
||||
/// SSE server URL
|
||||
#[arg(long, default_value = "http://127.0.0.1:8000/sse")]
|
||||
sse_url: String,
|
||||
|
||||
/// HTTP server URL
|
||||
#[arg(long, default_value = "http://127.0.0.1:8001/mcp")]
|
||||
http_url: String,
|
||||
|
|
@ -203,59 +198,7 @@ async fn test_stdio_transport(records: u32) -> Result<()> {
|
|||
tracing::info!("STDIO transport test completed successfully!");
|
||||
Ok(())
|
||||
}
|
||||
// Test SSE transport, must run the server with `cargo run --example servers_progress_demo -- sse` in the servers directory
|
||||
async fn test_sse_transport(sse_url: &str, records: u32) -> Result<()> {
|
||||
tracing::info!("Testing SSE Transport");
|
||||
tracing::info!("=========================");
|
||||
tracing::info!("SSE URL: {}", sse_url);
|
||||
|
||||
// Wait a bit for server to be ready
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
|
||||
let transport = SseClientTransport::start(sse_url).await?;
|
||||
|
||||
// Create progress-aware client handler
|
||||
let client_handler = ProgressAwareClient::new();
|
||||
client_handler.start_tracking();
|
||||
let client_handler_clone = client_handler.clone();
|
||||
|
||||
let client = client_handler.serve(transport).await.inspect_err(|e| {
|
||||
tracing::error!("SSE client error: {:?}", e);
|
||||
})?;
|
||||
|
||||
// Initialize
|
||||
let server_info = client.peer_info();
|
||||
if let Some(info) = server_info {
|
||||
tracing::info!("Connected to server: {:?}", info.server_info.name);
|
||||
}
|
||||
|
||||
// List tools
|
||||
let tools = client.list_tools(Default::default()).await?;
|
||||
tracing::info!(
|
||||
"Available tools: {:?}",
|
||||
tools.tools.iter().map(|t| &t.name).collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// Call stream processor tool
|
||||
tracing::info!("Starting to process {} records...", records);
|
||||
let tool_result = client
|
||||
.call_tool(CallToolRequestParam {
|
||||
name: "stream_processor".into(),
|
||||
arguments: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
if let Some(content) = tool_result.content.first() {
|
||||
if let Some(text) = content.as_text() {
|
||||
tracing::info!("Processing completed: {}", text.text);
|
||||
}
|
||||
}
|
||||
|
||||
client.cancel().await?;
|
||||
client_handler_clone.stop_tracking();
|
||||
tracing::info!("SSE transport test completed successfully!");
|
||||
Ok(())
|
||||
}
|
||||
// Test HTTP transport, must run the server with `cargo run --example servers_progress_demo -- http` in the servers directory
|
||||
async fn test_http_transport(http_url: &str, records: u32) -> Result<()> {
|
||||
tracing::info!("Testing HTTP Streaming Transport");
|
||||
|
|
@ -316,13 +259,6 @@ async fn run_single_test(transport_type: &TransportType, args: &Args) -> Result<
|
|||
test_stdio_transport(args.records).await?;
|
||||
Ok(true)
|
||||
}
|
||||
TransportType::Sse => match test_sse_transport(&args.sse_url, args.records).await {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => {
|
||||
tracing::error!("SSE test failed: {}", e);
|
||||
Ok(false)
|
||||
}
|
||||
},
|
||||
TransportType::Http => match test_http_transport(&args.http_url, args.records).await {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => {
|
||||
|
|
@ -357,11 +293,7 @@ async fn main() -> Result<()> {
|
|||
// Test all transport types
|
||||
let mut results = std::collections::HashMap::new();
|
||||
|
||||
for transport_type in [
|
||||
TransportType::Stdio,
|
||||
TransportType::Sse,
|
||||
TransportType::Http,
|
||||
] {
|
||||
for transport_type in [TransportType::Stdio, TransportType::Http] {
|
||||
let transport_name = format!("{:?}", transport_type).to_uppercase();
|
||||
tracing::info!("\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use rmcp::{
|
||||
ServiceExt,
|
||||
model::{CallToolRequestParam, ClientCapabilities, ClientInfo, Implementation},
|
||||
transport::SseClientTransport,
|
||||
};
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Initialize logging
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| format!("info,{}=debug", env!("CARGO_CRATE_NAME")).into()),
|
||||
)
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
let transport = SseClientTransport::start("http://localhost:8000/sse").await?;
|
||||
let client_info = ClientInfo {
|
||||
protocol_version: Default::default(),
|
||||
capabilities: ClientCapabilities::default(),
|
||||
client_info: Implementation {
|
||||
name: "test sse client".to_string(),
|
||||
title: None,
|
||||
version: "0.0.1".to_string(),
|
||||
website_url: None,
|
||||
icons: None,
|
||||
},
|
||||
};
|
||||
let client = client_info.serve(transport).await.inspect_err(|e| {
|
||||
tracing::error!("client error: {:?}", e);
|
||||
})?;
|
||||
|
||||
// Initialize
|
||||
let server_info = client.peer_info();
|
||||
tracing::info!("Connected to server: {server_info:#?}");
|
||||
|
||||
// List tools
|
||||
let tools = client.list_tools(Default::default()).await?;
|
||||
tracing::info!("Available tools: {tools:#?}");
|
||||
|
||||
let tool_result = client
|
||||
.call_tool(CallToolRequestParam {
|
||||
name: "increment".into(),
|
||||
arguments: serde_json::json!({}).as_object().cloned(),
|
||||
})
|
||||
.await?;
|
||||
tracing::info!("Tool result: {tool_result:#?}");
|
||||
client.cancel().await?;
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in a new issue