DEV Community

Auten
Auten

Posted on Edited on

Your MCP server works in the terminal but not in Claude Desktop or Cursor: 8 causes

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 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 npx in your terminal and paste the result.
  • Set PATH explicitly in the server's env block 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"]
}
Enter fullscreen mode Exit fullscreen mode

8. It is configured for a different project (Claude Code)

Added from the comments, thanks to @heyitsjakub. claude mcp add uses the local scope by default: the server is registered for the project you ran it in, and nowhere else. Open another project and it looks like the server vanished, while the config is fine.

Fix: run claude mcp list inside the project where it is missing. For every project, add it with --scope user. To share it with your team, use --scope project, which writes a .mcp.json at the repo root (Claude Code asks each person to approve it once). Cursor has the same split: ~/.cursor/mcp.json for all projects, .cursor/mcp.json for one.

Where to look first

  • Claude Desktop logs: ~/Library/Logs/Claude/ on macOS (mcp.log plus one mcp-server-<name>.log per server), %APPDATA%\Claude\logs on Windows. Your stderr ends up there.
  • Claude Code: claude mcp list shows which servers connect, and /mcp inside 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?
  • In Claude Code, added in the right scope?

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 another cause? Put it in the comments and we will add it.

Top comments (4)

Collapse
 
heyitsjakub profile image
Jakub Hecht •

Another possible reason is the scope configuration.
By default, claude mcp add adds the server only to the current project. This means that when you open a different project, the server might not be available there.
So, it may look like the server has disappeared, even though it is still configured correctly. You can check this by running claude mcp list. If you want the server to be available across multiple projects, you can use --scope user when adding it.

Collapse
 
autenai profile image
Auten •

Good one, thanks. That "it disappeared" moment looks exactly like a broken server, so it belongs on this list.

One addition: there is also --scope project, which writes a .mcp.json at the repo root. It is meant to be committed, so everyone on the team gets the server, and Claude Code asks each person to approve it the first time. Cursor has the same split: ~/.cursor/mcp.json for all projects, .cursor/mcp.json inside one project.

Collapse
 
heyitsjakub profile image
Jakub Hecht •

Thanks for adding that to the article. Distinguishing personal and team scopes is super useful, and I really like the Cursor example too.

Thread Thread
 
autenai profile image
Auten •

Glad it helped, and thanks again for the tip. One small extra for anyone debugging this: claude mcp get <name> prints which scope a server lives in, so you can see at a glance whether it is local, project or user before re-adding it.