Skip to content

Commit c4dc40b

Browse files
committed
fix: exit cleanly on stdio KeyboardInterrupt
1 parent e8e6484 commit c4dc40b

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

src/mcp/server/mcpserver/server.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ def run(
293293

294294
match transport:
295295
case "stdio":
296-
anyio.run(self.run_stdio_async)
296+
try:
297+
anyio.run(self.run_stdio_async)
298+
except KeyboardInterrupt:
299+
return
297300
case "sse": # pragma: no cover
298301
anyio.run(lambda: self.run_sse_async(**kwargs))
299302
case "streamable-http": # pragma: no cover

tests/server/mcpserver/test_server.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ def test_dependencies(self):
7474
mcp_no_deps = MCPServer("test")
7575
assert mcp_no_deps.dependencies == []
7676

77+
def test_run_stdio_exits_cleanly_on_keyboard_interrupt(self, monkeypatch: pytest.MonkeyPatch):
78+
mcp = MCPServer("test")
79+
80+
def raise_keyboard_interrupt(func: Any) -> None:
81+
assert func == mcp.run_stdio_async
82+
raise KeyboardInterrupt
83+
84+
monkeypatch.setattr("mcp.server.mcpserver.server.anyio.run", raise_keyboard_interrupt)
85+
86+
mcp.run("stdio")
87+
7788
async def test_sse_app_returns_starlette_app(self):
7889
"""Test that sse_app returns a Starlette application with correct routes."""
7990
mcp = MCPServer("test")

0 commit comments

Comments
 (0)