Skip to content

MCP STDIO Performance Issue - Async Context Management Bug #2980

@AlfredoJF

Description

@AlfredoJF

Describe the bug

STDIO MCP connections restart between requests, causing significant performance degradation (2-5 seconds per request instead of expected 10-50ms). This occurs due to an async context management issue where AsyncExitStack cleanup is attempted from a different async task than where it was created.

To Reproduce

  1. Create an ADK agent with STDIO MCP toolset:

    from google.adk.tools.mcp_tool import McpToolset
    from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
    from mcp import StdioServerParameters
    
    tools=[McpToolset(
        connection_params=StdioConnectionParams(
            server_params=StdioServerParameters(
                command="node", 
                args=["path/to/mcp-server.js"]
            )
        )
    )]
  2. Run the agent and observe logs:

    INFO:google_adk.google.adk.tools.mcp_tool.mcp_session_manager:Cleaning up disconnected session: stdio_session
    WARNING:google_adk.google.adk.tools.mcp_tool.mcp_session_manager:Error during disconnected session cleanup: Attempted to exit cancel scope in a different task than it was entered in
    

Expected behaviour

  • MCP sessions should persist between tool calls (10-50ms per request)
  • No async context management errors
  • Sessions only cleaned up when actually disconnected

Desktop Information

  • OS: macOS (affects all platforms)
  • Python version: 3.10+
  • ADK version: current main branch
  • LiteLLM: No
  • Model: Any (reproduction doesn't depend on model)

Additional context

Root Cause: src/google/adk/tools/mcp_tool/mcp_session_manager.py:330-338

else:
    # Session is disconnected, clean it up
    logger.info('Cleaning up disconnected session: %s', session_key)
    try:
        await exit_stack.aclose()  # ← Problem: called from wrong async task
    except Exception as e:
        logger.warning('Error during disconnected session cleanup: %s', e)
    finally:
        del self._sessions[session_key]

Problem: AsyncExitStack created during agent initialisation (main task) but cleanup attempted from tool execution task (different async context), violating anyio's cancel scope requirements.

Impact: Affects all STDIO MCP users, especially plugin-based tools and performance-critical applications.

Metadata

Metadata

Assignees

Labels

mcp[Component] Issues about MCP support

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions