Skip to content

Dynamic MCP Toolset | ValueError: MCPServer.__aexit__ called more times than __aenter__ #3542

@hayescode

Description

@hayescode

Initial Checks

Description

I am trying to have a single agent configuration for my users that uses an authenticated MCP server. Following the documentation I see I can pass in a function to use the RunContext to configure the MCP server for each user.

This correctly authenticates each MCP server and returns the results, but it always errors out before completing. I can see in the events that when prompts "what's my github username?" it gets the logged in user, then afterwards it fails with the below error.

  File "C:\Users\user\AppData\Local\Programs\Python\Python313\Lib\contextlib.py", line 235, in __aexit__
    await self.gen.athrow(value)
  File "C:\Users\user\cheersgpt\.venv\Lib\site-packages\pydantic_ai\agent\__init__.py", line 656, in iter
    async with toolset:
               ^^^^^^^
  File "C:\Users\user\cheersgpt\.venv\Lib\site-packages\pydantic_ai\toolsets\combined.py", line 60, in __aexit__
    await self._exit_stack.aclose()
  File "C:\Users\user\AppData\Local\Programs\Python\Python313\Lib\contextlib.py", line 705, in aclose
    await self.__aexit__(None, None, None)
  File "C:\Users\user\AppData\Local\Programs\Python\Python313\Lib\contextlib.py", line 768, in __aexit__
    raise exc
  File "C:\Users\user\AppData\Local\Programs\Python\Python313\Lib\contextlib.py", line 751, in __aexit__
    cb_suppress = await cb(*exc_details)
                  ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\cheersgpt\.venv\Lib\site-packages\pydantic_ai\toolsets\_dynamic.py", line 44, in __aexit__
    return await self._toolset.__aexit__(*args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\cheersgpt\.venv\Lib\site-packages\pydantic_ai\mcp.py", line 650, in __aexit__
    raise ValueError('MCPServer.__aexit__ called more times than __aenter__')

Example Code

from fastapi import Depends
from pydantic_ai import Agent, RunContext


async def github_mcp(ctx: RunContext[AgentContext]):
    token = ctx.deps.user.metadata.github_access_token
    return MCPServerStreamableHTTP(
        id="github",
        url="https://api.githubcopilot.com/mcp/",
        headers={"Authorization": f"Bearer {token}"},
    )


github_agent = github_agent = Agent(TestModel(), deps_type=AgentContext, toolsets=[github_mcp])


@app.post("/stream")
async def stream(
    body: StreamRequest,
    user: User = Depends(get_current_user),
):
    agent_context = AgentContext(user=user)
    async for event in github_agent.run_stream_events(body.prompt, deps=agent_context):
        # await event_handler.handle(event)
        print(event)

Python, Pydantic AI & LLM client version

Python: 3.13.2
Pydantic AI: 1.22.0
LLM: OpenAI (latest)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions