|
46 | 46 | StreamWriter = ContextSendStream[SessionMessageOrError] |
47 | 47 | StreamReader = ContextReceiveStream[SessionMessage] |
48 | 48 |
|
| 49 | + |
| 50 | +async def _send_or_ignore_closed(read_stream_writer: StreamWriter, message: SessionMessageOrError) -> bool: |
| 51 | + try: |
| 52 | + await read_stream_writer.send(message) |
| 53 | + except (anyio.BrokenResourceError, anyio.ClosedResourceError): |
| 54 | + logger.debug("Read stream closed before Streamable HTTP message could be delivered", exc_info=True) |
| 55 | + return False |
| 56 | + return True |
| 57 | + |
| 58 | + |
49 | 59 | MCP_SESSION_ID = "mcp-session-id" |
50 | 60 | LAST_EVENT_ID = "last-event-id" |
51 | 61 |
|
@@ -179,17 +189,17 @@ async def _handle_sse_event( |
179 | 189 | # Otherwise, return False to continue listening |
180 | 190 | return isinstance(message, JSONRPCResponse | JSONRPCError) |
181 | 191 |
|
182 | | - # Forwarding to a closed read stream lands here when the caller cancels mid-SSE |
183 | | - # (BrokenResourceError, not a parse failure); coverage is timing-dependent in the |
184 | | - # streaming story's modern HTTP cancellation leg. |
| 192 | + except (anyio.BrokenResourceError, anyio.ClosedResourceError): |
| 193 | + logger.debug("Read stream closed while forwarding SSE message", exc_info=True) |
| 194 | + return True |
185 | 195 | except Exception as exc: # pragma: lax no cover |
186 | 196 | logger.exception("Error parsing SSE message") |
187 | 197 | if original_request_id is not None: |
188 | 198 | error_data = ErrorData(code=PARSE_ERROR, message=f"Failed to parse SSE message: {exc}") |
189 | 199 | error_msg = SessionMessage(JSONRPCError(jsonrpc="2.0", id=original_request_id, error=error_data)) |
190 | | - await read_stream_writer.send(error_msg) |
| 200 | + await _send_or_ignore_closed(read_stream_writer, error_msg) |
191 | 201 | return True |
192 | | - await read_stream_writer.send(exc) |
| 202 | + await _send_or_ignore_closed(read_stream_writer, exc) |
193 | 203 | return False |
194 | 204 | else: # pragma: no cover |
195 | 205 | logger.warning(f"Unknown SSE event: {sse.event}") |
|
0 commit comments