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

  1. Check server latency; slow servers may not announce the endpoint within 10s
  2. Verify the server actually sends the legacy SSE endpoint event
  3. 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


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)