Skip to content

Commit 7b07fe7

Browse files
Raise error if MCPServer.__aexit__ is called when _running_count is already 0 (#2696)
1 parent 4f5daee commit 7b07fe7

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

pydantic_ai_slim/pydantic_ai/mcp.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ async def __aenter__(self) -> Self:
300300
return self
301301

302302
async def __aexit__(self, *args: Any) -> bool | None:
303+
if self._running_count == 0:
304+
raise ValueError('MCPServer.__aexit__ called more times than __aenter__')
303305
async with self._enter_lock:
304306
self._running_count -= 1
305307
if self._running_count == 0 and self._exit_stack is not None:

tests/test_mcp.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ async def test_context_manager_initialization_error() -> None:
107107
assert server._write_stream._closed # pyright: ignore[reportPrivateUsage]
108108

109109

110+
async def test_aexit_called_more_times_than_aenter():
111+
server = MCPServerStdio('python', ['-m', 'tests.mcp_server'])
112+
113+
with pytest.raises(ValueError, match='MCPServer.__aexit__ called more times than __aenter__'):
114+
await server.__aexit__(None, None, None)
115+
116+
async with server:
117+
pass # This will call __aenter__ and __aexit__ once each
118+
119+
with pytest.raises(ValueError, match='MCPServer.__aexit__ called more times than __aenter__'):
120+
await server.__aexit__(None, None, None)
121+
122+
110123
async def test_stdio_server_with_tool_prefix(run_context: RunContext[int]):
111124
server = MCPServerStdio('python', ['-m', 'tests.mcp_server'], tool_prefix='foo')
112125
async with server:

0 commit comments

Comments
 (0)