Skip to content

streamable HTTP client parses zstd-compressed JSON response bytes as JSON #2649

@daryllimyt

Description

@daryllimyt

Summary

The Python SDK streamable HTTP client appears to parse compressed response bytes directly as JSON when an MCP server returns Content-Encoding: zstd.

We hit this while using the Python MCP/FastMCP client path as part of an agent runtime built around the Claude Code SDK. The user-visible failure is that Claude Code agent initialization times out while MCP tool discovery is happening.

The hosted Datadog MCP server reproduces the issue:

https://mcp.datadoghq.eu/api/unstable/mcp-server/mcp?toolsets=core,security

Environment

  • Python: 3.12
  • MCP Python SDK: 1.26.0
  • FastMCP: 3.2.0
  • Transport: Streamable HTTP
  • Runtime: Claude Code SDK
  • Remote MCP server: Datadog MCP

What Happens

During initialization / tool discovery against the Datadog MCP server, the streamable HTTP client logs:

Error parsing JSON response
Traceback (most recent call last):
  File ".../site-packages/mcp/client/streamable_http.py", line 385, in _handle_json_response
    message = JSONRPCMessage.model_validate_json(content)
...
pydantic_core._pydantic_core.ValidationError: 1 validation error for JSONRPCMessage
  Invalid JSON: expected value at line 1 column 1
  [type=json_invalid, input_value=b'(\xb5/\xfdd...', input_type=bytes]

28 b5 2f fd is the zstd frame magic number, so this looks like compressed JSON bytes being passed directly to the JSON-RPC parser.

The higher-level symptom is:

Control request timeout: initialize

Expected Behavior

The streamable HTTP transport should either:

  1. decode the response according to Content-Encoding before calling JSONRPCMessage.model_validate_json(...), or
  2. avoid advertising encodings it cannot decode, or
  3. document that MCP HTTP clients should force Accept-Encoding: identity.

Workaround

Forcing identity encoding avoids the issue:

Accept-Encoding: identity

Why This Matters

This is server-dependent. In our testing, Datadog MCP reproduces the failure, while another hosted MCP server, Linear MCP, does not. The difference appears to be whether the server returns compressed response bytes on the streamable HTTP JSON response path.

So this looks like a general streamable HTTP transport issue that only appears with servers returning compressed JSON.

Relevant Code

In mcp/client/streamable_http.py:

content = await response.aread()
message = JSONRPCMessage.model_validate_json(content)

There does not appear to be a decode step based on Content-Encoding before JSON parsing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions