MCP server not connecting in Claude Code

A server that will not connect is failing for one of seven reasons, and the first is specific enough that knowing it saves an afternoon: the server printed something to stdout.

By the Continuum team. We build a workbench that runs Claude Code, Codex, and their peers, so the model rates quoted here are the ones our own cost analytics ship with.

The short version

Run claude mcp list first: it prints a health status next to every configured server, which tells you whether the problem is connection, authentication, or an approval you never gave. If a server shows as failed, run its command by hand, because it usually fails visibly. The most common cause for a custom stdio server is writing to stdout, which the transport uses as the protocol channel. After that come pending project approval, relative paths in the command, missing environment variables, and configuration written into a file Claude Code does not read.

What you need to know
  • Anything on stdout corrupts the protocol. Log to stderr, always.
  • claude mcp list prints a health status per server. Read it before anything else.
  • Project servers need a one-time approval. Dismissed prompt means never connected.
  • Relative paths in command resolve against your launch directory, not .mcp.json.
  • Environment variables belong in the server env block, not your shell.
  • claude --debug=mcp writes the server stderr to ~/.claude/debug/<session-id>.txt.

Diagnose in order

Four commands, in this order. Most cases end at step two or three.
# 1. what is configured, and what does each one report?
claude mcp list
claude mcp get postgres

# 2. what actually connected, and is anything awaiting approval?
#    (inside a session)
/mcp

# 3. run the server command by hand - this finds most problems
npx -y @modelcontextprotocol/server-postgres "$DATABASE_URL"

# 4. read the server stderr from the client side
claude --debug=mcp
# then: ~/.claude/debug/<session-id>.txt

What claude mcp list tells you, and what to do about it.

StatusMeansDo
ConnectedWorkingNothing
Needs authenticationOAuth not completedRun /mcp and authenticate
Failed to connectThe server did not start or was unreachableStep 3: run it by hand
Pending approvalA project server you never approvedRun claude in the repo and approve from /mcp
RejectedYou declined it onceCheck disabledMcpjsonServers in settings
Not listed at allWrong scope, or the wrong config fileSee the configuration section below

The stdout trap

Wrong, and it will look completely fine when you run it by hand.
console.log("server starting...");     // corrupts the stream
console.log(`connected to ${dbUrl}`);   // same
process.stdout.write("ready\n");        // same
Right. stderr is free for logging and Claude Code will show it to you.
console.error("server starting...");
process.stderr.write("connected\n");
Check whether a server you did not write is clean.
# anything on stdout that is not JSON-RPC is a problem
npx -y some-mcp-server 2>/dev/null | head -5

# a well-behaved stdio server prints NOTHING and blocks, waiting for a client.
# a silent hang here is success, not a failure.

Configuration in a file Claude Code does not read

A whole class of "my server never appears" is a correct configuration in the wrong place. There is no error, because nothing read it.

You didWhat happened
Put .mcp.json inside .claude/Project MCP config lives at the repository root
Added mcpServers to settings.jsonsettings.json does not read that key. Use .mcp.json or --scope user.
Used the Claude Desktop config formatDifferent file, different shape. Use claude mcp add and let it write the file.
Added it in one project and expected it everywhereLocal scope is the default. Re-add with --scope user.
Committed enableAllProjectMcpServers and cloned the repoA cloned repository cannot approve its own servers until you trust the workspace
The three scopes, and where each one is stored.
# local (default): this project only, private to you, in ~/.claude.json
claude mcp add --transport http stripe https://mcp.stripe.com

# project: shared with the team via .mcp.json at the repository root
claude mcp add --transport http shared-server --scope project https://example.com/mcp

# user: all your projects, private to you, in ~/.claude.json
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic

# and if you dismissed the approval prompt once:
claude mcp reset-project-choices

Environment variables and relative paths

Two failures that both look like "it works in my shell but not in Claude Code", for two different reasons.

Environment variables belong in the config, not your shell.
# the server is a child process. It gets Claude Code's environment minus the
# variables Claude Code strips from subprocesses, and nothing you exported after launch.
claude mcp add postgres \
  --env DATABASE_URL="postgres://localhost/dev" \
  -- npx -y @modelcontextprotocol/server-postgres
And absolute paths for anything local.
{
  "mcpServers": {
    "internal": {
      "type": "stdio",
      "command": "/Users/you/tools/mcp-internal/bin/server",
      "args": ["--config", "/Users/you/tools/mcp-internal/config.json"],
      "env": { "API_TOKEN": "..." }
    }
  }
}

Timeouts, reconnection, and the servers that drop later

A server that connects and then stops working is a different problem from one that never connects, and the controls are different too.

The timers, as of August 2026.

TimerDefaultControl
Server startupSet per launchMCP_TIMEOUT, in milliseconds
Tool call wall clockAbout 28 hoursPer-server timeout in ms, or MCP_TOOL_TIMEOUT
Tool call idle5 minutes remote, 30 minutes stdioCLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT, or 0 to disable
First response byte, remote only60 secondsRaised by setting timeout or MCP_TOOL_TIMEOUT to 60s or more
Backgrounding a long call2 minutesCLAUDE_CODE_MCP_AUTO_BACKGROUND_MS
# a server that is slow to boot
MCP_TIMEOUT=10000 claude

# a specific server whose tools take minutes
#   in its .mcp.json entry: "timeout": 600000

Questions people ask

Run claude mcp list first, since it prints a health status next to each server and distinguishes a failed connection from a missing OAuth login or an approval you never gave. If it shows as failed, run the server command by hand: it usually fails visibly. For custom stdio servers the most common cause is writing to stdout.

Almost certainly a stray print to stdout. The stdio transport uses stdout as the JSON-RPC channel, so a startup banner or a console.log corrupts the stream. Log to stderr instead, and check with npx -y your-server 2>/dev/null | head -5, which should print nothing.

claude mcp list shows what is configured plus a health status for each; /mcp inside a session shows what actually connected and which project servers are awaiting approval. The difference between the two tells you where the problem is.

It started but is not returning a tool list. Select Reconnect from /mcp. If the count stays at zero, run claude --debug=mcp and read the server stderr in the debug log at ~/.claude/debug/<session-id>.txt.

It runs as a child process and receives Claude Code environment minus the variables Claude Code strips from subprocesses, not whatever you exported in your shell afterwards. Pass them in the per-server env block, which does not depend on the launch environment at all.

It was added at local scope, which stores it in ~/.claude.json under your path. Re-add it with --scope project, which writes .mcp.json at the repository root for everyone. Each teammate then approves it once, since project servers require a one-time approval.

A relative path in command or args resolves against the directory you launched Claude Code from, not against the location of .mcp.json. Use an absolute path for local scripts; executables on PATH such as npx work as they are.

Less than they used to. Tool definitions are deferred by default, so only names enter context until a schema is needed. The live cost is tool output: Claude Code warns above 10,000 tokens for a single result and caps results at 25,000 tokens by default. Prune servers you no longer use.

Sources

Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.

  1. Claude Code: connect to tools via MCP
  2. Claude Code: debug your configuration
  3. Model Context Protocol specification
Try it

Overhead,
visible.

Continuum shows the token split per session, so what your servers actually cost stops being invisible.

free app · your subscriptions · local-first