Hmbown/CodeWhale · error · anyhow::Error
MCP server ' ' initialize result omitted protocolVersion
Error message
MCP server '{}' initialize result omitted protocolVersion What it means
During MCP initialization, the client requires the server's initialize result to include a protocolVersion string so a version can be negotiated. If the field is absent (or not a string), the handshake fails — without it the client cannot know which protocol revision the server speaks and cannot safely proceed.
Solutions
- Upgrade the MCP server to a version that returns protocolVersion in its initialize result.
- Verify you are pointing at the correct MCP endpoint (right port/path, actual MCP server behind any proxy).
- Inspect the raw initialize response (log the JSON) to confirm whether the field is missing or mistyped.
- If you own the server, add protocolVersion from MCP_SUPPORTED_PROTOCOL_VERSIONS to the initialize result.
Example fix
// before (server-side)
json!({ "capabilities": {...} })
// after
json!({ "protocolVersion": "2025-06-18", "capabilities": {...} }) Defensive patterns
Strategy: try-catch
Validate before calling
// verify the endpoint answers a real MCP initialize before full connect
let probe = raw_initialize(endpoint).await?;
if probe.get("protocolVersion").and_then(|v| v.as_str()).is_none() {
return Err("endpoint is not a conformant MCP server");
} Type guard
fn has_protocol_version(result: &serde_json::Value) -> bool {
result.get("protocolVersion").and_then(|v| v.as_str()).is_some()
} Try / catch
match client.initialize().await {
Err(e) if e.to_string().contains("omitted protocolVersion") => {
log_raw_initialize_response();
Err(anyhow!("server is not MCP-conformant; upgrade the server"))
}
other => other,
} Prevention
- Conformance-test any custom MCP server's initialize response
- Ensure proxies don't rewrite or strip JSON-RPC response fields
- Pin server versions known to implement the MCP handshake
- Log raw initialize payloads in debug mode for fast diagnosis
When it happens
Trigger: Server's initialize response JSON lacks a "protocolVersion" key, has it as null, or as a non-string value (number/object); happens when connecting to a non-conformant or partially implemented MCP server.
Common situations: Connecting to a home-grown or beta MCP server that skips the field, an HTTP proxy stripping/rewriting the JSON body, pointing the client at an endpoint that isn't actually MCP (wrong port/path), or a server implementing an older pre-versioning draft of the spec.
Related errors
- MCP server ' ': unsupported protocol version ' '…
- MCP server ' ' negotiated unsupported protocol version ' '…
- MCP SSE server sent a message before declaring its endpoint
- Codewhale stream-json contained an unknown event type
- JSON-RPC line exceeded the
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d53972d1513e38bb.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp.rs:1894
}
}
}))
.await?;
let response = self.recv(init_id).await?;
let result = response_result(
&response,
"initialize",
self.config.reviewed_plugin.is_some(),
)?;
// Per spec, a server that cannot speak the advertised revision answers
// with one it does support. Accept any dated revision we still
// implement; anything else ends the handshake.
let negotiated = result
.and_then(|result| result.get("protocolVersion"))
.and_then(|version| version.as_str())
.ok_or_else(|| {
anyhow::anyhow!(
"MCP server '{}' initialize result omitted protocolVersion",
self.name
)
})?;
anyhow::ensure!(
MCP_SUPPORTED_PROTOCOL_VERSIONS.contains(&negotiated),
"MCP server '{}' negotiated unsupported protocol version '{negotiated}' (supported: {})",
self.name,
MCP_SUPPORTED_PROTOCOL_VERSIONS.join(", ")
);
self.transport.set_protocol_version(negotiated);
self.server_capabilities = McpServerCapabilities::from_initialize_response(&response);
// Send initialized notification (no id, no response expected)
self.send(serde_json::json!({
"jsonrpc": "2.0",
"method": "notifications/initialized"
}))View on GitHub (pinned to 73e0f67d83)