MCPcopy
hub / github.com/modelcontextprotocol/python-sdk / _stop_server_process

Function _stop_server_process

src/mcp/client/stdio.py:248–267  ·  view source on GitHub ↗

Closes stdin, waits out the grace period, then kills the whole tree. The escalation order is spec text; timeouts and tree-wide scope are SDK policy: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#shutdown

(process: ServerProcess)

Source from the content-addressed store, hash-verified

246
247
248async def _stop_server_process(process: ServerProcess) -> None:
249 """Closes stdin, waits out the grace period, then kills the whole tree.
250
251 The escalation order is spec text; timeouts and tree-wide scope are SDK policy:
252 https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#shutdown
253 """
254 assert process.stdin and process.stdout, "server process is spawned with pipes"
255
256 await _close_pipe(process.stdin)
257 if not await _wait_for_process_exit(process, PROCESS_TERMINATION_TIMEOUT):
258 await _terminate_process_tree(process)
259 # Until the event loop observes the death, the transport cannot close.
260 if not await _wait_for_process_exit(process, _KILL_REAP_TIMEOUT):
261 logger.warning("MCP server process %d is still alive after the kill escalation; abandoning it", process.pid)
262
263 # Reaps surviving Windows job members now, not at GC; no-op on POSIX.
264 close_process_job(process)
265 # A kill survivor can hold the stdout pipe open; poison the reader anyway.
266 await _close_pipe(process.stdout)
267 _close_subprocess_transport(process)
268
269
270async def _close_pipe(stream: AsyncResource) -> None:

Callers 1

shutdownFunction · 0.85

Calls 6

close_process_jobFunction · 0.90
_close_pipeFunction · 0.85
_wait_for_process_exitFunction · 0.85
_terminate_process_treeFunction · 0.85
warningMethod · 0.80

Tested by

no test coverage detected