ultraworkers/claw-code · error · std::io::Error

MCP response for {method} used unsupported jsonrpc version `

Error message

MCP response for {method} used unsupported jsonrpc version `{}`

What it means

`McpStdioProcess::request` (runtime/src/mcp_stdio.rs:1304) validates every JSON-RPC response from the spawned MCP server: `response.jsonrpc` must equal "2.0" exactly. claw always sends "2.0" on requests; a server replying with "1.0", "2", or any other string gets `InvalidData`. Note `jsonrpc` is a required String field on JsonRpcResponse — a response OMITTING it fails serde deserialization earlier, so this error specifically means a wrong explicit value.

Source

Thrown at rust/crates/runtime/src/mcp_stdio.rs:1304

    }

    pub async fn read_response<T: DeserializeOwned>(&mut self) -> io::Result<JsonRpcResponse<T>> {
        self.read_jsonrpc_message().await
    }

    pub async fn request<TParams: Serialize, TResult: DeserializeOwned>(
        &mut self,
        id: JsonRpcId,
        method: impl Into<String>,
        params: Option<TParams>,
    ) -> io::Result<JsonRpcResponse<TResult>> {
        let method = method.into();
        let request = JsonRpcRequest::new(id.clone(), method.clone(), params);
        self.send_request(&request).await?;
        let response = self.read_response().await?;

        if response.jsonrpc != "2.0" {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "MCP response for {method} used unsupported jsonrpc version `{}`",
                    response.jsonrpc
                ),
            ));
        }

        if response.id != id {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "MCP response for {method} used mismatched id: expected {id:?}, got {:?}",
                    response.id
                ),
            ));
        }

View on GitHub (pinned to 08106b0c37)

Solutions

  1. In the server, always serialize responses with "jsonrpc":"2.0" (use the SDK's response type, not hand-built JSON).
  2. Check the exact value in the error message against the server's serialization code.
  3. If using an SDK, upgrade it — old JSON-RPC 1.0 libraries do not emit the field correctly.

Example fix

// before (server)
{"id":1,"result":{}}                                  // no/invalid version -> deserialize fail or this error

// after (server)
{"jsonrpc":"2.0","id":1,"result":{}}
Defensive patterns

Strategy: try-catch

Try / catch

match process.request(id, method, params).await {
    Err(e) if e.kind() == io::ErrorKind::InvalidData
        && e.to_string().contains("unsupported jsonrpc version") => {
        // peer is not spec-compliant: log the version it sent and drop the server
    }
    other => other,
}

Prevention

When it happens

Trigger: A homegrown MCP server echoing JSON-RPC 1.0 style responses ("jsonrpc":"1.0" or version pulled from config); a server deriving the field from the negotiated protocolVersion of initialize; hardcoded "2" without the patch component.

Common situations: Adapting an old JSON-RPC 1.0 service as an MCP server; typos in hand-serialized responses; forks that renamed the constant.

Related errors


AI-assisted analysis of ultraworkers/claw-code@08106b0c37 (2026-08-18). Data as JSON: /api/errors/895e7412a17a98c8. Report an issue: GitHub.