Repository navigation
MCP Server Hangs Indefinitely After KqueueSelector Log on macOS (Python 3.12, Both STDIO & SSE) #547
Description
Activity
Same issue with Python 3.10.17 and 3.12.3; although it hangs even earlier at this stage
... DEBUG Requirement already installed: mdurl==0.1.2 Audited 28 packages in 0.08ms DEBUG Using Python 3.10.17 interpreter at: .../.venv/bin/python3 DEBUG Running `python weather.py` DEBUG Spawned child 23168 in process group 23167 <-- HANGS -->surya-prakash-susarla commented
on May 30, 2025 ContributorMore actionsUsing fastmcp but I think the problem is coming from deeper. With Python 3.13, fastmcp==2.5.1 running this simple example:
from fastmcp import Client from src.config.config_manager import get_config_manager import asyncio import sys import os async def get_tools(): servers = get_config_manager().get_mcp_config().list_servers() print("servers: {servers}".format(servers=servers)) server = servers[1] print("Picking: {server}".format(server=server)) config = get_config_manager().get_mcp_config().get_server(server) final_config = { "mcpServers": { server: config.to_dict() } } print("Final generated config: {config}".format(config=final_config)) ''' Output: Final generated config: {'mcpServers': {'everything': {'command': 'npx', 'args': ['-y', '@modelcontextprotocol/server-everything']}}} ''' async with Client(final_config, timeout=10) as client: print("Blocked here, pid:{pid}".format(pid=os.getpid())) tools = await client.list_tools() print("Tools output: {tools}".format(tools=tools)) print("Starting the process") print("Current process pid: {pid}".format(pid=os.getpid())) asyncio.run(get_tools())This gets stuck in the stdio prompt
Hi thanks for this report, is this still an issue for you? Checking as it's been a while (apologies for the time it took to get back to this)
- addedbugSomething isn't workingSomething isn't workingneeds confirmationNeeds confirmation that the PR is actually required or needed.Needs confirmation that the PR is actually required or needed.
on Oct 6, 2025 - added a commit that references this issue
on Feb 16, 2026 Closing as not-a-bug — the behavior described is the stdio transport working as designed.
What's happening
Per the spec, "the client launches the MCP server as a subprocess" and the server "reads JSON-RPC messages from its standard input." When you run
python mcp_stdio_test.pydirectly in a terminal, there is no client — the server correctly blocks on stdin atstdio.py:58waiting for a JSON-RPC message that never arrives. It isn't hung; it's listening.Piping a valid
initializerequest produces an immediate response:$ echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}' | python server.py {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{...},"serverInfo":{...}}}
This matches how LSP and DAP servers behave (rust-analyzer, gopls, pylsp all do the same), and the TypeScript/Go/C# MCP SDKs are identical — none print a banner or detect a TTY.
The SSE claim
At the reported commit (
babb477),FastMCP.run()defaulted totransport="stdio". Callingmcp.run()with no arguments gives you stdio, not SSE — so you'd have observed the same behavior twice.For interactive testing
Use the MCP Inspector:
uv run mcp dev server.py— this launches a client for you. Or configure the server in Claude Desktop withuv run mcp install server.py. Both are covered in the README's Running Your Server section ahead of "Direct Execution."Comment thread
- @shreyass-ranganatha's
uv run weather.pyis the same scenario —uvspawns the script, which then waits on stdin. - @surya-prakash-susarla's
fastmcp.Client+npxhang is a separate client-side issue — see Thestdio_clienthangs indefinitely on session initialization #1452.
- @shreyass-ranganatha's
Describe the bug
When running an MCP server using
mcp-sdk(bothFastMCPand the low-levelServerwithmcp.server.stdio.stdio_server) on macOS with Python 3.12, the server process hangs indefinitely immediately after theDEBUG - Using selector: KqueueSelectorlog message appears. This happens during theserver.run()ormcp.run()call.The hang occurs regardless of whether the STDIO transport (
transport="stdio") or the default web/SSE transport is used. It also occurs even with a minimal server configuration with no custom tools, resources, or plugins registered.Environment:
pip install -e .from Git main branch usingmcp @ git+https://github.com/modelcontextprotocol/python-sdk.gitinpyproject.tomlwithhatchlingandallow-direct-references = true)To Reproduce
Steps to reproduce the behavior:
mcp-sdk(tested with version1.6.1.dev14+babb477installed from Git main branch) are installed in your environment on macOS.mcp_stdio_test.py:python mcp_stdio_test.pyAttempting server.run()...log message.Expected behavior
The server should successfully start, remain running, and be ready to accept MCP connections via STDIO (or SSE if run without
transport="stdio"). It should not hang during initialization.Screenshots
N/A - The issue is a process hang, the relevant output is text logs shown below.
Desktop:
Smartphone:
N/A
Additional context
FastMCP().run(...)and the low-levelServer().run(...)implementation.mcpinstalled from PyPI or directly from the Git main branch.uvicorn[standard]to0.30.3(a version used in a previously working commit) did not resolve the issue.time.sleep(10)before therun()call (which seemed to help in older commits) no longer prevents the hang.This strongly suggests an underlying issue within
mcp-sdk's core run logic or its interaction withasyncio/KqueueSelectoron macOS with recent Python versions or recentmcp-sdkversions. The hang point afterKqueueSelectorseems critical.Log Output Showing Hang: