MCP servers fail in a small number of predictable ways. The diagnostic workflow below is built around isolating the failure to one of three layers — registration, transport, or the server itself — and fixing it from there. Most problems are resolved in the first two layers; the inspector tool handles the rest.
The three layers
- Registration — Claude Code knows the server exists. Run
/mcp; the server is in the list. If not, the problem is in your config file - Transport — Claude Code can connect to the server. The server appears as connected in
/mcp, not error or disconnected. If it errors, the problem is in how the server is launched or in network/auth configuration - Server — the server runs and responds correctly. Tools appear in
/mcp, calls return results, no schema errors. If tools fail when called, the problem is in the server's code
Diagnose in order. Don't dig into server code if the server isn't even being registered; don't suspect a tool implementation if the transport is broken.
Layer 1 — server doesn't appear
Symptom: you registered the server, but /mcp doesn't list it.
Check the config file. User-scope servers are in ~/.claude.json under the mcpServers key. Workspace-scope servers are in ./.mcp.json at the workspace root. Open the file and verify your server is there with the expected name. Common mistakes: edited the wrong file, JSON syntax error elsewhere in the file invalidating the whole document, server registered under user scope but you're checking from a workspace where the user scope hasn't loaded.
Validate JSON. A trailing comma anywhere in ~/.claude.json or .mcp.json breaks the entire file. cat ~/.claude.json | jq . — if jq complains, fix the syntax error before doing anything else. The Claude Code CLI doesn't always report this clearly; the symptom is "no MCP servers" rather than "your config is broken".
Restart Claude Code. MCP server lists are loaded at session start. Edits to ~/.claude.json or .mcp.json while Claude Code is running don't take effect until you start a new session.
Workspace approval (project scope). Servers in .mcp.json require one-time per-workspace approval the first time you run Claude Code there. If you dismissed the approval prompt, the server stays registered but unapproved. Run /mcp, find the server, and approve it.
Layer 2 — server appears but errors
Symptom: /mcp shows the server but with a red error indicator, or it shows zero tools.
Use the debug flag. Restart Claude Code with claude --debug mcp. Stderr from your MCP server is then surfaced in the Claude Code logs. For stdio servers, this is the most useful single command — most server-side errors print to stderr on startup, but you only see them with --debug.
Check the command path. If the registered command is node dist/index.js (relative), it resolves against Claude Code's launch directory, not against the directory where you ran claude mcp add. Use absolute paths in MCP server commands; relative paths work in interactive testing and break in real use.
Check the executable exists. A Node version mismatch (server compiled against Node 20, system has Node 16) causes the server to crash on startup. Try running the exact command from your config in a plain terminal:
node /absolute/path/to/dist/index.js
It should sit silently waiting for stdin. If it crashes, the error tells you what's wrong.
Stdio-specific issues
- Server logs to stdout — any
console.login the server's code sends invalid bytes into the JSON-RPC stream and Claude Code disconnects with a parse error. Search the server source forconsole.log; replace withconsole.error(stderr is safe) - Server crashes silently on startup — usually an unhandled promise rejection in async setup. The server starts, fails, exits; Claude Code sees a closed stream and reports "disconnected". Run with
--debug mcpto see the stack trace - Environment variables not passed — env vars set via
--envat registration are written to~/.claude.json; if you registered the server without them, the server won't see them. Re-register with the correct flags
HTTP-specific issues
- Authorization header format — Bearer tokens need the literal "Bearer " prefix; some servers expect just the token, some expect the full
Authorization: Bearer xxxstring. Read the server's docs and verify the header registration matches - CORS on local development servers — if you're testing against a server running on
localhost, CORS configuration in the server can block Claude Code's requests. Server-side fix: allow the appropriate origin - Connection timeouts — slow servers or geographic distance can exceed the default connection timeout. Configure timeout in the registration if Claude Code's CLI exposes it; otherwise, host the server closer or speed up its cold-start
Layer 3 — tool calls fail
Symptom: server connects, tools appear in /mcp, but when Claude actually calls a tool, it fails.
Read the error. Tool call failures surface in Claude Code's chat — usually with a message like "Tool error: …" followed by the underlying issue. Read the literal text first; it often tells you exactly what's wrong (missing parameter, type mismatch, server-side exception).
Common error signatures and meanings:
- "Method not found" — the tool name in the call doesn't match what the server registered. Usually a typo in the server's tool name, or a stale tool definition cached client-side. Reconnect the server
- "Invalid params" — Claude passed arguments the server's input schema rejected. Either the schema is wrong (overly strict), or Claude is genuinely passing wrong types. Check the schema definition in the server source
- "Internal error" — generic server-side exception. Run
--debug mcpto see the actual stack trace from the server - JSON parse errors — the server returned invalid JSON. Almost always means stdout pollution (logging in stdio servers) or a bug in the response-shaping code
- Schema validation failures — the response shape doesn't match what MCP expects. Check that your tool handler returns
{ content: [{ type: "text", text: "..." }] }, not just a string
The MCP Inspector
For stubborn problems that don't reveal themselves through Claude Code, the MCP Inspector tool isolates the server from the client. It's a separate process you run against your server directly, with a UI that lets you list tools, call them with chosen arguments, and see the raw protocol traffic.
npx @modelcontextprotocol/inspector node /path/to/your/server.js
The Inspector connects to your server using the same protocol Claude Code uses, but with a debugger UI on top. If your tool works in the Inspector and fails in Claude Code, the bug is in how Claude is calling it (probably a schema mismatch). If it fails in both, the bug is in your server.
When you're stuck
If diagnostics aren't progressing:
- Reconnect the server from the
/mcpmenu — picks up server-side changes without restarting Claude Code - Restart Claude Code — picks up config changes
- Roll back to a known-good version of the server — bisect to find what change broke it
- Run the Inspector against the server in isolation — eliminates Claude Code as a variable
- Check the server's GitHub issues — popular community servers have many of these problems documented
The general principle: don't add complexity (more tools, more env vars, more transports) until what you have is working. MCP problems compound — a slightly-broken server with one tool is much easier to fix than a slightly-broken server with twelve.
