{"record":{"id":"d4982471d0680d54","repo":"Hmbown/CodeWhale","slug":"mcp-server-server-name-initialize-serverinfo-field-must-be-a","errorCode":null,"errorMessage":"MCP server '{server_name}': initialize serverInfo.{field} must be a string","messagePattern":"MCP server '(.+?)': initialize serverInfo\\.(.+?) must be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mcp/src/stdio_client.rs","lineNumber":454,"sourceCode":"        })?;\n    // Negotiation per spec: we advertise the newest revision and accept any\n    // dated revision we still implement; anything else ends the handshake.\n    if !MCP_SUPPORTED_PROTOCOL_VERSIONS.contains(&protocol_version) {\n        bail!(\n            \"MCP server '{server_name}': unsupported protocol version '{protocol_version}' (supported: {})\",\n            MCP_SUPPORTED_PROTOCOL_VERSIONS.join(\", \")\n        );\n    }\n\n    let server_info = response\n        .get(\"serverInfo\")\n        .and_then(Value::as_object)\n        .with_context(|| {\n            format!(\"MCP server '{server_name}': initialize result omitted serverInfo\")\n        })?;\n    for field in [\"name\", \"version\"] {\n        if !server_info.get(field).is_some_and(Value::is_string) {\n            bail!(\"MCP server '{server_name}': initialize serverInfo.{field} must be a string\");\n        }\n    }\n\n    match response.get(\"capabilities\") {\n        None => Ok(None),\n        Some(Value::Object(capabilities)) => Ok(Some(ServerCapabilities {\n            tools: capabilities.contains_key(\"tools\"),\n            resources: capabilities.contains_key(\"resources\"),\n        })),\n        Some(_) => bail!(\"MCP server '{server_name}': initialize capabilities must be an object\"),\n    }\n}\n\n/// A live connection to one MCP server subprocess.\npub struct ChildProcessMcpClient {\n    server_name: String,\n    capabilities: Option<ServerCapabilities>,\n    connection: Mutex<Connection>,","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/mcp/src/stdio_client.rs#L436-L472","documentation":"During the MCP initialize handshake, stdio_client validates that the child server's initialize result contains a serverInfo object with string-valued `name` and `version` fields. This bail fires when either field is missing or is not a JSON string. The library enforces this because protocol and server identity are recorded for capability negotiation and diagnostics.","triggerScenarios":"Calling spawn_with_timeouts (directly or via connect) against an MCP server whose initialize response has serverInfo missing, null, a non-object, or whose `name`/`version` is absent or a non-string (number, object, etc.).","commonSituations":"Homegrown or non-conformant MCP servers returning malformed serverInfo; servers skipping the spec's serverInfo; proxies or wrappers that rewrite initialize responses and drop or retype fields.","solutions":["Fix the MCP server to return serverInfo with string `name` and `version` in its initialize result, per the MCP spec.","If you control a wrapper/proxy in front of the server, ensure it forwards serverInfo verbatim.","Pin to a known-good server version; check the server's changelog for initialize-result regressions.","Capture raw stdout of the child to inspect the actual initialize JSON it sent."],"exampleFix":"// server before (non-conformant)\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"serverInfo\":{\"name\":42}}}\n// after\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"serverInfo\":{\"name\":\"my-server\",\"version\":\"1.0.0\"}}}","handlingStrategy":"validation","validationCode":"fn server_info_is_valid(init: &serde_json::Value) -> bool {\n    init.get(\"result\").and_then(|r| r.get(\"serverInfo\")).and_then(serde_json::Value::as_object)\n        .map(|si| [\"name\", \"version\"].iter().all(|f| si.get(*f).is_some_and(serde_json::Value::is_string)))\n        .unwrap_or(false)\n}","typeGuard":"fn as_server_info(v: &Value) -> Option<(&str, &str)> {\n    let si = v.get(\"result\")?.get(\"serverInfo\")?.as_object()?;\n    Some((si.get(\"name\")?.as_str()?, si.get(\"version\")?.as_str()?))\n}","tryCatchPattern":"match spawn_with_timeouts(&config, handshake, request_timeout) {\n    Ok(c) => c,\n    Err(e) if e.to_string().contains(\"serverInfo\") => {\n        eprintln!(\"server sent malformed serverInfo; check server version\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Test your server's initialize response against the MCP schema in CI.","Log the raw initialize response when integrating a new server.","Prefer maintained, spec-conformant server implementations.","Wrapper/proxy code must forward serverInfo untouched."],"tags":["mcp","json-schema","handshake"],"backgroundTag":"schema-validation-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}