DEV Community

Muhammad Moeed
Muhammad Moeed

Posted on Originally published at moeed.app

spawn npx ENOENT and 9 Other MCP Errors, Explained in Plain English

You added an MCP server to your config, restarted the app, and one of these happened:

  • Nothing showed up at all.
  • The server showed up and then died with MCP error -32000: Connection closed.
  • Every tool call hits Request timed out after 60 seconds.
  • You got spawn npx ENOENT and no idea what "ENOENT" even means.

I hit all four in one week. So I sat down with the Claude Code changelog, ~20 open anthropics/claude-code GitHub issues, the MCP debugging docs, and a bunch of Reddit and Stack Overflow threads, and wrote a plain-English fix guide.

Here is the short version.

The 4 things that fix 80% of MCP failures

Before you Google a specific error, try these:

  1. Fully quit the client, then relaunch. Cmd+Q on macOS. On Windows right-click the tray icon and click Quit. Closing the window is not enough. Config only reloads on a cold start.
  2. Run your config file through a JSON linter. A single missing comma, an unescaped Windows backslash, or the wrong top-level key silently breaks the whole file. No error dialog, no servers register.
  3. Replace bare npx with an absolute path. On Mac/Linux run which npx and paste the full path (something like /Users/you/.nvm/versions/node/v22.14.0/bin/npx). On Windows use cmd /c npx or point directly at node.exe.
  4. Check the logs. Mac: tail -F ~/Library/Logs/Claude/mcp*.log. Windows: %APPDATA%\Claude\logs\. Claude Code CLI: claude --debug=mcp then read ~/.claude/debug/<session-id>.txt.

The single most common MCP error

spawn npx ENOENT is the #1 setup failure. It shows up in 30+ MCP repos. Here is why it happens.

Your terminal shells (zsh, bash) source ~/.zshrc or ~/.bashrc on startup. That is where nvm adds its bin directory to your PATH. So npx works in your terminal.

GUI apps like Claude Desktop do NOT source those shell files. They launch with a minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin) that excludes nvm, mise, fnm, and Homebrew. So npx is not on the client's PATH. The child_process.spawn call fails with ENOENT (Error NO ENTity, meaning "file does not exist").

Two ways to fix it. Either paste the absolute path from which npx as the command in your config, or add a per-server env block that gives the child process a working PATH. Full recipe (with Windows and NVM variants) is in the guide.

What is in the full guide

  • 10 named errors with the exact copy-paste text you see and the fix steps for each:

    • MCP error -32000: Connection closed
    • MCP error -32001: Request timed out
    • spawn npx ENOENT
    • spawn EINVAL (Windows only)
    • Server transport closed unexpectedly
    • Could not attach to MCP server <NAME>
    • -32601 Method not found
    • -32602 Invalid params
    • Failed to connect in claude mcp list
    • OAuth 401 / authorization with MCP server failed
  • Per-platform gotchas for Claude Desktop on macOS and Windows (including the MSIX / Microsoft Store virtualized-path trap that opens the WRONG config file), Claude Code CLI, VS Code, Cursor, Node with NVM/mise/fnm, and corporate networks with proxies and OAuth.

  • 7-step diagnostic checklist if your specific error is not in the catalog.

  • 8 H3 FAQs matching the exact questions people paste into Google.

Read the full guide here: MCP Server Not Connecting? 10 Fixes That Actually Work.

If you have hit an MCP error not in the list, drop it in the comments and I will add it in the next update.

Top comments (1)

Collapse
 
mihai_leanzero profile image
Mihai Perdum

The ENOENT/PATH one is real. Worth the space you gave it. One more that isn't PATH-related: a stdio MCP server that writes anything to stdout outside the JSON-RPC frames breaks the transport instantly. A stray console.log is enough. So is a dependency that logs to stdout on init. The client reads it as a malformed message and reports the connection closed, not invalid input, so it looks exactly like the ENOENT case even when the binary is fine. Cost me an afternoon before I moved every log line to stderr.