You run your MCP server by hand, it starts, nothing crashes. You add it to Claude Desktop, Cursor or another client and it shows up red, "failed", or connects and then no tool works.
Almost always the server is fine. The difference is the environment the client launches it in. These are the seven causes we keep hitting, roughly in order of how often.
1. Something writes to stdout
With the stdio transport, stdout IS the protocol. Every byte on it must be a JSON-RPC message. One console.log("server started"), a banner from a library, or a deprecation warning printed to stdout, and the client fails to parse the stream.
Fix: send all logs to stderr (console.error in Node, print(..., file=sys.stderr) in Python, the logging module defaults to stderr). Clients usually capture stderr into their log file, so you lose nothing.
2. The client does not have your shell's PATH
On macOS, an app started from the Dock or Finder does not read .zshrc or .bash_profile. It gets the minimal launchd PATH, /usr/bin:/bin:/usr/sbin:/sbin. If node came from Homebrew (/opt/homebrew/bin) or nvm (~/.nvm/versions/...), the client cannot find npx or node, and you get spawn npx ENOENT.
Fix, pick one:
- Use the absolute path as the command: run
which npxin your terminal and paste the result. - Set PATH explicitly in the server's
envblock in the client config.
With nvm, the absolute path also pins the Node version, which avoids cause 6.
3. Your environment variables are not there either
The same applies to API keys and settings you exported in your shell. The server process only gets what the client passes it.
Fix: put them in the env block of that server's config entry, not in your shell profile.
4. npx is waiting or still downloading
npx some-package on a machine that does not have it cached first downloads it. Without -y it can stop to ask "Ok to proceed?", and nobody is there to answer. Even with -y, a slow first download can outlast the client's startup timeout, so the first launch fails and the second one works.
Fix: always npx -y, and run the exact command once in a terminal so the package is cached before the client starts it.
5. Relative paths and the working directory
Clients do not promise a working directory. On macOS it is often /. A server that opens ./config.json or writes ./data.db works from your project folder and fails everywhere else.
Fix: absolute paths in args, or resolve paths relative to the script file, not the current directory.
6. A different Node or Python than you think
Your terminal uses the version from nvm, pyenv or a virtualenv. The client may hit the system one, or an old Homebrew one. Syntax errors at import time or "unsupported engine" warnings in the log are the sign.
Fix: point the command at the exact interpreter (/path/to/venv/bin/python, the nvm node), not a bare python or node.
7. Windows: npx is not an executable
On Windows npx is npx.cmd, a batch file, and some clients spawn the command without a shell, so "command": "npx" fails.
Fix: launch it through cmd:
{
"command": "cmd",
"args": ["/c", "npx", "-y", "your-mcp-package"]
}
Where to look first
-
Claude Desktop logs:
~/Library/Logs/Claude/on macOS (mcp.logplus onemcp-server-<name>.logper server),%APPDATA%\Claude\logson Windows. Your stderr ends up there. -
Claude Code:
claude mcp listshows which servers connect, and/mcpinside a session shows their status. -
MCP Inspector:
npx @modelcontextprotocol/inspector <your command> <args>starts the server the way a client would and lets you call each tool by hand. If it works there and not in the client, the problem is the client's environment (causes 2 to 6). - Restart for real. Most clients read the config only at startup. On macOS that means Cmd+Q, not closing the window.
A 30-second checklist
- Nothing but JSON-RPC on stdout?
- Command is an absolute path, or PATH is set in
env? - API keys in the config's
env, not only in your shell? -
npx -y, and the package already cached? - No relative paths?
- The interpreter the client runs is the one you tested with?
- On Windows,
cmd /c npx?
Why we wrote this
We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer and your Android phone (beta). It is launched with npx -y @autenai/mcp, so every item on this list is a support question we have either hit ourselves or expect to.
Hit an eighth cause? Put it in the comments and we will add it.
Top comments (0)