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

Terminal
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.json that 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:

.mcp.json (repository root)
{
  "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 under mcpServers, not under servers as in VS Code’s mcp.json. Claude Code’s guide to debugging your configuration (opens in a new tab) lists both as common causes.
  • settings.json does not read an mcpServers key. Servers put there never appear. Use .mcp.json, or claude mcp add --scope user.
  • An entry with a url but no type is read as a stdio server and skipped with a message telling you to add "type": "http". streamable-http is accepted as an alias for http.
  • A ${VAR} that is not set, with no ${VAR:-default}, loads unexpanded and claude mcp list names the missing variable. In a remote server’s url and headers, some credential names, such as ANTHROPIC_API_KEY, NPM_TOKEN and HTTPS_PROXY, always read as empty, so the server receives Bearer and 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 --env away from the name, with another option such as --transport stdio between them, or the name is read as another variable.
  • Relative paths in command or args resolve 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 as npx and uvx are 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 Authorization header 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 /mcp menu 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.

Give a slow server longer to start
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.

Questions people ask.

Why does my MCP server say failed to connect in Claude Code?

Claude Code started the server or called its URL and got an error back. Run claude mcp get with the server name to see the HTTP status or error code. For a local server, run its command yourself and check for relative paths and missing environment variables; for a remote one, check the URL and any Authorization header.

Why is my .mcp.json server not showing up?

Check that .mcp.json is at the repository root, not inside .claude, and that servers are under the mcpServers key. Then run /mcp: project servers stay pending until you approve them, and the approval prompt only appears in an interactive session after you trust the folder.

How do I sign in to an MCP server from Claude Code?

Run /mcp in a session, choose the server and complete the sign-in in your browser. From the shell, claude mcp login with the server name does the same, and --no-browser prints the URL for you to open on another machine, which suits SSH sessions.

How do I increase the MCP timeout in Claude Code?

Set MCP_TIMEOUT in milliseconds for server start-up, for example MCP_TIMEOUT=60000 claude. For slow tool calls on HTTP servers, raise MCP_TOOL_TIMEOUT or add a timeout field in milliseconds to that server’s entry in .mcp.json.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.