FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(client): catch httpx transport errors in streamable HTTP post_writer by devansh-dek · Pull Request #3025 · modelcontextprotocol/python-sdk · GitHub

Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (2) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
25 changes: 21 additions & 4 deletions src/mcp/client/streamable_http.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -479,10 +479,27 @@ async def _handle_message(session_message: SessionMessage) -> None:
)

async def handle_request_async():
if is_resumption:
await self._handle_resumption_request(ctx)
else:
await self._handle_post_request(ctx)
try:
if is_resumption:
await self._handle_resumption_request(ctx)
else:
await self._handle_post_request(ctx)
except httpx.HTTPError as exc:
# Letting this escape into `tg` would crash the outer task group
# from a different task than the one yielding the streams,
# producing an uncatchable cancel-scope RuntimeError instead of
# a connect error at the caller.
logger.exception("Transport error handling request")
if isinstance(message, JSONRPCRequest):
error_data = ErrorData(
code=INTERNAL_ERROR,
message=f"Transport error: {exc}",
)
error_msg = SessionMessage(
JSONRPCError(jsonrpc="2.0", id=message.id, error=error_data)
)
with contextlib.suppress(anyio.BrokenResourceError, anyio.ClosedResourceError):
await read_stream_writer.send(error_msg)

# If this is a request, start a new task to handle it
if isinstance(message, JSONRPCRequest):
Expand Down
27 changes: 27 additions & 0 deletions tests/issues/test_915_streamable_http_unreachable.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Regression test for issue #915.

When a streamable HTTP MCP server is unreachable, httpx transport errors must
complete the pending JSON-RPC waiter instead of escaping into the outer task
group (which surfaces as an uncatchable cancel-scope RuntimeError).
"""

from __future__ import annotations

import anyio
import pytest
from mcp_types import INTERNAL_ERROR

from mcp.client.session_group import ClientSessionGroup, StreamableHttpParameters
from mcp.shared.exceptions import MCPError


@pytest.mark.anyio
async def test_unreachable_streamable_http_server_raises_catchable_error() -> None:
async with ClientSessionGroup() as group:
server_params = StreamableHttpParameters(url="http://127.0.0.1:1/mcp/")
with anyio.fail_after(10):
with pytest.raises(MCPError) as exc_info:
await group.connect_to_server(server_params)

assert exc_info.value.code == INTERNAL_ERROR
assert "Transport error" in exc_info.value.message
Loading

Back | FazBrowse Home | New Git URL