Stdio MCP server cwd field silently ignored on Windows (2.1.123)
Description
On Windows, the cwd field in a stdio MCP server config (.mcp.json or
user-scope mcpServers in ~/.claude.json) is silently ignored when Claude
Code spawns the server. The subprocess inherits the parent process's cwd
instead of the configured value. This breaks any server that uses
cwd-relative paths to locate its script file or its data directories.
The failure presents as ✗ Failed to connect in claude mcp list with no
surface-level explanation. The real cause is only visible by running withDEBUG=true and inspecting the debug log, which shows the spawned Python
interpreter reporting it cannot find server.py because it's looking in the
wrong directory.
A second, compounding failure mode (covered partially by #46360):
when working around the first by using absolute paths for both the
interpreter AND the script, the recommended cmd /c <python> <script>
Windows wrapper hits cmd.exe's "old-behavior" quote-stripping rule (≥2
quoted args triggers it), producing'c:\Users\noahr\code' is not recognized as an internal or external command.
The wrapper that's supposed to make Windows work makes Windows worse once
both args have spaces. Dropping the wrapper (using direct interpreter +
absolute script path with no cmd /c) is what works — same workaround as
#46360 Bug 2, but the diagnostic path is different.
Steps to Reproduce
- Windows 11 (10.0.26200), Claude Code 2.1.123 (CLI binary AND VS Code extension bundle).
- Create a Python MCP server at
C:\some\path with spaces\my-server\server.py. - Add to
.mcp.jsonin some other directory (e.g. a repo root):
``json``
{
"mcpServers": {
"demo": {
"type": "stdio",
"command": "cmd",
"args": ["/c", "C:\some\path with spaces\my-server\.venv\Scripts\python.exe", "server.py"],
"cwd": "C:\some\path with spaces\my-server"
}
}
}
- Run
DEBUG=true CLAUDE_CODE_DEBUG_LOGS_DIR=/tmp/log claude mcp listfrom
the repo root (NOT the server dir).
- Observe
✗ Failed to connectand, in the debug log:
````
Server stderr: python.exe: can't open file 'C:\<repo-root>\server.py': [Errno 2] No such file or directory
Expected Behavior
Claude Code should set the spawned subprocess's working directory to thecwd value from the config, so that relative server.py (and any
cwd-relative data paths the server uses) resolve correctly. This matches
how vanilla child_process.spawn(cmd, args, {cwd}) in Node behaves.
Actual Behavior
The subprocess inherits the parent's cwd. The cwd field in the config
has no effect.
Workaround
Drop the cmd /c wrapper, use bare interpreter + absolute path to the
script:
{
"command": "C:\full\path\python.exe",
"args": ["C:\full\path\server.py"]
}
And ensure each server itself usesos.path.dirname(os.path.abspath(__file__)) for any data lookups, sincecwd still won't be set on the spawned process.
Environment
- OS: Windows 11 Home 10.0.26200 (win32-x64)
- Claude Code CLI: 2.1.123 (both
~/.local/bin/claude.exeand
~/.vscode/extensions/anthropic.claude-code-2.1.123-win32-x64/resources/native-binary/claude.exe)
- VS Code extension: 2.1.123
- Affected: every stdio MCP server defined with relative script path +
cwd - Diagnostic-visibility prerequisite:
DEBUG=trueenv var; otherwise
claude mcp list reports only ✗ Failed to connect
Related
- #46360 — Windows
claude mcp add/cflag mangling + workaround
(different root cause, same workaround shape)
- #49133 — Silent-failure UX gap meta-issue (macOS-flagged but applies on
Windows too — confirms the diagnostic-discoverability problem)
Suggested Labels
bug, area:mcp, platform:windows, has repro
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗