-
Notifications
You must be signed in to change notification settings - Fork 23
Description
Hey @elusznik! I saw this cool server and have been looking for a way to cut down the ridiculous mcp token bloat, especially from chrome dev tools. I got it installed but ran into the error below. I had claude generate an issue for me, is there anything else you need to help fix it?
RuntimeError with anyio cancel scopes on Python 3.14
Description
When using mcp-server-code-execution-mode with Python 3.14 and attempting to proxy an MCP server (e.g., mcp-server-time), the server crashes with a RuntimeError related to anyio cancel scope management.
The server works fine for basic run_python calls (including runtime.capability_summary() and standard library code), but crashes when attempting to load/proxy another MCP server via the servers=["time"] parameter.
Environment
| Component | Version |
|---|---|
| OS | Ubuntu 22.04.5 LTS |
| Kernel | 5.19.0-051900-generic x86_64 |
| Python (via uvx) | 3.14.0 |
| uv | 0.9.11 |
| mcp-server-code-execution-mode | 1.22.0 (from git main) |
| mcp | 1.22.0 |
| anyio | 4.11.0 |
| pydantic | 2.12.4 |
| pydantic_core | 2.41.5 |
| Docker | 29.0.2 |
| Claude Code CLI | 2.0.53 |
Configuration
Claude Code MCP config (~/.claude.json):
{
"type": "stdio",
"command": "uvx",
"args": [
"--python",
"3.14",
"--from",
"git+https://github.com/elusznik/mcp-server-code-execution-mode",
"mcp-server-code-execution-mode",
"run"
],
"env": {
"MCP_BRIDGE_RUNTIME": "docker",
"MCP_SERVERS_CONFIG": "/path/to/mcp-servers.json"
}
}Proxied servers config (mcp-servers.json):
{
"mcpServers": {
"time": {
"command": "uvx",
"args": ["mcp-server-time"],
"env": {},
"description": "Timezone utilities - get current time, convert timezones"
}
}
}Steps to Reproduce
- Configure
mcp-server-code-execution-modewith Python 3.14 as shown above - Configure at least one proxied MCP server (e.g.,
mcp-server-time) - Start a Claude Code session
- Run a basic command that works:
use run python to ask time to get the current time - Attempt to use a proxied server:
# This triggers the crash # (passed servers=["time"] parameter to run_python)
Expected Behavior
The server should successfully load the proxied time MCP server and allow calling its tools.
Actual Behavior
The server crashes with nested ExceptionGroup errors after loading the proxied server:
INFO:mcp-server-code-execution-mode:Loaded MCP server time
Then approximately 2-3 minutes later (possibly during cleanup/timeout):
RuntimeError: Attempted to exit a cancel scope that isn't the current tasks's current cancel scope
Full Stack Trace
ERROR:root:Fatal error in main loop
+ Exception Group Traceback (most recent call last):
| File ".../mcp_server_code_execution_mode.py", line 2633, in main
| async with stdio_server() as (read_stream, write_stream):
| File ".../contextlib.py", line 235, in __aexit__
| await self.gen.athrow(value)
| File ".../mcp/server/stdio.py", line 85, in stdio_server
| async with anyio.create_task_group() as tg:
| File ".../anyio/_backends/_asyncio.py", line 781, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| ) from None
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File ".../mcp/server/stdio.py", line 88, in stdio_server
| yield read_stream, write_stream
| File ".../mcp_server_code_execution_mode.py", line 2634, in main
| await app.run(
| read_stream, write_stream, app.create_initialization_options()
| )
| File ".../mcp/server/lowlevel/server.py", line 616, in run
| async with AsyncExitStack() as stack:
| File ".../contextlib.py", line 768, in __aexit__
| raise exc
| File ".../contextlib.py", line 751, in __aexit__
| cb_suppress = await cb(*exc_details)
| File ".../mcp/shared/session.py", line 220, in __aexit__
| return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
| File ".../anyio/_backends/_asyncio.py", line 781, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| ) from None
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File ".../mcp/server/lowlevel/server.py", line 627, in run
| async with anyio.create_task_group() as tg:
| File ".../anyio/_backends/_asyncio.py", line 781, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| ) from None
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File ".../mcp_server_code_execution_mode.py", line 2482, in _patched_handle_message
| return await _orig_handle_message(
| self, message, session, lifespan_context, raise_exceptions
| )
| File ".../mcp/server/lowlevel/server.py", line 649, in _handle_message
| with responder:
| File ".../mcp/shared/session.py", line 116, in __exit__
| self._cancel_scope.__exit__(exc_type, exc_val, exc_tb)
| File ".../anyio/_backends/_asyncio.py", line 467, in __exit__
| raise RuntimeError(
| ...
| )
| RuntimeError: Attempted to exit a cancel scope that isn't the current tasks's current cancel scope
+------------------------------------
Additional error during cleanup:
ERROR:asyncio:an error occurred during closing of asynchronous generator <async_generator object stdio_client at 0x...>
...
RuntimeError: Attempted to exit cancel scope in a different task than it was entered in
Analysis
This appears to be a Python 3.14 + anyio compatibility issue. Python 3.14 introduced changes to asyncio's task cancellation semantics that may conflict with how anyio manages cancel scopes.
The issue specifically occurs in mcp/shared/session.py:116 when the RequestResponder.__exit__ method tries to exit its cancel scope, but the scope is being exited from a different task than it was entered in.
Note: This issue was generated with assistance from Claude Code (Opus 4.5) based on log analysis