An MCP server that won’t connect is one of the most common Claude Code frustrations, and it’s almost always one of a handful of causes. The good news: the failures are predictable, and a quick diagnostic routine finds the culprit fast. This guide walks the usual suspects in the order worth checking them, with the fix for each.
Most reports come down to four things: the Windows npx wrapper, a launch command that’s wrong, a missing credential, or a server writing to the wrong stream. We’ll cover those plus the steps to tell which one you’ve got. For the clean setup that avoids most of these, see the MCP setup guide.
First: see the actual status
Before guessing, look. Two commands tell you most of what you need.
Inside a session:
/mcp
That shows each server’s connection status and, for connected ones, the tools they expose. From the terminal:
claude mcp list
That lists configured servers and whether they connected. A server showing “failed” or “disconnected” is your starting point — note which one, then work through the causes below.
Cause 1: the Windows npx wrapper (the big one)
If a server connects in WSL but fails on native Windows, this is almost certainly it. Tools installed by npm — including npx — are .cmd shim files on Windows, and Claude Code can’t always spawn them directly the way it spawns a real executable. The server fails to launch.
The fix is to run through the command interpreter with cmd /c:
claude mcp add filesystem -- cmd /c npx -y @modelcontextprotocol/server-filesystem C:\Users\YourName\project
The cmd /c prefix lets Windows resolve the .cmd shim. Inside WSL you do not use it — npx is a normal Linux binary there. If you’ve copied a command between environments, this mismatch is often the cause.
npx by environment
| Native Windows | Prefix with cmd /c — npx is a .cmd shim |
|---|---|
| WSL / Linux | No wrapper — npx is a normal executable |
| Symptom of getting it wrong | Works in one environment, fails to spawn in the other |
Cause 2: a wrong command or path
If running the launch command yourself errors, the command is the problem. Common variants:
- Bad package name. A typo or a package that doesn’t exist. Confirm the exact name in the MCP docs or the server’s own page.
- Wrong path argument. A filesystem server pointed at a directory that doesn’t exist, or a Windows path used in WSL (or vice versa). Use Windows paths in Windows, Linux paths in WSL.
- Built file missing. For a server you built yourself, the path points at a
dist/index.jsthat wasn’t compiled. Re-run the build.
Cause 3: PATH problems
If npx or node “isn’t found” but you know it’s installed, the shell’s PATH is stale or the global npm bin isn’t on it.
- Reopen the terminal after installing Node so the updated PATH loads. A surprising number of “command not found” failures are just a terminal that predates the install.
- Check the npm global bin with
npm config get prefixand confirm it’s on your PATH. - In WSL, make sure you’re using the WSL-installed Node, not accidentally reaching for a Windows one across the boundary.
Cause 4: authentication failures
A server that connects but reports auth errors, or repeatedly asks for credentials, isn’t getting its token.
- Is the env var set in the right shell? The variable has to exist in the same shell that launches Claude Code. Setting it in one terminal and starting Claude in another won’t work — on Windows, use
setxand reopen for persistence. - Is it spelled correctly? A mismatch between the variable name in your config and the one you set is a frequent, easy-to-miss cause.
- Has the token expired? Fine-grained tokens have expirations. An expired GitHub or API token presents exactly as an auth failure.
- For HTTP servers, confirm the auth header is actually being passed in the add command.
The GitHub MCP setup guide has a worked example of token-based auth if that’s the server you’re fighting.
Cause 5: connects but no tools, or instantly drops
A server that shows connected but exposes nothing, or connects then dies, usually started and then errored internally. Two frequent reasons:
- Stdout corruption. Under stdio transport, stdout carries the protocol messages. If the server — or your own, if you built it — writes logs to stdout, it corrupts the stream and the connection breaks. Debug output must go to stderr. This is the number-one bug in home-built MCP servers.
- An internal crash. The server launched but threw an error on startup. Running it directly (the diagnostic from the top) surfaces the actual error message.
A diagnostic routine
Put it together into a routine you can run in under a minute:
MCP troubleshooting steps
- Run /mcp and claude mcp list to see which server failed
- Run the exact launch command yourself in the shell
- On native Windows, confirm cmd /c is wrapping npx
- Check path style matches the shell (Windows vs WSL)
- Reopen the terminal if npx/node 'isn't found'
- Confirm any token env var is set in the launching shell and not expired
- If connected but no tools, check for stdout logging in the server
Work top to bottom and you’ll find most failures within the first two or three steps. The /mcp status plus running the command yourself isolates the cause almost every time.
Wrapping up
MCP connection failures look mysterious but follow a short list: the Windows cmd /c wrapper, a wrong command or mismatched path, a stale PATH, a missing or expired credential, or a server logging to stdout. Start by checking /mcp and running the launch command directly — that one move points at the cause more often than not — then walk the rest of the list.
Set things up cleanly the first time with the MCP setup guide, and if your issue is a crowded, sluggish setup rather than a hard failure, see when too many MCP servers eat your context.