[BUG] MCP server args containing `~` (tilde) cause ENOENT — tilde not expanded in stdio server arguments
What's Wrong?
MCP servers configured in ~/.claude.json (user scope) with ~ (tilde) in the args array fail to connect with ENOENT (No such file or directory). Claude Code does not expand ~ in MCP server arguments before passing them to the spawned process.
The ~ works correctly in .mcp.json when the user launches Claude Code from the project directory (because the project-level config takes precedence and the tilde happens to resolve correctly via uv's own tilde handling). But when Claude Code spawns the MCP server process from a different working directory using the global config, the ~ is passed literally and causes an ENOENT failure.
Workaround: Use ${HOME} instead of ~ in MCP server args. Claude Code correctly expands ${HOME} in both ~/.claude.json and .mcp.json.
What Should Happen?
Claude Code should expand ~ to the user's home directory in MCP server args (and command), consistent with how ${HOME} is already expanded. This is standard Unix behavior — users expect ~ to resolve to their home directory in path arguments.
Error Messages/Logs
From claude --debug:
2026-03-22T21:41:55.216Z [DEBUG] MCP server "github-repo-database": Starting connection with timeout of 30000ms
2026-03-22T21:41:55.375Z [ERROR] MCP server "github-repo-database" Server stderr: error: Failed to spawn: `github-repo-database-mcp`
Caused by: No such file or directory (os error 2)
2026-03-22T21:41:55.378Z [DEBUG] MCP server "github-repo-database": Connection failed after 163ms: MCP error -32000: Connection closed
2026-03-22T21:41:55.378Z [ERROR] MCP server "github-repo-database" Connection failed: MCP error -32000: Connection closed
The /mcp dialog shows: github-repo-database · ✘ failed
Steps to Reproduce
- Register an MCP server in
~/.claude.jsonwith~in the args:
``json``
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "uv",
"args": ["run", "--project", "~/path/to/my-project", "my-server-script"]
}
}
}
- Start Claude Code from a different directory (not the project directory):
``bash``
cd ~/Desktop
claude
- Run
/mcp— the server shows as✘ failed.
- Run
claude --debugand check the debug log — you'll see:
``my-server-script
Server stderr: error: Failed to spawn: ``
Caused by: No such file or directory (os error 2)
- Now replace
~with${HOME}in the same config:
``json``
"args": ["run", "--project", "${HOME}/path/to/my-project", "my-server-script"]
- Start a new Claude Code session — the server connects successfully.
Note: The same ~ path works correctly when run manually in a terminal (the shell expands ~ before passing it to the command). The issue is specific to how Claude Code spawns the MCP server process (Node.js child_process.spawn without shell, which does not expand ~).
Is this a regression?
I don't know
Claude Code Version
2.1.81
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Ghostty 1.3.1
Additional Information
- The issue affects both
~/.claude.json(user scope) and.mcp.json(project scope) configs ${HOME}expansion works correctly as a workaround in both config files- The
envfield is not related — the issue occurs with or without"env": {} - The
uvcommand itself handles~correctly when invoked from a shell or via Python'ssubprocess.run()— the issue is that Claude Code's Node.js process spawner passes~as a literal character, and the child process receives~without HOME context to resolve it - Tested on macOS Darwin 25.3.0, Apple Silicon (aarch64)
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗