Skip to content

Commit 78525ff

Browse files
committed
fix: send JSONRPCError instead of raw Exception for failed requests
When a JSONRPCRequest fails with a connection error in post_writer, the error must be sent as a JSONRPCError wrapped in a SessionMessage so the response router in BaseSession can match it to the waiting send_request call. Sending a raw Exception causes the request to hang indefinitely because _receive_loop forwards it to _handle_incoming (a no-op by default) while send_request blocks on its response stream. Notification errors are still forwarded as raw exceptions since nothing waits on a response stream for them.
1 parent 387cbfc commit 78525ff

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

src/mcp/client/streamable_http.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,17 @@ async def handle_request_async() -> None:
476476
raise
477477
except Exception as exc:
478478
with contextlib.suppress(Exception):
479-
await read_stream_writer.send(exc)
479+
if isinstance(message, JSONRPCRequest):
480+
error_data = ErrorData(
481+
code=INTERNAL_ERROR,
482+
message=str(exc) or "Connection error",
483+
)
484+
error_msg = SessionMessage(
485+
JSONRPCError(jsonrpc="2.0", id=message.id, error=error_data)
486+
)
487+
await read_stream_writer.send(error_msg)
488+
else:
489+
await read_stream_writer.send(exc)
480490

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

tests/shared/test_streamable_http.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
CallToolRequestParams,
5757
CallToolResult,
5858
InitializeResult,
59+
JSONRPCError,
5960
JSONRPCRequest,
6061
ListToolsResult,
6162
PaginatedRequestParams,
@@ -2353,7 +2354,10 @@ async def test_connection_error_forwarded_to_read_stream():
23532354
)
23542355
await write_stream.send(init_message)
23552356

2356-
# The connection error should be forwarded to the read stream
2357+
# The connection error should be forwarded as a JSONRPCError
2358+
# so that send_request can route it to the correct response stream
23572359
with anyio.fail_after(5):
23582360
result = await read_stream.receive()
2359-
assert isinstance(result, Exception)
2361+
assert isinstance(result, SessionMessage)
2362+
assert isinstance(result.message, JSONRPCError)
2363+
assert result.message.id == "init-err"

0 commit comments

Comments
 (0)