stdio servers don't exit when the client does and continue running indefinitely.
Description
When using a FastMCP server with a stdio client (such as Claude Desktop) the server doesn't seem to ever exit, leading to dozens or hundreds of instances of each server running in the background on the user's machine.
Was not able to reproduce this with the FastMCP client (e. g. async with Client(StdioTransport("python", ["echo.py"]))) but also see the same issue in Cherry Studio and have noticed that nodejs mcp tools do not have this problem so filing a bug here.
Example Code
"""
FastMCP Echo Server
"""
from fastmcp import FastMCP
# Create server
mcp = FastMCP("Echo Server")
@mcp.tool()
def echo_tool(text: str) -> str:
"""Echo the input text"""
return text
@mcp.resource("echo://static")
def echo_resource() -> str:
return "Echo!"
@mcp.resource("echo://{text}")
def echo_template(text: str) -> str:
"""Echo the input text"""
return f"Echo: {text}"
@mcp.prompt("echo")
def echo_prompt(text: str) -> str:
return text
if __name__ == "__main__":
# Run the server
mcp.run()
Version Information
FastMCP version: 2.2.10
MCP version: 1.7.1
Python version: 3.10.17
Platform: macOS-15.4.1-arm64-arm-64bit
FastMCP root path: /Users/<user>/Documents/Git/curl-mcp/.venv/lib/python3.10/site-packages
Additional Context
No response
I believe this is a bug in the low level server which has no ability to stop . It has been raised before and we may just need to solve it here instead of relying on the official sdk
I confirm this bug on Mac OS X + Claude Desktop + Python process (stdio)
While waiting for this issue to be resolved how do you properly kill off the old ones?
I'm unable to replicate this behavior with Claude Desktop on Mac OS -- when Claude starts, I see STDIO servers start for each installed MCP, as expected. When Claude exits, those processes disappear. While I don't have insight into how Claude manages the lifecycle of STDIO servers, this seems like expected behavior to me.
How are you running them? I'm currently using uv so maybe it's related to that? I'm on macOS testing with Claude Desktop as well with the relevant part of my config like this:
"echo": {
"command": "uv",
"args": [
"--directory",
"/path/to/echo/project",
"run",
"echo.py"
]
}
Running ps aux to check if the process is still running and it is several minutes after quitting claude desktop:
$ ps aux | grep echo.py | grep -v grep
<user> 22539 0.0 0.1 412073472 35392 ?? S 1:53PM 0:00.95 /path/to/echo/project/.venv/bin/python3 echo.py
<user> 22536 0.0 0.0 410948752 12496 ?? S 1:53PM 0:00.02 /opt/homebrew/bin/uv --directory /path/to/echo/project run echo.py
Python version is 3.12.10
EDIT: Checked and instead setting it up as a script in pyproject.toml and running with uvx and it seems to quit as expected, so this looks like it may be something about uv run rather than fastmcp or the sdk.
I'm running a simple stdio fastmcp server on a mac and after pressing ctrl-c I still have to press Enter to go back to the terminal prompt
Howdy, I shipped some improvements to stdio handling / shutdown here https://github.com/jlowin/fastmcp/pull/1444
Let me know if you can still reproduce this issue otherwise I'll close it in the next couple of days.