Kuberwastaken/claurst · error · anyhow::Error
failed to resolve legacy SSE endpoint
Error message
failed to resolve legacy SSE endpoint '{}': {} What it means
For legacy SSE MCP servers, a relative `endpoint` event value is joined onto the base URL with Url::join. This error fires when the join itself fails, meaning the endpoint string from the server cannot be resolved against the base URL (e.g. the join produced no valid URL).
Solutions
- Inspect the server's `endpoint` event output and fix the server/proxy so it advertises a valid endpoint path or absolute URL
- Update or replace the non-compliant MCP server implementation
- Bypass proxies that rewrite SSE handshake events
- Ensure the endpoint string contains only valid URL path/query characters
Defensive patterns
Strategy: try-catch
Try / catch
match connect(cfg).await {
Err(e) if e.to_string().contains("failed to resolve legacy SSE endpoint") => {
// log raw endpoint event, disable or upgrade that server
}
r => r?,
} Prevention
- Keep MCP servers and proxies compliant with the SSE handshake spec
- Test behind reverse proxies for endpoint-rewriting behavior
- Prefer streamable-http transport where supported
When it happens
Trigger: Legacy SSE handshake returns an endpoint event with a malformed relative path that Url::join rejects when combined with the server base URL.
Common situations: Server (or an intermediate proxy) advertises a corrupted endpoint value such as `http://[bad-ipv6/endpoint`; reverse proxy rewriting the SSE endpoint event incorrectly; nonstandard MCP server implementation.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- invalid legacy SSE base URL
- MCP server ' ': legacy SSE POST request failed
- MCP server ' ': failed to read legacy SSE HTTP response body
- MCP server ' ' is configured as ' ' but missing URL
- legacy SSE endpoint event did not include a POST endpoint
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/6370bd9ae3d81cb6.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/mcp/src/lib.rs:426
.get(CONTENT_TYPE)
.and_then(|value| value.to_str().ok())
.map(|value| value.contains("text/event-stream"))
.unwrap_or(false)
}
pub(crate) fn resolve_legacy_endpoint(base_url: &str, endpoint: &str) -> anyhow::Result<String> {
let endpoint = endpoint.trim();
if endpoint.is_empty() {
anyhow::bail!("legacy SSE endpoint event did not include a POST endpoint");
}
if let Ok(url) = url::Url::parse(endpoint) {
return Ok(url.to_string());
}
let base = url::Url::parse(base_url)
.map_err(|e| anyhow::anyhow!("invalid legacy SSE base URL '{}': {}", base_url, e))?;
base.join(endpoint)
.map(|url| url.to_string())
.map_err(|e| anyhow::anyhow!("failed to resolve legacy SSE endpoint '{}': {}", endpoint, e))
}
#[cfg(test)]
pub(super) fn route_incoming_value(
server_name: &str,
value: serde_json::Value,
response_tx: &mpsc::UnboundedSender<JsonRpcResponse>,
notification_tx: &mpsc::UnboundedSender<serde_json::Value>,
) -> anyhow::Result<()> {
let is_response = value.get("id").map(|id| !id.is_null()).unwrap_or(false)
|| value.get("result").is_some()
|| value.get("error").is_some();
if is_response {
let response: JsonRpcResponse = serde_json::from_value(value).map_err(|e| {
anyhow::anyhow!(
"MCP server '{}': failed to parse JSON-RPC response from HTTP transport: {}",
server_name,
View on GitHub (pinned to b0637c97ec)