Windows: Python stdio MCP servers fail handshake — stdout response never received by rmcp client
What version of Codex is running?
codex-cli v0.142.0-alpha.6 (also tested v0.141.0)
What subscription do you have?
N/A — using Ollama as backend (glm-5.2:cloud)
Which model were you using?
glm-5.2:cloud (via Ollama OpenAI-compatible endpoint)
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64
What issue are you seeing?
Python-based stdio MCP servers fail the JSON-RPC handshake on Windows. The server starts successfully, loads all tools (visible in stderr logs), and writes the initialize response to stdout — but Codex's Rust MCP client (rmcp) never receives it.
Error:
MCP startup failed: handshaking with MCP server failed: connection closed: initialize response
Key Evidence
- ✅ The Python MCP server (workspace-mcp / FastMCP) starts and loads 9 tools correctly — all visible in stderr
- ✅ The
initializeJSON-RPC response IS written to stdout (verified via manual shell pipe test) - ✅ Node.js-based MCP servers work fine (e.g.,
node_repl) — this is Python-specific - ❌ Codex's
rmcpclient never logsService initialized as clientfor the Python server - ❌ Only
node_replgetsService initialized; the Python server is silently dropped
What steps can reproduce the bug?
- Configure a Python-based MCP server in
~/.codex/config.toml:
[mcp_servers.gdrive]
command = 'C:\path\to\python.exe'
args = ['-u', 'path/to/launcher.py']
startup_timeout_sec = 120
- The Python launcher imports FastMCP/MCP SDK and runs in stdio mode:
sys.argv = ['workspace-mcp', '--tools', 'drive', '--transport', 'stdio']
from main import main
main()
- Start Codex (Desktop or
codex exec)
- Observe:
- Server stderr shows successful startup (tools loaded, auth configured)
Service initialized as clientis logged fornode_replbut NOT for the Python server- Error:
handshaking with MCP server failed: connection closed: initialize response
Debug log output
Running with RUST_LOG=debug codex exec shows:
INFO codex_rmcp_client::stdio_server_launcher: MCP server stderr (python.exe): INFO:auth.google_auth:Using credentials directory...
INFO codex_rmcp_client::stdio_server_launcher: MCP server stderr (python.exe): [TOOLS] Tool tier 'core' loaded: 9 tools across 1 services [['drive']]
INFO codex_rmcp_client::stdio_server_launcher: MCP server stderr (python.exe): [REGISTRY] Tool filtering: removed 13 tools, 9 enabled. Mode: Read-Only
INFO serve_inner: rmcp::service: Service initialized as client peer_info=Some(InitializeResult { ... server_info: Implementation { name: "rmcp" ...}) ← only node_repl
WARN codex_mcp::rmcp_client: failed to initialize MCP client during shutdown: MCP startup failed: handshaking with MCP server failed: connection closed: initialize response
What was tried (all failed)
| Approach | Result |
|----------|--------|
| uvx workspace-mcp | Same — sandbox also blocks AppData |
| Direct workspace-mcp.exe (pip wrapper) | Same |
| python.exe -u + PYTHONUNBUFFERED=1 | Same |
| .bat wrapper around python | Same |
| cmd.exe /c python.exe | Same |
| Node.js wrapper spawning Python with stdio: inherit | Same |
| Python sys.stdout.reconfigure(line_buffering=True) | Same |
Root Cause Hypothesis
This appears to be a Windows pipe compatibility issue between Python's stdout and Codex's Rust MCP client (rmcp). The MCP SDK's stdio writer (mcp/server/stdio.py) uses:
stdout = anyio.wrap_file(TextIOWrapper(sys.stdout.buffer, encoding="utf-8"))
# ...
await stdout.write(json + "\n")
await stdout.flush()
On Windows, Python's sys.stdout.buffer may not properly flush to the pipe created by Codex's Rust process, even with PYTHONUNBUFFERED=1 and -u. The anyio async wrapper adds another layer of buffering.
This is related to #7155 (Windows stderr MCP issue) and #24439 (diagnostic command request), but specifically affects Python stdout to Rust stdin pipe on Windows during the initial handshake.
Node.js-based MCP servers don't have this issue because Node handles Windows pipes differently.
Workaround
Use a direct CLI script (shell command) instead of MCP — Codex calls Python via codex exec shell tool, bypassing the MCP protocol entirely. This works but loses MCP's benefits (tool auto-discovery, persistent connection, etc.).
Expected behavior
Python stdio MCP servers should complete the handshake on Windows, same as Node.js servers.
Related issues
- #7155 — Windows stderr MCP
Transport closed(same rmcp client, stderr blocking) - #24439 — Request for
codex mcp checkdiagnostic command - #6020 — Broad
initialize responsefailures (42 comments) - #3510 — MCP servers not working on Windows (closed)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗