-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Closed
Description
Initial Checks
- I confirm that I'm using the latest version of MCP Python SDK
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
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-141
async _maybeWritePrimingEvent(res, streamId) {
if (!this._eventStore) {
return;
}
const primingEventId = await this._eventStore.storeEvent(streamId, {});
let primingEvent = `id: ${primingEventId}\ndata: \n\n`; // ← Empty data field
if (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);
await this._maybeWritePrimingEvent(res, streamId); // Sends empty SSE eventClient 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-162
if sse.event == "message":
try:
message = JSONRPCMessage.model_validate_json(sse.data) # ❌ Fails on empty dataSteps to Reproduce
- Set up an MCP server using
@modelcontextprotocol/sdkwithStreamableHTTPServerTransport - 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:
import logging
from mcp.client.streamable_http import StreamableHTTPTransport
# Save original method
original_handle_sse_event = StreamableHTTPTransport._handle_sse_event
# Create patched version
async def patched_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 data
if not sse.data or sse.data.strip() == '':
logging.debug(f"Skipping empty SSE data (event: {sse.event})")
return False
# Call original method for non-empty data
return await original_handle_sse_event(
self, sse, read_stream_writer,
original_request_id, resumption_callback, is_initialization
)
# Apply patch
StreamableHTTPTransport._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
Metadata
Metadata
Assignees
Labels
No labels