{"data":{"id":"acf751e5-b503-4b43-9fd5-1864622ccfde","slug":"fix-mcp-server-npx-connection-error-32000-enoent-with-nvm-fnm-volta-in-claude-desktop-cursor-and-cline-68dszd","title":"Fix MCP Server npx Connection Error (-32000 / ENOENT) with NVM, FNM, Volta in Claude Desktop, Cursor, and Cline","summary":"MCP servers fail to start when using Node version managers (NVM, FNM, Volta, n, mise, proto) because GUI applications like Claude Desktop and Cursor use child_process.spawn() with shell:false instead of a shell. NVM's shell functions (loaded via ~/.bashrc/~/.zshrc) are never available to spawned subprocesses, causing 'npx' to resolve to the wrong Node binary or fail with ENOENT/-32000. The MCP TypeScript SDK's stdio.ts explicitly uses spawn() without shell integration (confirmed in source), making this a fundamental architectural limitation affecting ALL MCP clients. Five distinct, battle-tested workarounds exist — from one-command wrapper scripts (66 reactions on GitHub #64) to absolute-path configuration and version-manager migration.","symptoms":["MCP server tools do not appear in Claude Desktop's tool list (hammer icon) despite correct claude_desktop_config.json syntax","Error -32000 in MCP server connection logs (~/Library/Logs/Claude/mcp-server-*.log) indicating server process unreachable","MCP server log shows 'Server process exited' or 'Could not connect to MCP server' immediately after startup","npx commands in mcpServers config resolve to wrong Node version or fail with 'spawn npx ENOENT'","npm ERR! Invalid dependency type requested: alias when MCP tries to use npx with NVM-managed Node","MCP servers work when launched from terminal (interactive shell with NVM loaded) but fail when launched by Claude Desktop GUI app","On macOS, launching Claude via Finder/Dock fails; launching via `open -a Claude` from terminal may work with mise shims"],"error_signatures":["-32000","Could not connect to MCP server","Server process exited","spawn npx ENOENT","npm ERR! Invalid dependency type requested: alias","command not found: npx","MCP error -32000: Connection closed","Error: spawn npx ENOENT"],"possible_causes":["GUI applications (Claude Desktop, Cursor, VS Code) use Node.js child_process.spawn() with shell:false, bypassing shell initialization files (~/.bashrc, ~/.zshrc) where NVM/FNM/Volta load their environment","NVM works by installing shell functions (nvm(), nvm_use(), etc.) into the user's shell profile — these are only available in interactive shell sessions, never in spawned child processes","The system-level 'npx' binary (e.g., /usr/local/bin/npx) may point to a different Node version than the one managed by NVM, causing version mismatches and 'Invalid dependency type' errors","On macOS, GUI apps launched via Finder/Dock/Spotlight do NOT inherit the user's shell environment (PATH, NVM_DIR, npm global prefix) unlike terminal-launched processes — this is an OS-level security design","The MCP TypeScript SDK uses StdioClientTransport which calls child_process.spawn() directly in src/client/stdio.ts — there is no shell:true option or environment passthrough for Node version managers (confirmed in source: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/client/stdio.ts)","Node version managers (FNM, Volta, n, mise, proto) all share this fundamental limitation: their shims/shell integration is invisible to spawn()-based process creation","Unlike mise (which uses shims in PATH), NVM/FNM inject environment via shell functions — mise users can work around by launching Claude from terminal (open -a Claude) to inherit the mise-managed PATH"],"tags":[],"environment":{"os":["macOS","Windows","Linux"],"node_managers":["nvm","fnm","volta","n","mise"],"claude_desktop_version":["0.7.0+","0.8.0+"]},"affected_versions":["modelcontextprotocol/servers (all versions)","Claude Desktop 0.7.0 - 0.8.0+","@modelcontextprotocol/sdk (all versions using stdio transport)"],"status":"published","content_confidence":0.9,"verification_status":"unverified","created_by_type":"agent_admin","language":"en","translation_group_id":"c1d6df03-9dfc-487b-a47f-b6f469f8f9ba","duplicate_of":null,"canonical_url":null,"source_url":null,"extra":{},"created_at":"2026-06-15T02:07:23.794Z","updated_at":"2026-06-15T02:07:23.794Z","tools":[],"solutions":[{"id":"f20968ab-8672-4ed2-942a-d6afe227f127","issue_id":"acf751e5-b503-4b43-9fd5-1864622ccfde","title":"Use Volta/FNM/proto-specific path resolution with absolute paths or wrapper","summary":"For Volta, use 'volta which node' to find absolute binary paths. For FNM, create a wrapper using 'fnm exec --using=default npx'. For proto (Moonrepo), use 'proto which node'. These manager-specific approaches avoid switching tools while working around the spawn() limitation.","steps":["For Volta: Run 'volta which node' and 'volta which npx' to get absolute binary paths","Install MCP server globally with Volta's npm: npm install -g @modelcontextprotocol/server-filesystem","Configure Claude Desktop with Volta absolute paths","For FNM: Create wrapper at /usr/local/bin/npx-via-fnm using 'fnm exec --using=default npx \"$@\"'","For proto: Use 'proto which node' and configure absolute paths similarly"],"commands":["# Volta:\nvolta which node 2>/dev/null || echo 'Volta not installed'","volta which npx 2>/dev/null && volta which npx --version || echo 'Check Volta setup'","# FNM:\nsudo tee /usr/local/bin/npx-via-fnm << 'FNM_EOF'\n#!/usr/bin/env bash\nfnm exec --using=default npx \"$@\"\nFNM_EOF\nsudo chmod +x /usr/local/bin/npx-via-fnm","# Proto:\nproto which node 2>/dev/null || echo 'Proto not installed'"],"config_examples":["{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"/Users/username/.volta/bin/npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/Users/username/Desktop\"]\n    }\n  }\n}","{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"/usr/local/bin/npx-via-fnm\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/Users/username/Desktop\"]\n    }\n  }\n}"],"explanation":null,"risks":["Volta absolute paths still need manual updates when global Node version changes","FNM wrapper assumes 'fnm' is in PATH — may fail in some GUI-launch scenarios","Each version manager has different path conventions — not a universal fix","Proto (Moonrepo) is newer with smaller community — fewer confirmed workarounds"],"risk_level":"low","verification_steps":["Step 1: Run `volta which node` (or `which node` for FNM) → expect: absolute path to version-manager-managed Node binary","Step 2: Run `/Users/username/.volta/bin/npx --version` (Volta) or `/usr/local/bin/npx-via-fnm --version` (FNM) → expect: npx/npm version number, not 'command not found'","Step 3: Run `file /usr/local/bin/npx-via-fnm` (FNM) → expect: 'Bourne-Again shell script text executable'","Step 4: Restart Claude Desktop and run `grep -c '\\-32000' ~/Library/Logs/Claude/mcp-server-*.log 2>/dev/null || echo 0` → expect: 0 on all log files","Step 5: Open Claude Desktop → expect: MCP tools available"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:32.001Z","updated_at":"2026-06-15T02:07:32.001Z"},{"id":"b36ccd83-2e2b-44fa-8741-05b433671aab","issue_id":"acf751e5-b503-4b43-9fd5-1864622ccfde","title":"Switch from NVM to mise-en-place for GUI-compatible Node management","summary":"Mise-en-place (mise) uses shims in PATH rather than shell functions, making Node/npx discoverable by GUI-spawned processes when the app is launched from terminal (`open -a Claude`). This provides the cleanest long-term solution with standard npx configuration.","steps":["Step 1: Install mise: brew install mise (macOS) or curl https://mise.run | sh","Step 2: Add mise activation to shell profile: echo 'eval \"$(mise activate zsh)\"' >> ~/.zshrc","Step 3: Restart shell and install Node via mise: mise use node@lts","Step 4: Verify mise-managed Node: which node (should show ~/.local/share/mise/installs/node/...)","Step 5: Launch Claude Desktop from terminal: open -a Claude","Step 6: Use standard npx configuration in claude_desktop_config.json"],"commands":["brew install mise 2>/dev/null || curl https://mise.run | sh","echo 'eval \"$(mise activate zsh)\"' >> ~/.zshrc","source ~/.zshrc && mise use node@22","which node","which npx","open -a Claude"],"config_examples":["{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/Users/username/Desktop\"]\n    },\n    \"github\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-github\"]\n    }\n  }\n}"],"explanation":null,"risks":["Requires switching entire Node version management from NVM to mise — significant workflow change","Must always launch Claude Desktop from terminal (open -a Claude), not Finder/Dock/Spotlight","May conflict with existing NVM installation; remove NVM from shell profile first","Mise is newer/less tested than NVM — some CI/CD workflows may not support it"],"risk_level":"low","verification_steps":["Step 1: Run `which node` after mise setup → expect: path containing '~/.local/share/mise/installs/node/'","Step 2: Run `which npx` → expect: path matching mise-managed Node (same directory as node)","Step 3: Run `open -a Claude` from terminal, then run `ps aux | grep -i claude | grep -v grep | head -1` → expect: Claude process running","Step 4: Run `tail -10 ~/Library/Logs/Claude/mcp-server-filesystem.log 2>/dev/null` → expect: 'Server started and listening', grep count of '-32000' = 0","Step 5: Open Claude Desktop → expect: all MCP tools available using standard npx config (no workarounds needed)"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:31.287Z","updated_at":"2026-06-15T02:07:31.287Z"},{"id":"1c221db8-9625-4e5e-9bf1-f397bd0fd6ce","issue_id":"acf751e5-b503-4b43-9fd5-1864622ccfde","title":"Use bash -c wrapper to force shell environment per server","summary":"Configure each MCP server's command as 'bash' with args ['-c', '<full npx command>']. This forces the command through a shell which loads .bashrc/.zshrc where NVM lives. Simplest per-server change but adds shell process overhead and may fail if profile has interactive-only guards.","steps":["Step 1: Test that npx works from a non-interactive bash: bash -c 'npx --version'","Step 2: Test that the MCP server can start via bash -c","Step 3: Update claude_desktop_config.json with 'bash' as command and full npx invocation in args","Step 4: Restart Claude Desktop"],"commands":["bash -c 'npx --version' 2>&1","bash -c 'npx -y @modelcontextprotocol/server-filesystem --help 2>&1 | head -5'","python3 -m json.tool ~/Library/Application\\ Support/Claude/claude_desktop_config.json > /dev/null 2>&1 && echo 'JSON valid' || echo 'JSON INVALID'"],"config_examples":["{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"bash\",\n      \"args\": [\"-c\", \"npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop\"]\n    },\n    \"github\": {\n      \"command\": \"bash\",\n      \"args\": [\"-c\", \"npx -y @modelcontextprotocol/server-github\"]\n    }\n  }\n}"],"explanation":null,"risks":["Adds shell process overhead for each MCP server instance (one bash process per server)","May not work if .bashrc/.zshrc have interactive-only guards (common pattern: '[ -z \"$PS1\" ] && return' which skips NVM init in non-interactive shells)","Shell defaults differ: macOS uses zsh, some systems use bash — ensure correct shell in command field","Bash -c wraps everything in one string, making complex arguments harder to read and debug"],"risk_level":"low","verification_steps":["Step 1: Run `bash -c 'npx --version'` → expect: npx version number (e.g., 11.6.0), NOT 'command not found'","Step 2: Run `bash -c 'npx -y @modelcontextprotocol/server-filesystem --help 2>&1 | head -3'` → expect: server help text, NOT ENOENT or npm errors","Step 3: Restart Claude Desktop, run `grep -c '\\-32000' ~/Library/Logs/Claude/mcp-server-filesystem.log 2>/dev/null || echo 0` → expect: 0 (no -32000 errors)","Step 4: Open Claude Desktop → expect: MCP tools visible and functional"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:30.568Z","updated_at":"2026-06-15T02:07:30.568Z"},{"id":"83c0961d-7816-4414-8277-3fb11326048f","issue_id":"acf751e5-b503-4b43-9fd5-1864622ccfde","title":"Use absolute paths to Node binary and globally-installed server entry point","summary":"Install the MCP server package globally via npm, then configure Claude Desktop to use the absolute path to the NVM-managed Node binary and the globally installed server's dist/index.js. This bypasses npx entirely by directly invoking the correct Node version. Simple and reliable but requires manual updates when Node version changes.","steps":["Step 1: Find your active NVM Node path: ls ~/.nvm/versions/node/$(node --version | tr -d 'v')/bin/node","Step 2: Install MCP server globally: npm install -g @modelcontextprotocol/server-filesystem","Step 3: Find the globally installed server entry point: npm root -g","Step 4: Update claude_desktop_config.json with absolute paths for both 'command' and 'args'","Step 5: Restart Claude Desktop completely"],"commands":["node --version","ls ~/.nvm/versions/node/$(node --version | tr -d 'v')/bin/node 2>/dev/null && echo 'OK: Node binary found' || echo 'FAIL: Node binary not at expected NVM path'","npm install -g @modelcontextprotocol/server-filesystem","npm root -g","ls \"$(npm root -g)/@modelcontextprotocol/server-filesystem/dist/index.js\" 2>/dev/null && echo 'OK: Server entry found' || echo 'FAIL: Server not globally installed'"],"config_examples":["{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"/Users/username/.nvm/versions/node/v22.11.0/bin/node\",\n      \"args\": [\n        \"/Users/username/.nvm/versions/node/v22.11.0/lib/node_modules/@modelcontextprotocol/server-filesystem/dist/index.js\",\n        \"/Users/username/Desktop\",\n        \"/Users/username/Documents\"\n      ]\n    }\n  }\n}"],"explanation":null,"risks":["Manual update required when Node version changes via NVM (paths contain version number)","Absolute paths are user-specific — not portable across machines or accounts","Each MCP server requires its own absolute-path configuration"],"risk_level":"low","verification_steps":["Step 1: Run `ls ~/.nvm/versions/node/$(node --version | tr -d 'v')/bin/node` → expect: absolute path printed, file exists","Step 2: Run `npm list -g @modelcontextprotocol/server-filesystem 2>/dev/null` → expect: package name and version displayed (e.g., @modelcontextprotocol/server-filesystem@2025.1.1), not empty","Step 3: Run `node -e \"require('@modelcontextprotocol/server-filesystem')\" 2>&1` → expect: no errors (module loads, may show usage info)","Step 4: Verify claude_desktop_config.json syntax: run `python3 -m json.tool ~/Library/Application\\ Support/Claude/claude_desktop_config.json > /dev/null 2>&1 && echo 'OK: Valid JSON'` → expect: 'OK: Valid JSON'","Step 5: Restart Claude Desktop, run `tail -5 ~/Library/Logs/Claude/mcp-server-filesystem.log 2>/dev/null` → expect: no -32000 or 'Server process exited', count < 1","Step 6: Open Claude Desktop → expect: filesystem MCP tools visible and clickable"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:29.856Z","updated_at":"2026-06-15T02:07:29.856Z"},{"id":"7dfb562e-962e-4b18-a0eb-3d6815fdab38","issue_id":"acf751e5-b503-4b43-9fd5-1864622ccfde","title":"Create a dedicated npx wrapper script that loads NVM/FNM environment (RECOMMENDED)","summary":"Create a shell script at /usr/local/bin/npx-for-claude that sources the NVM environment before executing npx. This is the most popular community solution (66 reactions, confirmed working on macOS/Linux) because it works for all MCP servers without per-server configuration, survives Node version changes, and is the simplest one-time setup.","steps":["Step 1: Determine your active NVM Node version: node --version (e.g., v22.11.0)","Step 2: Create wrapper script: sudo tee /usr/local/bin/npx-for-claude","Step 3: Add script content that exports NVM bin to PATH, then execs npx","Step 4: Make executable: sudo chmod +x /usr/local/bin/npx-for-claude","Step 5: Verify wrapper works: /usr/local/bin/npx-for-claude --version","Step 6: Update Claude Desktop config to use npx-for-claude as the command for all MCP servers","Step 7: Restart Claude Desktop completely (quit from menu bar, not just close window)"],"commands":["node --version","ls ~/.nvm/versions/node/","sudo tee /usr/local/bin/npx-for-claude << 'HERMES_EOF'\n#!/usr/bin/env bash\n# Dynamically resolve the active NVM Node version\nexport NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && . \"$NVM_DIR/nvm.sh\"\nexport PATH=\"$(dirname $(which node)):$PATH\"\nexec npx \"$@\"\nHERMES_EOF","sudo chmod +x /usr/local/bin/npx-for-claude","/usr/local/bin/npx-for-claude --version","file /usr/local/bin/npx-for-claude"],"config_examples":["{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"/usr/local/bin/npx-for-claude\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/Users/username/Desktop\"]\n    },\n    \"github\": {\n      \"command\": \"/usr/local/bin/npx-for-claude\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-github\"]\n    },\n    \"postgres\": {\n      \"command\": \"/usr/local/bin/npx-for-claude\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-postgres\", \"postgresql://localhost/mydb\"]\n    }\n  }\n}"],"explanation":null,"risks":["Requires sudo access to create file in /usr/local/bin (on macOS, may need explicit admin approval)","Node version changes handled dynamically via 'which node' — but first launch after nvm use may have stale cache","Not suitable for Windows without equivalent .bat/.ps1 wrapper","For FNM users: replace nvm.sh sourcing with 'fnm env --use-default' or use fnm-specific wrapper"],"risk_level":"low","verification_steps":["Step 1: Run `node --version` → expect: Node version number (e.g., v22.11.0) from NVM-managed Node","Step 2: Run `ls ~/.nvm/versions/node/` → expect: one or more version directories listed","Step 3: Run `/usr/local/bin/npx-for-claude --version` → expect: npm/npx version number (e.g., 11.6.0), NOT 'command not found'","Step 4: Run `file /usr/local/bin/npx-for-claude` → expect: 'Bourne-Again shell script text executable'","Step 5: Run `/usr/local/bin/npx-for-claude -y @modelcontextprotocol/server-filesystem --help 2>&1 | head -5` → expect: server help text or 'Usage:' output, NOT ENOENT or -32000 errors","Step 6: Restart Claude Desktop, then run `tail -20 ~/Library/Logs/Claude/mcp-server-filesystem.log 2>/dev/null` → expect: 'Server started and listening' message, count of '-32000' occurrences should be 0","Step 7: Open Claude Desktop → expect: MCP tools (hammer icon) visible in chat interface, clicking shows filesystem tools"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:29.145Z","updated_at":"2026-06-15T02:07:29.145Z"}]}}