-
Notifications
You must be signed in to change notification settings - Fork 438
Closed
Labels
T-bugBug fixes and error correctionsBug fixes and error corrections
Description
Sorry, I misunderstood how the SDK was implemented.
Describe the bug
Server incorrectly reports "Transport error: disconnected" when sending notifications/resources/updated, even though the client successfully receives the data. This creates false error logs and makes it difficult to monitor actual connection issues.
To Reproduce
Steps to reproduce the behavior:
- Start MCP server
- Client subscribes to "memo://insights" resource
- Server sends periodic ResourceUpdatedNotification (every 2 seconds in example)
- Server logs show "Transport error: disconnected" for each notification
- Client actually receives all notifications successfully
Expected behavior
- Server should not log transport errors when notifications are successfully delivered
- Only actual connection failures should be reported as errors
- Notification mechanism should distinguish between real disconnections and successful deliveries
Example
async fn subscribe(
&self,
SubscribeRequestParam { uri }: SubscribeRequestParam,
ctx: RequestContext<RoleServer>,
) -> Result<(), McpError> {
let peer = ctx.peer;
tokio::spawn(async move {
let span = tracing::info_span!("subscribe", uri = %uri);
let _enter = span.enter();
loop {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
if let Err(e) = peer
.notify_resource_updated(ResourceUpdatedNotificationParam { uri: uri.clone() })
.await
{
// match e {
// rmcp::ServiceError::Transport(e) => {
// if e.to_string().trim() != "disconnected" {
// tracing::error!(error = %e);
// break;
// }
// }
// _ => {
// tracing::error!(error = %e);
// break;
// }
// }
tracing::error!(error = %e);
}
}
});
Ok(())
}Logs
Relevant log excerpts showing false positive errors:
{"timestamp":"2025-03-30T23:52:30.259112Z","level":"INFO","fields":{"message":"received request","id":"3","request":"SubscribeRequest(Request { method: SubscribeRequestMethod, params: SubscribeRequestParam { uri: \"memo://insights\" } })"},"threadId":"ThreadId(24)"}
{"timestamp":"2025-03-30T23:52:30.259129Z","level":"INFO","fields":{"message":"response message","id":"3","result":"EmptyResult(EmptyObject)"},"threadId":"ThreadId(24)"}
{"timestamp":"2025-03-30T23:52:30.259137Z","level":"DEBUG","fields":{"message":"new event","evt":"ToSink(Response(EmptyResult(EmptyObject), Number(3)))"},"threadId":"ThreadId(24)"}
{"timestamp":"2025-03-30T23:52:32.271100Z","level":"DEBUG","fields":{"message":"new event","evt":"ProxyMessage(Notification(ResourceUpdatedNotification(Notification { method: ResourceUpdatedNotificationMethod, params: ResourceUpdatedNotificationParam { uri: \"memo://insights\" } }), Sender { inner: Some(Inner { state: State { is_complete: false, is_closed: false, is_rx_task_set: true, is_tx_task_set: false } }) }))"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:32.271903Z","level":"ERROR","fields":{"error":"Transport error: disconnected"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:34.275746Z","level":"DEBUG","fields":{"message":"new event","evt":"ProxyMessage(Notification(ResourceUpdatedNotification(Notification { method: ResourceUpdatedNotificationMethod, params: ResourceUpdatedNotificationParam { uri: \"memo://insights\" } }), Sender { inner: Some(Inner { state: State { is_complete: false, is_closed: false, is_rx_task_set: true, is_tx_task_set: false } }) }))"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:34.275819Z","level":"ERROR","fields":{"error":"Transport error: disconnected"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:36.278846Z","level":"DEBUG","fields":{"message":"new event","evt":"ProxyMessage(Notification(ResourceUpdatedNotification(Notification { method: ResourceUpdatedNotificationMethod, params: ResourceUpdatedNotificationParam { uri: \"memo://insights\" } }), Sender { inner: Some(Inner { state: State { is_complete: false, is_closed: false, is_rx_task_set: true, is_tx_task_set: false } }) }))"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:36.278922Z","level":"ERROR","fields":{"error":"Transport error: disconnected"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:38.290143Z","level":"DEBUG","fields":{"message":"new event","evt":"ProxyMessage(Notification(ResourceUpdatedNotification(Notification { method: ResourceUpdatedNotificationMethod, params: ResourceUpdatedNotificationParam { uri: \"memo://insights\" } }), Sender { inner: Some(Inner { state: State { is_complete: false, is_closed: false, is_rx_task_set: true, is_tx_task_set: false } }) }))"},"threadId":"ThreadId(23)"}
{"timestamp":"2025-03-30T23:52:38.290234Z","level":"ERROR","fields":{"error":"Transport error: disconnected"},"threadId":"ThreadId(23)"}
{"timestamp":"2025-03-30T23:52:40.306348Z","level":"DEBUG","fields":{"message":"new event","evt":"ProxyMessage(Notification(ResourceUpdatedNotification(Notification { method: ResourceUpdatedNotificationMethod, params: ResourceUpdatedNotificationParam { uri: \"memo://insights\" } }), Sender { inner: Some(Inner { state: State { is_complete: false, is_closed: false, is_rx_task_set: true, is_tx_task_set: false } }) }))"},"threadId":"ThreadId(2)"}
{"timestamp":"2025-03-30T23:52:40.306406Z","level":"ERROR","fields":{"error":"Transport error: disconnected"},"threadId":"ThreadId(2)"}
Additional context
- Issue appears in the notification transport layer implementation
- Current workaround requires ignoring specific transport errors
- Need proper connection state tracking in the notification mechanism
- Affects both SSE and stdio transport implementations
Metadata
Metadata
Assignees
Labels
T-bugBug fixes and error correctionsBug fixes and error corrections