Skip to content

Commit e661927

Browse files
committed
Surface streamable HTTP connection errors
1 parent 2472563 commit e661927

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

src/mcp/client/streamable_http.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,19 @@ async def _handle_message(session_message: SessionMessage) -> None:
468468
)
469469

470470
async def handle_request_async():
471-
if is_resumption:
472-
await self._handle_resumption_request(ctx)
473-
else:
474-
await self._handle_post_request(ctx)
471+
try:
472+
if is_resumption:
473+
await self._handle_resumption_request(ctx)
474+
else:
475+
await self._handle_post_request(ctx)
476+
except Exception as exc:
477+
logger.debug("Error handling request", exc_info=True)
478+
if isinstance(message, JSONRPCRequest):
479+
error_data = ErrorData(code=INTERNAL_ERROR, message=f"Transport error: {exc}")
480+
error_msg = SessionMessage(JSONRPCError(jsonrpc="2.0", id=message.id, error=error_data))
481+
await ctx.read_stream_writer.send(error_msg)
482+
else:
483+
raise
475484

476485
# If this is a request, start a new task to handle it
477486
if isinstance(message, JSONRPCRequest):

tests/client/test_session_group.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,25 @@ async def test_client_session_group_disconnect_non_existent_server():
278278
await group.disconnect_from_server(session)
279279

280280

281+
@pytest.mark.anyio
282+
async def test_client_session_group_streamable_http_connection_error_surfaces() -> None:
283+
async def fail_request(request: httpx.Request) -> httpx.Response:
284+
raise httpx.ConnectError("offline", request=request)
285+
286+
http_client = httpx.AsyncClient(transport=httpx.MockTransport(fail_request))
287+
288+
with mock.patch("mcp.client.session_group.create_mcp_http_client", return_value=http_client):
289+
async with ClientSessionGroup() as group:
290+
with pytest.raises(MCPError) as excinfo:
291+
await group.connect_to_server(
292+
StreamableHttpParameters(url="http://example.test/mcp"),
293+
ClientSessionParameters(read_timeout_seconds=2),
294+
)
295+
296+
assert excinfo.value.error.code == types.INTERNAL_ERROR
297+
assert excinfo.value.error.message == "Transport error: offline"
298+
299+
281300
# TODO(Marcelo): This is horrible. We should drop this test.
282301
@pytest.mark.anyio
283302
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)