Skip to content

RuntimeError: Attempted to exit cancel scope in a different task than it was entered in #521

@npkanaka

Description

@npkanaka

Description

When attempting to stop an SSE client connection created with mcp.client.sse.sse_client(), the application throws a RuntimeError related to AnyIO cancel scopes being exited in different tasks than they were entered in. This prevents proper application shutdown and can lead to resource leaks.

Steps to Reproduce

Set up an SSE client using the mcp.client.sse.sse_client() function
Establish a connection using the aenter() method
Attempt to close the connection using the aexit() method during application shutdown

The issue appears to be that the sse_client function in mcp.client.sse module creates AnyIO task groups or cancel scopes that are entered in one task but exited in another during cleanup. AnyIO requires that cancel scopes must be entered and exited in the same task context.
The problem is likely in the implementation of the async generator pattern in the sse_client function. When the connection is closed or an error occurs, the task group's __aexit__ method is being called in a different task than the one where __aenter__ was called, violating AnyIO's constraints.

Expected Behavior

The SSE connection should close cleanly without errors.

Actual Behavior

The application throws the following error:

RuntimeError: Attempted to exit cancel scope in a different task than it was entered in

Code Example

from mcp.client.sse import sse_client

async def connect_and_disconnect():
    # Set up the client
    streams_context = sse_client(url="http://example.com/sse", headers={"Authorization": "Bearer token"})
    streams = await streams_context.__aenter__()
    
    # Use the streams...
    
    # When shutting down - this throws the RuntimeError
    await streams_context.__aexit__(None, None, None)

Environment

  • Python version: 3.10
  • mcp package version: 1.6.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions