An MCP server fails to connect with CONNECTION_CLOSED
MCPFailed to connect — CONNECTION_CLOSED: Connection closed
What is actually going on
- This almost always means the server process started and then exited before completing the MCP handshake. It is rarely a network problem, even though the message sounds like one.
- Run the server command yourself in a terminal. If it prints a usage or help message, the command in your config is missing a required subcommand.
- If it starts but does slow work before serving — building an index, syncing a database — it may be exceeding the startup timeout.
The fix
Run the exact command from your config by hand and watch what it does. Pipe an initialize request into it to confirm it answers.
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' | your-mcp-command
If the server answers here but not in Claude Code, the difference is usually environment variables or a slow startup task rather than the command itself.
A configured MCP server never appears, with no error at all
MCPWhat is actually going on
- Silence, rather than a failure, usually means the config file you edited is not one Claude Code reads.
- Claude Code reads MCP servers from ~/.claude.json (user scope) and .mcp.json (project scope).
- An mcpServers block placed in ~/.claude/settings.json is ignored — settings.json has no such key, so it fails silently rather than erroring.
The fix
List what is actually registered, then add the server through the CLI so it lands in the right file.
claude mcp list
claude mcp add --scope user <name> <command>
claude mcp add-json --scope user <name> '{"type":"stdio","command":"...","args":[]}'
This one is worth checking first whenever a server "should" be configured but no tools appear. A file that is never read produces no diagnostics.
More MCP workflows and fixes →A remote MCP server reports "Needs authentication"
MCPNeeds authentication
What is actually going on
- HTTP-based MCP servers use OAuth, and the sign-in happens inside an interactive session rather than at config time.
- Adding the server to your config is only half the setup.
The fix
Start Claude Code and run /mcp, then complete the sign-in for the server listed as needing authentication.
/mcp
Pressing Enter for a new line submits a half-written prompt
TerminalWhat is actually going on
- By default your terminal sends Enter straight through, so there is no way to type a second line.
- This is the single most common reason a first session feels broken.
The fix
Run /terminal-setup once. It rebinds Shift+Enter to insert a newline.
/terminal-setup
Full setup walkthrough →claude: command not found, right after a successful install
Installzsh: command not found: claude
What is actually going on
- The install succeeded but the directory it installed into is not on your PATH.
- A shell that was already open will not pick up a PATH change made during install.
The fix
Open a new terminal window first. If it still fails, find the binary and add its directory to your PATH.
# find it
ls ~/.local/bin/claude /usr/local/bin/claude 2>/dev/null
# add to PATH (zsh)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
Answers get vague, or the session warns that context is nearly full
ContextWhat is actually going on
- Every file read and command output stays in the conversation, so long sessions accumulate material that is no longer relevant.
- A session that has drifted across several unrelated tasks is usually carrying all of them at once.
The fix
Check utilisation with /context, and reset between unrelated tasks with /clear. Keep CLAUDE.md thin, since it is re-read on every task.
/context
/clear
Keeping CLAUDE.md thin with playbooks →The same safe command asks for approval over and over
PermissionsWhat is actually going on
- Approvals are per-action, so a command you run constantly will keep prompting unless it is allowlisted.
- Permission behaviour also depends on your account type — some accounts decide this server-side, so a local workaround may no longer apply.
The fix
Add the commands you trust to the permissions allowlist in your project settings, rather than disabling permission checks globally.
Prefer narrowing the rule to the specific command over turning the check off. A blanket bypass removes the confirmation on genuinely destructive actions too.
Configuring permissions →Browser automation cannot attach to your already-running Chrome
InstallWhat is actually going on
- Chrome only accepts the remote debugging port as a launch flag. There is no way to attach to a browser that is already open.
- Chrome also refuses the debugging port when pointed at the default profile directory.
The fix
Launch a second Chrome instance with a debugging port and a separate profile directory. Your normal windows stay untouched.
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir="$HOME/.chrome-debug-profile"
# verify
curl -s http://127.0.0.1:9222/json/version
Because the profile is separate, any site you need to be logged into must be signed in again inside that window.