Claude Code MCP Server Failed to Connect: A Fix List
An MCP server that will not connect in Claude Code nearly always tells you why, if you know where to look. Read the status first, then work through scopes, .mcp.json syntax, project approval, stdio commands, HTTP sign-in, timeouts and the debug log.
8 min read
When an MCP server is not working in Claude Code, read its status before you change anything. claude mcp list prints a status next to every server, claude mcp get <name> adds the detail of the last failure, and /mcp inside a session shows the same, plus whether you have approved the server for this project. The status points at the cause: ⏸ Pending approval is a project server nobody has approved, ! Needs authentication is a sign-in, ✘ Failed to connect comes with the HTTP status or error the server returned, and a server that is missing altogether is a file, key or scope problem. Work down the list below from the status you see.
This is about getting a server connected. Once it is connected and a tool misbehaves, see how to debug MCP tools. For the Claude Desktop app rather than Claude Code, see Claude Desktop MCP not working. If Claude Code itself will not start, start with Claude Code not working.
Read the status first
claude mcp list # every server with a health status claude mcp get fenbs # one server: scope, command or URL, and an Issue: line claude --debug=mcp # start a session that logs MCP connections # inside a session /mcp # status, approval, tool count; reconnect or sign in here
✔ Connected: the connection works. If the tools still do not appear, see the zero-tools case under the debug log below.⏸ Pending approval (run claude to approve): a server from the project’s.mcp.jsonthat you have not approved yet. See “Project servers wait for approval”.! Needs authentication: the server answered 401 or 403 and wants a sign-in. See “HTTP servers”.✘ Failed to connect: Claude Code tried and failed.claude mcp get <name>shows the HTTP status or error code and any text the server sent, with credential-like text redacted.⊘ Disabled for this project: someone switched it off in/mcp. Switch it back on there.- Not in the list at all: Claude Code never read its definition. Check the scope and the file next.
Which scope won
Claude Code keeps MCP servers in three scopes. Local, the default for claude mcp add, stores the server in ~/.claude.json under the current project’s path, so it does not appear in your other projects. Project writes .mcp.json at the repository root, for everyone who clones it. User stores it in ~/.claude.json for all your projects. A server you added “yesterday” that is missing today was most likely added at local scope in a different folder.
When the same name is defined in more than one scope, the Claude Code MCP documentation (opens in a new tab) gives the order: local, then project, then user, then plugin-provided servers, then claude.ai connectors. The whole entry from the winning scope is used; fields are never merged across scopes. So a correct URL in .mcp.json loses to a stale one you added locally months ago. claude mcp list warns when one name has different endpoints in different scopes; delete the one you do not want with claude mcp remove <name> --scope local.
.mcp.json not working
Most .mcp.json failures are the file’s place or shape, not its contents. Here is a correct file with one remote and one local server:
{
"mcpServers": {
"fenbs": {
"type": "http",
"url": "https://fenbs.ai/api/mcp"
},
"docs-search": {
"command": "npx",
"args": ["-y", "@example/docs-mcp"],
"env": { "DOCS_API_KEY": "${DOCS_API_KEY}" }
}
}
}- The file goes at the repository root, not inside
.claude/, and servers sit undermcpServers, not underserversas in VS Code’smcp.json. Claude Code’s guide to debugging your configuration (opens in a new tab) lists both as common causes. settings.jsondoes not read anmcpServerskey. Servers put there never appear. Use.mcp.json, orclaude mcp add --scope user.- An entry with a
urlbut notypeis read as a stdio server and skipped with a message telling you to add"type": "http".streamable-httpis accepted as an alias forhttp. - A
${VAR}that is not set, with no${VAR:-default}, loads unexpanded andclaude mcp listnames the missing variable. In a remote server’surlandheaders, some credential names, such asANTHROPIC_API_KEY,NPM_TOKENandHTTPS_PROXY, always read as empty, so the server receivesBearerand answers 401. Copy the value into a variable with your own name. - A pasted token with a trailing newline triggers a hidden-whitespace warning in
/mcp. Claude Code does not trim it for you.
Project servers wait for approval
For safety, Claude Code asks before it uses servers from a project’s .mcp.json in an interactive session. Until you answer, the server stays at ⏸ Pending approval. Run claude in the folder, accept the workspace trust dialog, then approve the server, or approve it later from /mcp. If you dismissed the prompt, the server stays off until you do.
A cloned repository cannot approve its own servers: enableAllProjectMcpServers committed in the project’s .claude/settings.json is ignored until you trust the folder. A disabledMcpjsonServers entry in any settings file rejects the server outright. To be asked again, run claude mcp reset-project-choices. The reverse matters too: claude -p runs and Agent SDK sessions load project servers without asking, so pass --strict-mcp-config when running on code you did not write.
stdio servers: command, paths and environment
- Put the server’s own command after
--:claude mcp add docs --env DOCS_API_KEY=... -- npx -y @example/docs-mcp. Without it, Claude Code tries to read the server’s flags as its own. Keep--envaway from the name, with another option such as--transport stdiobetween them, or the name is read as another variable. - Relative paths in
commandorargsresolve against the folder you started Claude Code in, not the folder holding.mcp.json. A server that works from the repository root and fails from a subfolder has a relative path. Use absolute paths; programs on your PATH such asnpxanduvxare fine as they are. - Environment variables your terminal sets may not reach the server. Put what it needs in the entry’s own
env, which does not depend on how Claude Code was launched. - Run the command yourself in a terminal. A healthy stdio server prints nothing and waits for input. The stdio binding in the MCP specification (opens in a new tab) forbids a server from writing anything but protocol messages to standard output, so a banner or a stray log line there breaks the connection; logs belong on standard error.
- Claude Code does not reconnect a stdio server that exits mid-session. Fix the crash, then reconnect it from
/mcp.
HTTP servers: URL, headers and sign-in
Add a remote server with claude mcp add --transport http <name> <url>. Recent versions fall back to SSE on their own when a server only speaks that, and WebSocket servers go in .mcp.json with "type": "ws", since the --transport flag does not accept it. When the status is ! Needs authentication, run /mcp, choose the server and sign in in the browser, or from the shell run claude mcp login <name>. Over SSH, add --no-browser: it prints the URL for you to open locally and asks for the redirect URL back.
- If the browser signs you in but the redirect fails with a connection error, paste the full callback URL from the address bar into the prompt Claude Code shows.
- If you set an
Authorizationheader yourself, a 401 or 403 is reported as✘ Failed to connect, not as needing sign-in, because the credential to fix is the one you configured. Replace the token, or remove the header to use the OAuth flow instead. - Tokens from a sign-in are refreshed automatically. When the server rejects the refresh token, Claude Code shows a notice pointing at
/mcp; choose Re-authenticate there. - “Clear authentication” in the server’s
/mcpmenu revokes the stored sign-in, which is the clean way to start over.
Timeouts
A slow server can fail simply by taking too long. According to the environment variables reference (opens in a new tab), MCP_TIMEOUT sets how long a server gets to start, 30 seconds by default, and each request to an HTTP or SSE server times out after 60 seconds unless MCP_TOOL_TIMEOUT, or a per-server timeout field in .mcp.json, raises it. A first connection to an HTTP or SSE server that fails with a transient error, such as a 5xx or a refused connection, is retried up to three times before the server is marked failed.
MCP_TIMEOUT=60000 claude
The debug log
When the status does not explain it, start a session with claude --debug=mcp. The CLI reference (opens in a new tab) documents the category filter; the log goes to ~/.claude/debug/<session-id>.txt, or to a file you name with --debug-file, and includes each stdio server’s standard error. A server that shows as connected with zero tools has started without returning a tool list: choose Reconnect in /mcp, and if the count stays at zero, read its standard error in that log. To test one server with nothing else loaded, run claude --strict-mcp-config --mcp-config ./one-server.json.
What a board connection looks like when it fails
fenbs is a remote HTTP server that uses OAuth, so it has no command, path or environment to break. Add it with claude mcp add --transport http fenbs https://fenbs.ai/api/mcp, then /mcp and sign in. A sign-in produces an hour-long access token that is refreshed on its own; if someone revokes the connection under Settings, “Connect an AI assistant”, the refresh is refused and the server shows as needing authentication, so sign in again from /mcp. A hand-issued token passed with --header works differently: it has a name, scopes and an optional expiry, and once it expires or is revoked the server shows as failed with a 401, and the fix is a new token. Once it connects, ask Claude to run fenbs_whoami to confirm who it is acting as. Setting up the rest is in the Claude Code integration.
Related
How transports differ: MCP transports. Testing a server outside Claude Code: the MCP Inspector. Which servers a team should allow: MCP governance. The fenbs tools and scopes: MCP docs.