StreamableHTTP: a client disconnect while reading the POST body is logged as an exception and answered 500
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 78/100
Hướng nghiên cứu
Bắt đầu trong mcp/server/streamable_http.py tại StreamableHTTPServerTransport._handle_post_request, đặc biệt là dòng body = await request.body() và trình xử lý ngoại lệ tổng quát ngay sau đó. So sánh cách xử lý ngắt kết nối hiện có trong _handle_message được tham chiếu bởi #2064 và #2257. Hoàn thành khi ClientDisconnect được xử lý mà không có stack trace lỗi hoặc phản hồi 500, đồng thời phạm vi kiểm thử hồi quy xác minh hành vi này.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Initial Checks
- I confirm that I'm using the newest release of my line (the latest 2.x, or the latest 1.x if I'm still on v1)
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Release line
2.x (current stable), and the same on 1.28.1
Description
StreamableHTTPServerTransport._handle_post_request reads the request body inside its blanket except Exception. When the client goes away before the body arrives, await request.body() raises starlette.requests.ClientDisconnect, the transport logs it with logger.exception("Error handling POST request") and answers 500. That is a normal network event on a public MCP endpoint (mobile clients, proxies with short timeouts, health probes), and it lands as an unhandled server error with a stack trace in every log aggregator. #2064 / #2257 handled the disconnect in _handle_message; this is the earlier point, in streamable_http.py (the body = await request.body() line and the except Exception as err below it). The SSE transport has no handling for it either.
Example Code
import asyncio
import importlib.metadata as md
import logging
from mcp.server.streamable_http import StreamableHTTPServerTransport
records = []
class Capture(logging.Handler):
def emit(self, record):
records.append(record)
logging.getLogger("mcp").addHandler(Capture())
logging.getLogger("mcp").setLevel(logging.DEBUG)
async def main():
transport = StreamableHTTPServerTransport(mcp_session_id=None)
scope = {
"type": "http", "method": "POST", "path": "/mcp", "query_string": b"", "headers": [
(b"content-type", b"application/json"),
(b"accept", b"application/json, text/event-stream"),
(b"content-length", b"58"),
],
}
async def receive(): # the client went away before sending its body
return {"type": "http.disconnect"}
sent = []
async def send(message):
sent.append(message)
async with transport.connect():
try:
await asyncio.wait_for(transport.handle_request(scope, receive, send), timeout=5)
except asyncio.TimeoutError:
print("handle_request did not return within 5s")
status = next((m["status"] for m in sent if m["type"] == "http.response.start"), None)
print(f"mcp {md.version('mcp')}: response status = {status}")
for r in records:
if r.levelno >= logging.ERROR:
print(f" logged {r.levelname} by {r.name}: {r.getMessage()} | exc: {type(r.exc_info[1]).__name__ if r.exc_info else None}")
try:
asyncio.run(asyncio.wait_for(main(), timeout=15))
except asyncio.TimeoutError:
print("main did not finish within 15s")
Output on 1.28.1 and 2.1.1:
mcp 2.1.1: response status = 500
logged ERROR by mcp.server.streamable_http: Error handling POST request | exc: ClientDisconnect
(The script caps handle_request at 5 s because the stub send / receive is not a real ASGI server; the 500 and the log line are sent before that.)
Expected: ClientDisconnect caught before the generic handler, logged at debug or info, and no response attempted, since there is nobody to answer.
Python & MCP Python SDK
Python 3.12.13, mcp 1.28.1 and 2.1.1, starlette 1.3.1, macOS
- Ngôn ngữ chính
- Python
- Star
- 24.3k
- Fork
- 4k
- Merge trung bình
- 1 ngày 19 phút
- Pull request đã merge (30 ngày)
- 29
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.
Issue khác của modelcontextprotocol/python-sdk
-
Streamable HTTP client logs a WARNING for valid 202 Accepted on session termination (DELETE) Đang mởv1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
modelcontextprotocol/python-sdk#3546 · 5 bình luận ·
-
v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
modelcontextprotocol/python-sdk#3545 · 1 bình luận ·
-
v1 v2
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 91/100
modelcontextprotocol/python-sdk#3508 · 2 bình luận ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 64/100
modelcontextprotocol/python-sdk#3504 ·
-
v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
modelcontextprotocol/python-sdk#3492 · 1 bình luận ·
Tất cả issue của modelcontextprotocol/python-sdk
Issue tương tự
-
documentation help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100
simonw/sqlite-utils#872 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100