-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
I am pushing the stdio_client
and ClientSession
onto an AsyncExitStack
to avoid needing to wrap everyting in with
statements. My client will have multiple simultaneous instances of different ClientSession
s, so I wanted a manager class to handle cleaning up the session when it is GC'd. My plan was to run a task in the manager classes __del__
method to clean up, e.g. asyncio.create_task(self.exit_stack.aclose())
.
However this raises RuntimeError: Attempted to exit cancel scope in a different task than it was entered in
To Reproduce
uv run
this script:
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "mcp",
# ]
# ///
import asyncio
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main() -> None:
exit_stack = AsyncExitStack()
server_params = StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
)
read, write = await exit_stack.enter_async_context(stdio_client(server_params))
session = await exit_stack.enter_async_context(ClientSession(read, write))
await session.initialize()
asyncio.create_task(exit_stack.aclose())
if __name__ == "__main__":
asyncio.run(main())
Expected behavior
Clean shutdown.
Logs
(node:63152) ExperimentalWarning: CommonJS module /opt/homebrew/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /opt/homebrew/lib/node_modules/npm/node_modules/supports-color/index.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Secure MCP Filesystem Server running on stdio
Allowed directories: [ '/tmp' ]
unhandled exception during asyncio.run() shutdown
task: <Task finished name='Task-6' coro=<AsyncExitStack.aclose() done, defined at /Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py:654> exception=RuntimeError('Attempted to exit cancel scope in a different task than it was entered in')>
Traceback (most recent call last):
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/mcp/client/stdio.py", line 128, in stdio_client
yield read_stream, write_stream
File "/Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py", line 697, in __aexit__
cb_suppress = await cb(*exc_details)
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/mcp/shared/session.py", line 122, in __aexit__
return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 769, in __aexit__
if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__):
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 433, in __exit__
raise RuntimeError(
RuntimeError: Attempted to exit cancel scope in a different task than it was entered in
During handling of the above exception, another exception occurred:
+ Exception Group Traceback (most recent call last):
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 763, in __aexit__
| raise BaseExceptionGroup(
| exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise exc_val
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 741, in __aexit__
| await _wait(self._tasks)
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 706, in _wait
| await waiter
| asyncio.exceptions.CancelledError
|
| During handling of the above exception, another exception occurred:
|
| Traceback (most recent call last):
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/mcp/client/stdio.py", line 128, in stdio_client
| yield read_stream, write_stream
| File "/Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py", line 697, in __aexit__
| cb_suppress = await cb(*exc_details)
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/mcp/shared/session.py", line 122, in __aexit__
| return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 769, in __aexit__
| if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__):
| File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 433, in __exit__
| raise RuntimeError(
| RuntimeError: Attempted to exit cancel scope in a different task than it was entered in
+------------------------------------
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py", line 656, in aclose
await self.__aexit__(None, None, None)
File "/Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py", line 714, in __aexit__
raise exc_details[1]
File "/Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py", line 697, in __aexit__
cb_suppress = await cb(*exc_details)
File "/Users/aw/.local/share/uv/python/cpython-3.10.15-macos-aarch64-none/lib/python3.10/contextlib.py", line 217, in __aexit__
await self.gen.athrow(typ, value, traceback)
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/mcp/client/stdio.py", line 122, in stdio_client
async with (
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 769, in __aexit__
if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__):
File "/Users/aw/Library/Caches/uv/archive-v0/bkm4-HGL-Ma8SIqOuzaOM/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 433, in __exit__
raise RuntimeError(
RuntimeError: Attempted to exit cancel scope in a different task than it was entered in
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working