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

  1. Upgrade the MCP server to a version that returns protocolVersion in its initialize result.
  2. Verify you are pointing at the correct MCP endpoint (right port/path, actual MCP server behind any proxy).
  3. Inspect the raw initialize response (log the JSON) to confirm whether the field is missing or mistyped.
  4. 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

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


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)