# MCP Server Not Showing Up or 'Failed to Connect' in Claude Code? Read the Status First

> Your MCP server is configured but Claude can't see it. `claude mcp list` tells you which of five different problems you actually have — pending approval, a failed spawn, a Windows .cmd shim, zero advertised tools, or a server that was never in the list to begin with.

By Tahir Nazir · Published 2026-08-11 · Updated 2026-10-12
Canonical: https://www.its-tahir.com/blog/mcp-server-not-showing-up-in-claude-code

**If an MCP server is missing from Claude Code or shows `✘ Failed to connect`, run `claude mcp list` before you touch any config. `Failed to connect` means Claude Code couldn't start or reach the server, so run the server's command yourself to see its real error. `⏸ Pending approval`, zero tools and a server missing from the list each have a different fix.**

When an MCP server doesn't show up in Claude Code, run `claude mcp list` before changing any config. The status next to each server tells you which of five distinct problems you have, and they need completely different fixes. Editing `.mcp.json` at random is how people lose an afternoon.

```bash
claude mcp list
```

You are looking for one of these, and each points somewhere specific:

| What you see | What it actually means |
| --- | --- |
| `✔ Connected` | Transport is fine. If tools are missing, jump to [zero tools](#connected-but-zero-tools). |
| `⏸ Pending approval` | The server is configured but you never approved it. |
| `✘ Failed to connect` | Claude Code tried to start or reach it and could not. |
| `not configured` | A remote server entry with an empty `url`. |
| *absent entirely* | Wrong scope, or a WebSocket server — which never appears here. |

A failure status means Claude Code couldn't connect to that server, not that the list command failed. That distinction matters more than it sounds: people see a red mark next to `claude mcp list` and start debugging the CLI.

![claude mcp list status mapped to cause and fix: ✔ Connected but zero tools, ⏸ Pending approval, ✘ Failed to connect, not configured (empty url), and a server not listed at all (wrong scope or WebSocket)](https://www.its-tahir.com/blog/mcp-server-not-showing-up-in-claude-code/mcp-list-status-to-fix.svg)

*Each claude mcp list status points to a different fix. Read the status before you edit .mcp.json.*

## `⏸ Pending approval` — and why approving it can still fail

Project-scoped servers defined in a repo's `.mcp.json` need a one-time approval before they load. Until you give it, they sit at `⏸ Pending approval (run \`claude\` to approve)`. Run `claude` interactively in the project and accept.

The part that catches teams out is what happens in a freshly cloned repo. As of v2.1.196, approvals are read only from settings files that aren't checked into the repository — **until you trust the workspace**. So a clone cannot approve its own servers: `enableAllProjectMcpServers` or `enabledMcpjsonServers` committed to the project's `.claude/settings.json` is ignored in an untrusted folder, and the server stays pending instead of connecting.

This is the failure mode where everything looks correct. The config is right there in version control, it works on the machine that wrote it, and it silently does nothing for everyone who clones. The fix is to run `claude` in the folder and accept the trust dialog.

An untracked `.claude/settings.local.json` behaves the same way — its approvals apply only after you've trusted that folder or a parent, because Claude Code runs git to check whether the file is tracked and only does that in a trusted folder.

## `✘ Failed to connect` — run the command yourself

Take the exact command that follows `--` in your `claude mcp add` line and run it directly in your shell.

```bash
# what you configured
claude mcp add my-server -- npx -y @acme/mcp-server

# what to run to isolate the problem
npx -y @acme/mcp-server
```

If it errors in your own shell, the problem isn't Claude Code — it's the command, the package, or the environment. That one step separates "Claude Code is broken" from "this server has never worked," and they are very different afternoons.

Two configuration details cause most genuine spawn failures:

**Relative paths.** Paths in `command` and `args` resolve against the directory Claude Code was launched from, not against `.mcp.json`. Use absolute paths for local scripts. If your server genuinely needs the project root, Claude Code sets `CLAUDE_PROJECT_DIR` in the spawned server's environment — read it from inside the server process (`process.env.CLAUDE_PROJECT_DIR`) rather than assuming a working directory. Note that referencing `${CLAUDE_PROJECT_DIR}` in the `command` or `args` of a `.mcp.json` entry needs a default, like `${CLAUDE_PROJECT_DIR:-.}`, because the variable is set in the server's environment rather than Claude Code's own.

**A misplaced `--`.** For stdio servers, `--` separates Claude's own flags from the command that runs the server. Everything after it is passed through untouched. Put `--transport` or `--scope` on the wrong side and you'll configure something you didn't intend.

Since v2.1.219, `claude mcp list` appends the failure detail to the status line, and `claude mcp get <name>` shows it on an `Issue:` line — the HTTP status or error code plus whatever error text the server returned. If you're on an older build you'll see the bare status with no explanation, which is worth knowing before you conclude there's nothing to go on.

## Windows: Node refuses to spawn `npx`

If the server works on a colleague's Mac and fails on your Windows machine with `spawn npx ENOENT` or `EINVAL`, the cause usually isn't MCP at all.

On Windows, `npx` is `npx.cmd` — a shell script, not a native executable. Since **CVE-2024-27980**, Node errors with `EINVAL` when a `.bat` or `.cmd` file is passed to `child_process.spawn` or `spawnSync` without the shell option set. Node's own documentation is explicit that on Windows, `.bat` and `.cmd` files can be invoked by spawning `cmd.exe` and passing the file as an argument.

So point the command at `cmd` and pass `npx` through as an argument:

```json
{
  "mcpServers": {
    "my-server": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@acme/mcp-server"]
    }
  }
}
```

I develop on Windows, and this is the single most common reason an MCP config that works everywhere else does nothing on my machine. It is not documented in the MCP guides because it isn't an MCP problem — it's a Node security change that MCP configs happen to trip over constantly, since so many servers are distributed as npm packages. If it's `claude` itself that won't start on Windows, rather than one of its servers, match the error in [Claude Code "Raw mode is not supported" and the other Windows startup failures](/blog/claude-code-raw-mode-is-not-supported-windows).

## Connected but zero tools

The `/mcp` panel shows a tool count next to each connected server, and it specifically flags servers that advertise the tools capability but expose none. If you see that, the transport is fine and the handshake completed — the server simply returned an empty tool list.

In practice this is nearly always the server's own fault, and nearly always visible on stderr. Run the server's command directly and read what it prints while starting up. If registration throws and the process stays alive, MCP has no way to tell Claude Code that anything went wrong; from the outside it looks like a healthy server with nothing to offer.

If the server is one you wrote, check that tool registration completes *before* you connect the transport. And if you're writing to stdout anywhere in a stdio server, fix that first — it corrupts the JSON-RPC stream, which I covered in [building an MCP server](/blog/how-to-build-an-mcp-server).

If tools appeared once and then vanished mid-session, that's different: Claude Code supports `list_changed` notifications and refreshes capabilities when a server sends one, so a server that dynamically drops tools will be reflected immediately.

## The server isn't in the list at all

Three reasons a configured server never appears:

**It's a WebSocket server.** WebSocket servers don't appear in `claude mcp list` output. Use `claude mcp get <name>` or the `/mcp` panel. Worth knowing before you re-add it three times.

**You added it at the wrong scope.** Scope decides which projects a server loads in:

| Scope | Loads in | Stored in |
| --- | --- | --- |
| Local (default) | Current project only | `~/.claude.json` |
| Project | Current project only, shared via version control | `.mcp.json` in project root |
| User | All your projects | `~/.claude.json` |

Local scope is the default, and it's stored under *that project's path* in `~/.claude.json` — so a server you added while working in one repo genuinely will not exist in another. If you wanted it everywhere, you wanted `--scope user`. If you'd rather not hand-write the entry, [this MCP config generator](https://tools.its-tahir.com/mcp-config-generator) produces ready-to-paste JSON for Claude Code, and the [reviewed MCP servers list](https://tools.its-tahir.com/mcp-servers) gives each server's install snippet.

Note that MCP "local scope" and general local settings are different things stored in different places: local-scoped servers live in `~/.claude.json`, while `.claude/settings.local.json` sits in the project directory. If you're weighing how per-project and global configuration differ between tools, I compared that directly in [Claude Code vs Cursor context management](/blog/claude-code-vs-cursor-context-management).

**The `url` is empty.** A remote server with an empty `url` shows as `not configured`, and Claude Code doesn't attempt to connect at all. Plugins sometimes ship placeholder entries like this on purpose, for a connector you configure later.

## Whitespace you cannot see

Claude Code warns when an MCP config value carries hidden leading or trailing whitespace — it checks `command`, `url`, each `args` entry, and the values and key names under `env` and `headers`. The warning names the affected field without echoing its value, for example `Leading or trailing whitespace in: headers.Authorization`.

This overwhelmingly comes from pasting a token that brought a trailing newline with it. **Claude Code does not trim the whitespace** — it uses the value exactly as written, so you have to fix the config yourself. An auth header with an invisible `\n` produces a 401 that looks nothing like a formatting problem.

## When it's the output limit, not the connection

A server that connects, exposes tools, and then seems to half-work may be hitting output limits rather than a transport fault. Claude Code warns when MCP tool output exceeds 10,000 tokens and limits output to 25,000 tokens by default. Raise it with `MAX_MCP_OUTPUT_TOKENS`:

```bash
export MAX_MCP_OUTPUT_TOKENS=50000
```

The warning threshold itself is fixed. If a specific server floods you regularly, the better fix is on the server side — paginate, or declare `anthropic/maxResultSizeChars` on the tool.

Separately, if a server is slow to start rather than broken, `MCP_TIMEOUT` controls startup timeout:

```bash
MCP_TIMEOUT=10000 claude
```

**Key takeaways**

- Read `claude mcp list` before editing any config — the status names the problem, and the five statuses need five different fixes.
- A cloned repo cannot approve its own MCP servers. Committed approval settings are ignored until you trust the workspace.
- On Windows, point `command` at `cmd` with `/c` and pass `npx` as an argument — Node refuses to spawn `.cmd` files directly since CVE-2024-27980.
- Connected with zero tools means the handshake worked and the server returned nothing. Run its command directly and read stderr.
- WebSocket servers never appear in `claude mcp list`. Use `claude mcp get` or `/mcp` instead of re-adding them.

Most of these are configuration problems wearing a connectivity costume. The status line tells you which one you have — the trick is reading it before you start editing.

If the problem turns out not to be MCP at all, [every Claude Code error and its fix](/blog/claude-code-troubleshooting) covers the rest, grouped by cause.

If you're building the server rather than consuming someone else's, the setup steps and the stdio pitfalls are in [how to build an MCP server](/blog/how-to-build-an-mcp-server). Managing what these tools know about a codebase is a related problem I've spent a lot of time on — [ContextZero](/work/contextzero) came out of it.

## FAQ

### Why does my MCP server show as connected but expose no tools?

The connection succeeded and the handshake completed, but the server advertised the tools capability and then returned an empty tool list. The /mcp panel flags exactly this case. It usually means tool registration runs after the server signals readiness, or it threw during registration and the process stayed alive. Run the server's command directly in your shell and watch stderr — the registration error is almost always printed there.

### Why does my server work on macOS but not on Windows?

If the command is npx or npm, this is almost certainly Node refusing to spawn a .cmd file. Since CVE-2024-27980, Node errors with EINVAL when a .bat or .cmd is passed to child_process.spawn without a shell, and on Windows npx is npx.cmd. Point the command at cmd with /c and pass npx as an argument instead.

### My .mcp.json is committed to the repo but teammates' servers stay pending. Why?

Approvals for project-scoped servers are only read from settings files once you trust the workspace. A cloned repository cannot approve its own servers: enableAllProjectMcpServers committed to .claude/settings.json is ignored in an untrusted folder, and the server stays at Pending approval. Run claude in the folder and accept the trust dialog first.

### Is claude mcp list enough to see every server?

No. WebSocket servers don't appear in claude mcp list output at all. Use claude mcp get <name> or the /mcp panel to check those. If a server you configured is simply absent from the list, that is a real clue rather than a display bug.

## Sources

- [Connect Claude Code to tools via MCP](https://code.claude.com/docs/en/mcp)
- [Node.js child_process documentation](https://nodejs.org/api/child_process.html)
- [Node.js April 2024 Security Releases (CVE-2024-27980)](https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2)
