@@ -346,10 +346,18 @@ async def collect(params: LoggingMessageNotificationParams) -> None:
346346 anyio .create_task_group () as tg ,
347347 ):
348348 await first .initialize ()
349- tg .start_soon (first .send_request , call , CallToolResult , None , capture )
349+ # The call is abandoned via its own scope so the task group exits cleanly: cancelling
350+ # the whole group propagates Cancelled through this frame, which 3.11's tracer mishandles.
351+ call_scope = anyio .CancelScope ()
352+
353+ async def issue_call () -> None :
354+ with call_scope :
355+ await first .send_request (call , CallToolResult , metadata = capture )
356+
357+ tg .start_soon (issue_call )
350358 await first_seen .wait ()
351359 await token_seen .wait ()
352- tg . cancel_scope .cancel ()
360+ call_scope .cancel ()
353361 assert captured == snapshot (["3" , "4" ])
354362 assert received == snapshot (["first" ])
355363 # The session id is only observable via the manager (the client transport does not expose it).
@@ -360,7 +368,7 @@ async def collect(params: LoggingMessageNotificationParams) -> None:
360368 await store .wait_until_stored (6 )
361369 http .headers ["mcp-session-id" ] = session_id
362370 http .headers ["mcp-protocol-version" ] = LATEST_PROTOCOL_VERSION
363- async with (
371+ async with ( # pragma: no branch
364372 streamable_http_client (f"{ BASE_URL } /mcp" , http_client = http ) as (r2 , w2 ),
365373 ClientSession (r2 , w2 , logging_callback = collect ) as second ,
366374 ):
0 commit comments