Skip to content

Commit 734aaeb

Browse files
committed
fix: suppress MCPServer KeyboardInterrupt tracebacks
1 parent ac96f88 commit 734aaeb

2 files changed

Lines changed: 21 additions & 8 deletions

File tree

src/mcp/server/mcpserver/server.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,16 @@ def run(
291291
if transport not in TRANSPORTS.__args__: # type: ignore # pragma: no cover
292292
raise ValueError(f"Unknown transport: {transport}")
293293

294-
match transport:
295-
case "stdio":
296-
anyio.run(self.run_stdio_async)
297-
case "sse": # pragma: no cover
298-
anyio.run(lambda: self.run_sse_async(**kwargs))
299-
case "streamable-http": # pragma: no cover
300-
anyio.run(lambda: self.run_streamable_http_async(**kwargs))
294+
try:
295+
match transport:
296+
case "stdio":
297+
anyio.run(self.run_stdio_async)
298+
case "sse": # pragma: no cover
299+
anyio.run(lambda: self.run_sse_async(**kwargs))
300+
case "streamable-http": # pragma: no cover
301+
anyio.run(lambda: self.run_streamable_http_async(**kwargs))
302+
except KeyboardInterrupt:
303+
return
301304

302305
async def _handle_list_tools(
303306
self, ctx: ServerRequestContext[LifespanResultT], params: PaginatedRequestParams | None

tests/server/mcpserver/test_server.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import base64
22
from pathlib import Path
3-
from typing import Any
3+
from typing import Any, Literal, cast
44
from unittest.mock import AsyncMock, MagicMock, patch
55

66
import pytest
@@ -73,6 +73,16 @@ def test_dependencies(self):
7373
mcp_no_deps = MCPServer("test")
7474
assert mcp_no_deps.dependencies == []
7575

76+
@pytest.mark.parametrize("transport", ["stdio", "sse", "streamable-http"])
77+
def test_run_suppresses_keyboard_interrupt(self, transport: str):
78+
mcp = MCPServer("test")
79+
transport_name = cast(Literal["stdio", "sse", "streamable-http"], transport)
80+
81+
with patch("mcp.server.mcpserver.server.anyio.run", side_effect=KeyboardInterrupt) as run:
82+
mcp.run(transport=transport_name)
83+
84+
run.assert_called_once()
85+
7686
async def test_sse_app_returns_starlette_app(self):
7787
"""Test that sse_app returns a Starlette application with correct routes."""
7888
mcp = MCPServer("test")

0 commit comments

Comments
 (0)