Kuberwastaken/claurst · error
MCP server ' ': timed out waiting for legacy SSE endpoint…
Error message
MCP server '{}': timed out waiting for legacy SSE endpoint event What it means
Endpoint discovery for the legacy SSE transport exceeded its hard 10-second timeout: no endpoint (or error) event arrived on the discovery channel within tokio::time::timeout(Duration::from_secs(10)). The stream may still be alive but silent — the server never announced its POST endpoint in time.
Solutions
- Check server latency; slow servers may not announce the endpoint within 10s
- Verify the server actually sends the legacy SSE endpoint event
- Retry the connection or switch to streamable-http transport
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:327 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/1410a8574297a4e9.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:327
.await;
if let Err(e) = result {
tracing::warn!(server = %server_name, error = %e, "Legacy SSE stream closed with error");
if let Some(tx) = lock_recover(&endpoint_tx_for_task).take() {
let _ = tx.send(Err(anyhow::anyhow!(e.to_string())));
}
} else if let Some(tx) = lock_recover(&endpoint_tx_for_task).take() {
let _ = tx.send(Err(anyhow::anyhow!(
"legacy SSE stream closed before announcing endpoint"
)));
}
});
lock_recover(&self.background_tasks).push(task);
let endpoint = tokio::time::timeout(std::time::Duration::from_secs(10), endpoint_rx)
.await
.map_err(|_| {
anyhow::anyhow!(
"MCP server '{}': timed out waiting for legacy SSE endpoint event",
self.server_name
)
})?
.map_err(|_| {
anyhow::anyhow!(
"MCP server '{}': legacy SSE stream ended before endpoint discovery",
self.server_name
)
})??;
*lock_recover(&self.post_endpoint) = Some(endpoint);
Ok(())
}
}
impl Drop for LegacySseRmcpTransport {
fn drop(&mut self) {
// Some upper-layer paths drop the backend instead of calling close()View on GitHub (pinned to b0637c97ec)