modelcontextprotocol / modelcontextprotocol/python-sdk
ClientDisconnect returns HTTP 500
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 24.3k
- Fork
- 4k
- Merge trung bình
- 1 ngày 1 giờ
- Pull request đã merge (30 ngày)
- 31
Mô tả
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
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:
except Exception as err: # pragma: no cover
logger.exception("Error handling POST request") # ❌ Logs as ERROR
response = self._create_error_response(
f"Error handling POST request: {err}",
HTTPStatus.INTERNAL_SERVER_ERROR, # ❌ Returns 500
INTERNAL_ERROR,
)
await response(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 python3
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Bug Demo", json_response=True)
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
if __name__ == "__main__":
mcp.run(transport="streamable-http")
3. Create test_client_disconnect.py:
#!/usr/bin/env python3
import socket
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 8000))
# Send headers claiming 100KB body
headers = (
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 disconnect
sock.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
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu trong src/mcp/server/streamable_http.py tại StreamableHTTPServerTransport._handle_post_request, quanh trình xử lý exception tổng quát gần các dòng 490–500, và xem xét cách ClientDisconnect đi đến đó. Chạy bản tái hiện socket với body không đầy đủ được cung cấp để quan sát response và logging hiện tại. Được xem là hoàn tất khi việc client ngắt kết nối bình thường không còn tạo ra HTTP 500, traceback ở mức ERROR hoặc cảnh báo 5XX trong production.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- api, backend
- Loại issue
- Lỗi
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 76/100