Skip to content

Commit e0306f9

Browse files
wiggzzclaude
andcommitted
Revert sleep(0) approach — coverage was racy
The sleep(0) between terminate() and cancel_scope.cancel() was non-deterministic: sometimes the event loop ran exception handlers (covering the pragmas), sometimes the cancel won the race (leaving lines uncovered). This caused strict-no-cover to flip between "wrongly marked" and "missing coverage" across CI runs. Revert to the simple, deterministic approach: - Restore all original pragma: no cover annotations - Add pragma: no cover for the ClosedResourceError/_terminated path in the message router, which is unreachable with request-scoped task groups (Cancelled always wins over ClosedResourceError) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3d68f9e commit e0306f9

3 files changed

Lines changed: 6 additions & 9 deletions

File tree

src/mcp/server/streamable_http.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -619,14 +619,14 @@ async def sse_writer(): # pragma: lax no cover
619619
# Then send the message to be processed by the server
620620
session_message = self._create_session_message(message, request, request_id, protocol_version)
621621
await writer.send(session_message)
622-
except Exception:
622+
except Exception: # pragma: no cover
623623
logger.exception("SSE response error")
624624
await sse_stream_writer.aclose()
625625
await self._clean_up_memory_streams(request_id)
626626
finally:
627627
await sse_stream_reader.aclose()
628628

629-
except Exception as err:
629+
except Exception as err: # pragma: no cover
630630
logger.exception("Error handling POST request")
631631
response = self._create_error_response(
632632
f"Error handling POST request: {err}",
@@ -809,7 +809,7 @@ async def _validate_request_headers(self, request: Request, send: Send) -> bool:
809809

810810
async def _validate_session(self, request: Request, send: Send) -> bool:
811811
"""Validate the session ID in the request."""
812-
if not self.mcp_session_id:
812+
if not self.mcp_session_id: # pragma: no cover
813813
# If we're not using session IDs, return True
814814
return True
815815

@@ -1018,7 +1018,7 @@ async def message_router():
10181018
might reconnect and replay."""
10191019
)
10201020
except anyio.ClosedResourceError:
1021-
if self._terminated:
1021+
if self._terminated: # pragma: no cover
10221022
logger.debug("Read stream closed by client")
10231023
else:
10241024
logger.exception("Unexpected closure of read stream in message router")

src/mcp/server/streamable_http_manager.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ async def run_stateless_server(*, task_status: TaskStatus[None] = anyio.TASK_STA
178178
self.app.create_initialization_options(),
179179
stateless=True,
180180
)
181-
except Exception:
181+
except Exception: # pragma: no cover
182182
logger.exception("Stateless session crashed")
183183

184184
# Use a request-scoped task group instead of the global one.
@@ -193,9 +193,6 @@ async def run_request_handler(*, task_status: TaskStatus[None] = anyio.TASK_STAT
193193
await http_transport.handle_request(scope, receive, send)
194194
# Terminate the transport after the request is handled
195195
await http_transport.terminate()
196-
# Yield one scheduling step so other tasks (e.g. the message
197-
# router) can observe the closed streams before we cancel.
198-
await anyio.sleep(0)
199196
# Cancel the request-scoped task group to stop the server task
200197
request_tg.cancel_scope.cancel()
201198

src/mcp/shared/session.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ async def _receive_loop(self) -> None:
423423
try:
424424
await stream.send(JSONRPCError(jsonrpc="2.0", id=id, error=error))
425425
await stream.aclose()
426-
except Exception:
426+
except Exception: # pragma: no cover
427427
# Stream might already be closed
428428
pass
429429
self._response_streams.clear()

0 commit comments

Comments
 (0)