File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -416,13 +416,16 @@ def run(
416416 if transport not in TRANSPORTS .__args__ : # type: ignore # pragma: no cover
417417 raise ValueError (f"Unknown transport: { transport } " )
418418
419- match transport :
420- case "stdio" :
421- anyio .run (self .run_stdio_async )
422- case "sse" : # pragma: no cover
423- anyio .run (lambda : self .run_sse_async (** kwargs ))
424- case "streamable-http" : # pragma: no cover
425- anyio .run (lambda : self .run_streamable_http_async (** kwargs ))
419+ try :
420+ match transport :
421+ case "stdio" :
422+ anyio .run (self .run_stdio_async )
423+ case "sse" : # pragma: no cover
424+ anyio .run (lambda : self .run_sse_async (** kwargs ))
425+ case "streamable-http" : # pragma: no cover
426+ anyio .run (lambda : self .run_streamable_http_async (** kwargs ))
427+ except KeyboardInterrupt :
428+ return
426429
427430 async def _handle_list_tools (
428431 self , ctx : ServerRequestContext [LifespanResultT ], params : PaginatedRequestParams | None
Original file line number Diff line number Diff line change @@ -111,6 +111,14 @@ def test_dependencies(self):
111111 mcp_no_deps = MCPServer ("test" )
112112 assert mcp_no_deps .dependencies == []
113113
114+ def test_stdio_keyboard_interrupt_exits_cleanly (self ):
115+ mcp = MCPServer ("test" )
116+
117+ with patch ("mcp.server.mcpserver.server.anyio.run" , side_effect = KeyboardInterrupt ) as run :
118+ mcp .run ("stdio" )
119+
120+ run .assert_called_once_with (mcp .run_stdio_async )
121+
114122 async def test_sse_app_returns_starlette_app (self ):
115123 """Test that sse_app returns a Starlette application with correct routes."""
116124 mcp = MCPServer ("test" )
You can’t perform that action at this time.
0 commit comments