-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Initial Checks
- I confirm that I'm using the latest version of MCP Python SDK
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Description
I'm trying to use stdio_client to spawn and communicate with a FastMCP server, but it consistently fails during the initialization handshake. The client times out after about 10 seconds with a BrokenResourceError.
The subprocess starts fine and I can see the server is running, but when the client tries to initialize the session, it hangs and eventually times out. Looking at the traceback, there's a BrokenResourceError happening in the stdout_reader coroutine at line 162 of mcp/client/stdio/init.py.
Expected behavior:
The client should successfully spawn the server, complete the initialize handshake, and be ready to call tools.
Actual behavior:
The client hangs during initialization and then times out with:
ExceptionGroup: unhandled errors in a TaskGroup (2 sub-exceptions)
BrokenResourceError at mcp/client/stdio/init.py:162 in stdout_reader
TimeoutError after waiting for initialize response
Additional cpontext:
Interesting finding: When I test the server directly by piping JSON to it, it works perfectly:
$ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | python test_server.py
The server immediately returns a valid response. So the server itself is working correctly - it can read from stdin and write to stdout just fine. The issue seems to be specifically with how stdio_client is handling the subprocess communication.
I've tried various things to fix it but nothing works:
- Running python with -u flag for unbuffered output
- Setting sys.stdout.reconfigure(line_buffering=True) in the server
- Using absolute paths
- Increasing timeout values
- Setting PYTHONUNBUFFERED=1
Note: HTTP/SSE transport works fine as an alternative.
Example Code
- Create a simple FastMCP server (test_server.py):
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("TestServer")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
if __name__ == "__main__":
mcp.run()- Create a client that uses stdio_client (test_client.py):
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def test():
params = StdioServerParameters(
command="python",
args=["test_server.py"]
)
async with stdio_client(params) as (stdio, write):
session = ClientSession(stdio, write)
await session.initialize() # Hangs here
result = await session.list_tools()
print(f"Tools: {result.tools}")
asyncio.run(test())- Run: python test_client.py
- Observe: hangs for about 10 seconds then fails with BrokenResourceError
Python & MCP Python SDK
- MCP SDK Version: 1.20.0
- Python Version: 3.12.7
- Operating System: macOS
- Installation method: pip install mcp==1.20.01