fix(tests): convert create_mcp_client_session to asynccontextmanager
The multi-user-basic integration job was consistently failing with `CancelledError: Cancelled via cancel scope ... by <async_generator_athrow>` followed by a cascade of `anyio.ClosedResourceError` in every subsequent test. Root cause: `create_mcp_client_session` was declared as an async generator driven by `async for session in ...:`, so Python's generator finalizer (`aclose`) ran under pytest-asyncio's cleanup task instead of the task that owned the nested `streamablehttp_client` cancel scope. anyio then raised when the inner task group saw its scope being exited from a foreign task, leaving the memory object streams half-closed and poisoning the rest of the session. Switching to `@asynccontextmanager` + `async with ... as session:` makes `__aenter__`/`__aexit__` run in the frame that owns the context manager, satisfying anyio's structured concurrency requirements. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
9b6b554155
commit
3935f45be8
@@ -367,12 +367,12 @@ async def nc_mcp_login_flow_client(
|
||||
content={"acknowledged": True},
|
||||
)
|
||||
|
||||
async for session in create_mcp_client_session(
|
||||
async with create_mcp_client_session(
|
||||
url=LOGIN_FLOW_MCP_URL,
|
||||
token=login_flow_oauth_token,
|
||||
client_name="Login Flow MCP",
|
||||
elicitation_callback=elicitation_callback,
|
||||
):
|
||||
) as session:
|
||||
# Step 1: Provision access via Login Flow v2
|
||||
logger.info("Starting Login Flow v2 provisioning...")
|
||||
provision_result = await session.call_tool(
|
||||
@@ -499,11 +499,11 @@ async def nc_mcp_login_flow_client_read_only(
|
||||
anyio_backend, login_flow_read_only_token: str
|
||||
) -> AsyncGenerator[ClientSession, Any]:
|
||||
"""MCP client with read-only scopes on the login-flow server."""
|
||||
async for session in create_mcp_client_session(
|
||||
async with create_mcp_client_session(
|
||||
url=LOGIN_FLOW_MCP_URL,
|
||||
token=login_flow_read_only_token,
|
||||
client_name="Login Flow MCP Read-Only",
|
||||
):
|
||||
) as session:
|
||||
yield session
|
||||
|
||||
|
||||
@@ -512,11 +512,11 @@ async def nc_mcp_login_flow_client_write_only(
|
||||
anyio_backend, login_flow_write_only_token: str
|
||||
) -> AsyncGenerator[ClientSession, Any]:
|
||||
"""MCP client with write-only scopes on the login-flow server."""
|
||||
async for session in create_mcp_client_session(
|
||||
async with create_mcp_client_session(
|
||||
url=LOGIN_FLOW_MCP_URL,
|
||||
token=login_flow_write_only_token,
|
||||
client_name="Login Flow MCP Write-Only",
|
||||
):
|
||||
) as session:
|
||||
yield session
|
||||
|
||||
|
||||
@@ -525,11 +525,11 @@ async def nc_mcp_login_flow_client_full_access(
|
||||
anyio_backend, login_flow_full_access_token: str
|
||||
) -> AsyncGenerator[ClientSession, Any]:
|
||||
"""MCP client with full access scopes on the login-flow server."""
|
||||
async for session in create_mcp_client_session(
|
||||
async with create_mcp_client_session(
|
||||
url=LOGIN_FLOW_MCP_URL,
|
||||
token=login_flow_full_access_token,
|
||||
client_name="Login Flow MCP Full Access",
|
||||
):
|
||||
) as session:
|
||||
yield session
|
||||
|
||||
|
||||
@@ -538,11 +538,11 @@ async def nc_mcp_login_flow_client_no_custom_scopes(
|
||||
anyio_backend, login_flow_no_custom_scopes_token: str
|
||||
) -> AsyncGenerator[ClientSession, Any]:
|
||||
"""MCP client with no custom scopes on the login-flow server."""
|
||||
async for session in create_mcp_client_session(
|
||||
async with create_mcp_client_session(
|
||||
url=LOGIN_FLOW_MCP_URL,
|
||||
token=login_flow_no_custom_scopes_token,
|
||||
client_name="Login Flow MCP No Custom Scopes",
|
||||
):
|
||||
) as session:
|
||||
yield session
|
||||
|
||||
|
||||
@@ -724,12 +724,12 @@ async def _provision_login_flow_mcp_client(
|
||||
|
||||
return ElicitResult(action="accept", content={"acknowledged": True})
|
||||
|
||||
async for session in create_mcp_client_session(
|
||||
async with create_mcp_client_session(
|
||||
url=LOGIN_FLOW_MCP_URL,
|
||||
token=token,
|
||||
client_name=f"Login Flow MCP ({username})",
|
||||
elicitation_callback=elicitation_callback,
|
||||
):
|
||||
) as session:
|
||||
# Provision access
|
||||
provision_result = await session.call_tool(
|
||||
"nc_auth_provision_access", {"scopes": None}
|
||||
|
||||
Reference in New Issue
Block a user