Skip to content

Commit 328bb0b

Browse files
committed
fix: also catch BrokenResourceError from respond() for SHTTP terminate()
streamable_http's terminate() closes _write_stream_reader (the receive end) before _write_stream (the send end). A handler reaching respond() between those two closes gets BrokenResourceError (peer end closed) rather than ClosedResourceError (our end closed). The stdio path only ever hits ClosedResourceError because _receive_loop's async-with closes the send end.
1 parent e1d712d commit 328bb0b

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

src/mcp/server/lowlevel/server.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,13 @@ async def _handle_request(
494494

495495
try:
496496
await message.respond(response)
497-
except anyio.ClosedResourceError:
497+
except (anyio.BrokenResourceError, anyio.ClosedResourceError):
498498
# Transport closed between handler unblocking and respond. Happens
499499
# when _receive_loop's finally wakes a handler blocked on
500500
# send_request: the handler runs to respond() before run()'s TG
501-
# cancel fires, but after _receive_loop closed _write_stream.
501+
# cancel fires, but after the write stream closed. Closed if our
502+
# end closed (_receive_loop's async-with exit); Broken if the peer
503+
# end closed first (streamable_http terminate()).
502504
logger.debug("Response for %s dropped - transport closed", message.request_id)
503505
return
504506

0 commit comments

Comments
 (0)