Initial Checks
Description
StreamableHTTPServerTransport._handle_post_request in mcp/server/streamable_http.py incorrectly handles starlette.requests.ClientDisconnect exceptions.
Current behavior:
- Returns HTTP 500 (Internal Server Error)
- Logs as ERROR with full traceback
- Triggers production 5XX alerts
When This Occurs
ClientDisconnect happens during normal operations:
- Network timeouts
- User cancels request
- Load balancer timeouts
- Mobile client network interruptions
These are client-side events, not server failures.
Root Cause
File:src/mcp/server/streamable_http.py
Line: ~490-500
The broad except Exception handler catches ClientDisconnect and returns 500:
exceptExceptionaserr: # pragma: no coverlogger.exception("Error handling POST request") # ❌ Logs as ERRORresponse=self._create_error_response(
f"Error handling POST request: {err}",
HTTPStatus.INTERNAL_SERVER_ERROR, # ❌ Returns 500INTERNAL_ERROR,
)
awaitresponse(scope, receive, send)Example Code
Reproduction
Steps
1. Install MCP SDK:
python3 -m venv venv
source venv/bin/activate
pip install mcp
2. Create minimal_mcp_server.py based on the documentation:
#!/usr/bin/env python3frommcp.server.fastmcpimportFastMCPmcp=FastMCP("Bug Demo", json_response=True)
@mcp.tool()defadd(a: int, b: int) ->int:
"""Add two numbers"""returna+bif__name__=="__main__":
mcp.run(transport="streamable-http")3. Create test_client_disconnect.py:
#!/usr/bin/env python3importsocketimporttimesock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 8000))
# Send headers claiming 100KB bodyheaders= (
b"POST /mcp HTTP/1.1\r\n"b"Host: localhost\r\n"b"Content-Type: application/json\r\n"b"Content-Length: 100000\r\n"b"Accept: application/json, text/event-stream\r\n"b"\r\n"
)
sock.send(headers)
# Send partial body then disconnectsock.send(b'{"jsonrpc": "2.0", "method": "initialize", "params": {')
time.sleep(0.05)
sock.close()
print("✓ Client disconnect simulated")4. Run:
Terminal 1
python minimal_mcp_server.py
Terminal 2
python test_client_disconnect.py
5. Observe the bug in Terminal 1:
Error handling POST request
Traceback (most recent call last):
File ".../mcp/server/streamable_http.py", line 351, in _handle_post_request
body = await request.body()
^^^^^^^^^^^^^^^^^^^^
File ".../starlette/requests.py", line 243, in body
async for chunk in self.stream():
File ".../starlette/requests.py", line 237, in stream
raise ClientDisconnect()
starlette.requests.ClientDisconnect
Python & MCP Python SDK
Python 3.12.9, MCP Python SDK v1.21.2
Initial Checks
Description
StreamableHTTPServerTransport._handle_post_requestinmcp/server/streamable_http.pyincorrectly handlesstarlette.requests.ClientDisconnectexceptions.Current behavior:
When This Occurs
ClientDisconnect happens during normal operations:
These are client-side events, not server failures.
Root Cause
File:
src/mcp/server/streamable_http.pyLine: ~490-500
The broad
except Exceptionhandler catchesClientDisconnectand returns 500:Example Code
Reproduction
Steps
1. Install MCP SDK:
python3 -m venv venv
source venv/bin/activate
pip install mcp
2. Create
minimal_mcp_server.pybased on the documentation:3. Create
test_client_disconnect.py:4. Run:
Terminal 1
python minimal_mcp_server.pyTerminal 2
python test_client_disconnect.py5. Observe the bug in Terminal 1:
Python & MCP Python SDK