-
Notifications
You must be signed in to change notification settings - Fork 579
Expand file tree
/
Copy pathsubscriptions_streamhttp.rs
More file actions
83 lines (74 loc) · 2.68 KB
/
Copy pathsubscriptions_streamhttp.rs
File metadata and controls
83 lines (74 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::{borrow::Cow, time::Duration};
use rmcp::{
ErrorData, ServerHandler,
model::{ProtocolVersion, ServerCapabilities, ServerInfo, SubscriptionFilter},
service::SubscriptionContext,
transport::streamable_http_server::{
StreamableHttpServerConfig, StreamableHttpService, session::local::LocalSessionManager,
},
};
use tokio_util::sync::CancellationToken;
#[derive(Clone)]
struct SubscriptionServer;
impl ServerHandler for SubscriptionServer {
fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]> {
Cow::Borrowed(&[ProtocolVersion::V_2026_07_28])
}
fn get_info(&self) -> ServerInfo {
ServerInfo::new(
ServerCapabilities::builder()
.enable_tools()
.enable_tool_list_changed()
.build(),
)
}
fn accepted_subscription_filter(
&self,
requested: &SubscriptionFilter,
) -> Option<SubscriptionFilter> {
Some(requested.supported_by(&self.get_info().capabilities))
}
async fn listen(&self, context: SubscriptionContext) -> Result<(), ErrorData> {
loop {
tokio::select! {
() = context.cancelled() => return Ok(()),
() = tokio::time::sleep(Duration::from_secs(2)) => {
context
.sink()
.notify_tool_list_changed()
.await
.map_err(|error| {
ErrorData::internal_error(error.to_string(), None)
})?;
}
}
}
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()),
)
.init();
let cancellation_token = CancellationToken::new();
let service: StreamableHttpService<SubscriptionServer, LocalSessionManager> =
StreamableHttpService::new(
|| Ok(SubscriptionServer),
Default::default(),
StreamableHttpServerConfig::default()
.with_legacy_session_mode(false)
.with_sse_keep_alive(Some(Duration::from_secs(10)))
.with_cancellation_token(cancellation_token.child_token()),
);
let router = axum::Router::new().nest_service("/mcp", service);
let listener = tokio::net::TcpListener::bind("127.0.0.1:8000").await?;
axum::serve(listener, router)
.with_graceful_shutdown(async move {
let _ = tokio::signal::ctrl_c().await;
cancellation_token.cancel();
})
.await?;
Ok(())
}