[BUG] MCP server args containing `~` (tilde) cause ENOENT — tilde not expanded in stdio server arguments

Open 💬 6 comments Opened Mar 22, 2026 by coygeek

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

  1. Register an MCP server in ~/.claude.json with ~ in the args:

``json
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "uv",
"args": ["run", "--project", "~/path/to/my-project", "my-server-script"]
}
}
}
``

  1. Start Claude Code from a different directory (not the project directory):

``bash
cd ~/Desktop
claude
``

  1. Run /mcp — the server shows as ✘ failed.
  1. Run claude --debug and check the debug log — you'll see:

``
Server stderr: error: Failed to spawn:
my-server-script
Caused by: No such file or directory (os error 2)
``

  1. Now replace ~ with ${HOME} in the same config:

``json
"args": ["run", "--project", "${HOME}/path/to/my-project", "my-server-script"]
``

  1. 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 env field is not related — the issue occurs with or without "env": {}
  • The uv command itself handles ~ correctly when invoked from a shell or via Python's subprocess.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)

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗