You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Windows stdio server: subprocess spawned inside a tool handler hangs forever when it inherits the server stdin (stdin=DEVNULL fixes) #3788
A subprocess spawned from INSIDE a FastMCP tool handler (stdio server, Windows) hangs forever when the child inherits the server stdin — which is the default in subprocess.run/create_subprocess_exec if stdin is not set.
Repro (Windows, minimal)
FastMCP server (stdio) with a tool that spawns a trivial child (e.g. python -c "print(1)"):
subprocess.run([...]) with inherited stdin → child never completes; tool call hangs (abort only via MCP idle-timeout — 30 min by default in Claude Code)
same call with stdin=subprocess.DEVNULL → completes in ~0.6 s
A/B tested with FastMCP pure (zero user imports) to rule out user code; also reproduced via asyncio.create_subprocess_exec on the event loop. The moment the child stops sharing the server jsonrpc stdin, everything works.
Suggested guard
Document/force stdin=DEVNULL for subprocesses spawned in handlers, or detach the child stdin by default in any subprocess helper the SDK provides — inheriting the protocol pipe is never what a tool wants.
Environment: Windows 11 (26200), Python 3.14, mcp/fastmcp stdio transport, Claude Code 2.1.310 host.
Confirmed on Windows 11 (26200), Python 3.12.10, mcp 1.30.0: the inherit tool hangs, the stdin=DEVNULL one returns in ~0.4s.
One correction on the cause: it isn't a second reader on the pipe. Popen returns immediately, and hostname.exe / cmd /c echo 1 children complete fine. Only a Python child freezes, and it stays alive at ~4 MB, stuck in interpreter startup. That is CPython gh-78961 (synchronous pipe I/O is serialized on Windows, and the server always has a blocking read pending on stdin), so this looks like a duplicate of #671.
It's already fixed on main by #3117: the same repro against 2.3.1.dev17 returns in ~0.7s. v1.x doesn't have it (no stdin diversion in src/mcp/server/stdio.py). On v1 the workaround is stdin=subprocess.DEVNULL in the handler.
If a backport to v1.x is wanted, I'd be glad to do it. Otherwise this can be closed in favour of #671.
Disclosure: I investigated this with the help of an AI coding assistant (Claude Code). I ran every repro above myself on my machine.
Hi, we are TechAura. We would like to work on this if a maintainer is willing to assign it to us. Our read of the problem: in a stdio server, a subprocess spawned inside a tool handler inherits the server stdin and blocks waiting on it, while passing stdin=DEVNULL returns immediately. The fix we have in mind is to stop tool-handler-spawned subprocesses from inheriting server stdin, defaulting to DEVNULL, with a regression test covering the hang case. Happy to adjust the approach if the maintainers prefer a different shape.
Activity
Ben-Home commentedon Oct 30, 2026
prafulla2121 commentedon Oct 31, 2026
Confirmed on Windows 11 (26200), Python 3.12.10,
mcp1.30.0: theinherittool hangs, thestdin=DEVNULLone returns in ~0.4s.One correction on the cause: it isn't a second reader on the pipe.
Popenreturns immediately, andhostname.exe/cmd /c echo 1children complete fine. Only a Python child freezes, and it stays alive at ~4 MB, stuck in interpreter startup. That is CPython gh-78961 (synchronous pipe I/O is serialized on Windows, and the server always has a blocking read pending on stdin), so this looks like a duplicate of #671.It's already fixed on
mainby #3117: the same repro against 2.3.1.dev17 returns in ~0.7s.v1.xdoesn't have it (no stdin diversion insrc/mcp/server/stdio.py). On v1 the workaround isstdin=subprocess.DEVNULLin the handler.If a backport to
v1.xis wanted, I'd be glad to do it. Otherwise this can be closed in favour of #671.Disclosure: I investigated this with the help of an AI coding assistant (Claude Code). I ran every repro above myself on my machine.
techaurah commentedon Nov 1, 2026
Hi, we are TechAura. We would like to work on this if a maintainer is willing to assign it to us. Our read of the problem: in a stdio server, a subprocess spawned inside a tool handler inherits the server stdin and blocks waiting on it, while passing stdin=DEVNULL returns immediately. The fix we have in mind is to stop tool-handler-spawned subprocesses from inheriting server stdin, defaulting to DEVNULL, with a regression test covering the hang case. Happy to adjust the approach if the maintainers prefer a different shape.