Initial Checks
Description
Summary
The MCP Python client crashes when receiving empty SSE (Server-Sent Events) data from the MCP server, which is sent as part of the resumability priming event. This causes a ValidationError when trying to parse empty strings as JSON-RPC messages.
Error Message
Error parsing SSE message
pydantic_core._pydantic_core.ValidationError: 1 validation error for JSONRPCMessage
Invalid JSON: EOF while parsing a value at line 1 column 0 [type=json_invalid, input_value='', input_type=str]
Root Cause Analysis
Server Behavior (Expected)
The MCP Server SDK (@modelcontextprotocol/sdk) intentionally sends empty SSE events as "priming events" for resumability support:
File: node_modules/@modelcontextprotocol/sdk/dist/esm/server/streamableHttp.js
// Lines 131-141async_maybeWritePrimingEvent(res,streamId){if(!this._eventStore){return;}constprimingEventId=awaitthis._eventStore.storeEvent(streamId,{});letprimingEvent=`id: ${primingEventId}\ndata: \n\n`;// ← Empty data fieldif(this._retryInterval!==undefined){primingEvent=`id: ${primingEventId}\nretry: ${this._retryInterval}\ndata: \n\n`;}res.write(primingEvent);}This is called during POST request handling (line 441):
res.writeHead(200,headers);awaitthis._maybeWritePrimingEvent(res,streamId);// Sends empty SSE event
Client Behavior (Buggy)
The Python client attempts to parse ALL SSE data as JSON without checking if it's empty first:
File: mcp/client/streamable_http.py
# Lines 160-162ifsse.event=="message":
try:
message=JSONRPCMessage.model_validate_json(sse.data) # ❌ Fails on empty data
Steps to Reproduce
- Set up an MCP server using
@modelcontextprotocol/sdk with StreamableHTTPServerTransport - Enable event store for resumability:
- Connect a Python MCP client using
streamablehttp_client - Send any request (e.g.,
list_tools()) - Observe the ValidationError when the priming event is received
Workaround
Until this is fixed in the SDK, users can apply a patch:
importloggingfrommcp.client.streamable_httpimportStreamableHTTPTransport# Save original methodoriginal_handle_sse_event=StreamableHTTPTransport._handle_sse_event# Create patched versionasyncdefpatched_handle_sse_event(self, sse, read_stream_writer, original_request_id=None, resumption_callback=None, is_initialization=False):
"""Patched version that skips empty SSE data."""# Skip empty dataifnotsse.dataorsse.data.strip() =='':
logging.debug(f"Skipping empty SSE data (event: {sse.event})")
returnFalse# Call original method for non-empty datareturnawaitoriginal_handle_sse_event(
self, sse, read_stream_writer, original_request_id, resumption_callback, is_initialization
)
# Apply patchStreamableHTTPTransport._handle_sse_event=patched_handle_sse_eventPython & MCP Python SDK
For Client (I'm using python-sdk):1.22.0
For Server (I'm using ts-sdk): 1.23.0
Initial Checks
Description
Summary
The MCP Python client crashes when receiving empty SSE (Server-Sent Events) data from the MCP server, which is sent as part of the resumability priming event. This causes a
ValidationErrorwhen trying to parse empty strings as JSON-RPC messages.Error Message
Root Cause Analysis
Server Behavior (Expected)
The MCP Server SDK (
@modelcontextprotocol/sdk) intentionally sends empty SSE events as "priming events" for resumability support:File:
node_modules/@modelcontextprotocol/sdk/dist/esm/server/streamableHttp.jsThis is called during POST request handling (line 441):
Client Behavior (Buggy)
The Python client attempts to parse ALL SSE data as JSON without checking if it's empty first:
File:
mcp/client/streamable_http.pySteps to Reproduce
@modelcontextprotocol/sdkwithStreamableHTTPServerTransportstreamablehttp_clientlist_tools())Workaround
Until this is fixed in the SDK, users can apply a patch:
Python & MCP Python SDK