← All articles

Claude MCP Failed to Connect Logs: How to Find and Read Them

July 7, 2026·14 min read·MCPForge

Quick Answer

When Claude shows "MCP failed to connect", the fastest path to the root cause is:

  1. Claude Desktop → open ~/Library/Logs/Claude/mcp.log (macOS) or %APPDATA%\Claude\logs\mcp.log (Windows). Find the first error, exit, or ENOENT line before any reconnect loop starts.
  2. Claude Code → relaunch with claude --mcp-debug and watch stderr output, or check ~/.claude/logs/ if a log file is written.
  3. Both clients → check the per-server log (mcp-server-{name}.log for Desktop) or capture raw server stderr to find what the server process itself printed before dying.
  4. Test independently → run the server through MCP Inspector to confirm it works outside Claude entirely.

If you are using Claude Code specifically, see MCP Failed to Connect in Claude Code for a deeper dive into that client's behavior.


Claude MCP Failed to Connect Logs: 60-Second Checklist

Work through this in order. Stop at the first check that reveals something.

  • Identify which client is failing — Claude Desktop or Claude Code. They have separate log systems, separate config files, and separate diagnostics.
  • Open the main MCP log for Claude Desktop (mcp.log). For Claude Code, relaunch with --mcp-debug.
  • Find the server name in the log. Claude logs which server failed before listing the error.
  • Search for the first error before reconnect messages: grep -n 'error\|exit\|ENOENT\|fail' mcp.log | head -20
  • Check the per-server stderr log (mcp-server-{servername}.log) for what the server process itself printed.
  • Verify the command path in your config. Run which node or which python3 in a fresh terminal — does it match what Claude would see?
  • Check for stdout contamination if the server uses stdio transport. Any non-JSON on stdout breaks the stream.
  • Test with MCP Inspector to confirm the server works independently.
  • Check HTTP status codes if the server is SSE or HTTP-based (401, 403, 404, 429, 5xx).
  • Redact the log before sharing: remove API keys, tokens, file paths with usernames.

Which Claude MCP Logs Should You Check?

ProblemLog or Diagnostic SourceWhat to Look For
Server never startsmcp.log (Desktop) or --mcp-debug output (Code)spawn ENOENT, command not found, non-zero exit code immediately after launch
Server starts but disconnectsPer-server stderr log (mcp-server-{name}.log)Process crash output, uncaught exception stack traces
Tools never appear after connectmcp.log + server stderrMissing initialized handshake, tools/list error or empty array
HTTP server authentication failuremcp.logHTTP 401, 403 status codes, OAuth redirect responses
Intermittent timeoutsmcp.logRequest timeout entries, error -32001, slow response warnings
PATH or environment problemsmcp.log + your shell configENOENT, wrong Node/Python version loaded, missing env vars
stdout contamination (stdio)Per-server stderr logJSON parse errors immediately after server launch
Rate limitingmcp.log or server logsHTTP 429, Too Many Requests, exponential backoff messages

Want to analyze your API security?

Import your OpenAPI spec and generate a Security Report automatically.

Claude Desktop MCP Log Locations

Claude Desktop produces two types of MCP logs. Know both — they answer different questions.

Main connection log (mcp.log)

This is where Claude Desktop records the connection lifecycle for all configured MCP servers: startup attempts, handshake results, transport errors, and reconnect events.

# macOS
~/Library/Logs/Claude/mcp.log

# Windows
%APPDATA%\Claude\logs\mcp.log

Tail it live while Claude starts:

bash
# macOS / Linux
tail -f ~/Library/Logs/Claude/mcp.log

# Windows PowerShell
Get-Content "$env:APPDATA\Claude\logs\mcp.log" -Wait

Per-server stderr log (mcp-server-{name}.log)

Claude Desktop captures each server's stderr output into a separate file named after the server key in your claude_desktop_config.json.

# macOS — example for a server named "filesystem"
~/Library/Logs/Claude/mcp-server-filesystem.log

# Windows
%APPDATA%\Claude\logs\mcp-server-filesystem.log

This is where you find the server's own crash output, missing dependency errors, and startup failures that the server printed before dying.

Claude Desktop config location (for cross-referencing server names):

# macOS
~/Library/Application Support/Claude/claude_desktop_config.json

# Windows
%APPDATA%\Claude\claude_desktop_config.json

Tip: Open both mcp.log and the relevant mcp-server-{name}.log side by side. The main log tells you when something failed; the server log tells you why.


Claude Code MCP Diagnostics

Claude Code does not write a persistent mcp.log file in the same way Claude Desktop does. MCP diagnostic output goes to the session's stderr and is controlled by debug flags.

Enable verbose MCP output:

bash
claude --mcp-debug

This flag increases verbosity for transport events, initialization messages, and connection lifecycle. Run it in a terminal where you can see stderr directly.

Environment variable alternative:

bash
MCP_DEBUG=1 claude

Check for session log files:

bash
ls ~/.claude/logs/

If Claude Code writes session logs on your version, they appear here. The file naming varies by release.

List configured MCP servers:

bash
claude mcp list

Check a specific server's status:

bash
claude mcp get <server-name>

Remove and re-add a broken server:

bash
claude mcp remove <server-name>
claude mcp add <server-name> -- <command> [args]

Claude Code stores MCP server configuration in ~/.claude/claude.json (global) or .claude/claude.json (project-level). Cross-reference the server name in logs against the keys in that file.

For a complete Claude Code MCP configuration reference, see Claude Code MCP Server Configuration.


Reading the Log: Finding the First Useful Error

The most common mistake when debugging MCP failures is reading the wrong part of the log. After a connection fails, Claude retries — and each retry generates more log lines. The root cause is buried before the first retry.

Find it fast:

bash
# Show first 20 error/failure lines — the first one is almost always the cause
grep -n 'error\|Error\|exit\|ENOENT\|fail\|Fail\|exception\|Exception' \
  ~/Library/Logs/Claude/mcp.log | head -20

Typical log sequence for a failed stdio server:

2025-01-30T10:14:01.234Z [mcp] Starting server: filesystem
2025-01-30T10:14:01.235Z [mcp] spawn ENOENT /usr/local/bin/node         ← FIRST USEFUL ERROR
2025-01-30T10:14:01.236Z [mcp] Server filesystem exited with code 1
2025-01-30T10:14:02.000Z [mcp] Retrying connection to filesystem (1/3)
2025-01-30T10:14:02.001Z [mcp] spawn ENOENT /usr/local/bin/node
2025-01-30T10:14:03.001Z [mcp] Retrying connection to filesystem (2/3)
... (repeat)
2025-01-30T10:14:05.000Z [mcp] Failed to connect: filesystem

The line spawn ENOENT /usr/local/bin/node at 10:14:01.235 is the diagnosis. Everything after it is noise.


Log Message Decoder Table

Log Message or SymptomLikely CauseNext Check
spawn ENOENTBinary not found at the specified pathRun which node / which python3; use absolute path in config
command not foundShell wrapper can't locate the commandCheck PATH in Claude's environment vs your shell
Module not found / Cannot find moduleMissing npm package or wrong working directoryRun npm install; check cwd in config
Error: EACCESPermission denied on the binary or directorychmod +x the binary; check directory permissions
Process exited with code 1 immediatelyServer crashed on startupOpen mcp-server-{name}.log for the crash output
Process exited with code 127Command not found (shell exit code)PATH problem — use absolute binary path
JSON parse error on first messagestdout contaminationRemove all console.log from server startup path
HTTP 401Missing or expired auth tokenRe-authorize; check OAuth token validity
HTTP 403Token valid but lacks permissionsCheck scopes; verify server-side authorization
HTTP 404Wrong server URL or endpoint pathVerify the url field in your config
HTTP 429Rate limitedBack off; check server-side rate limit config
HTTP 5xxServer-side crash or misconfigurationCheck server deployment logs
Connection closed / error -32000Server process died after connectingCheck server stderr for crash; see How to Fix MCP Error -32000
Request timed out / error -32001Server too slow to respondIncrease timeout; profile slow operations; see How to Fix MCP Error -32001
Connected but no tools listedHandshake incomplete or tools/list returns emptyRun MCP Inspector; check server tools registration

The Most Common Failure Causes (and How to Confirm Each)

1. PATH and Environment Variable Problems

Claude Desktop launches as a GUI application. It inherits a restricted environment — not the same PATH your terminal has. This is the single most common cause of spawn ENOENT and command not found errors.

Evidence in logs:

spawn ENOENT node
spawn ENOENT python3

Verify:

bash
# In your terminal — find the absolute path
which node
# → /Users/you/.nvm/versions/node/v20.11.0/bin/node

which python3
# → /opt/homebrew/bin/python3

Fix: Use absolute paths in claude_desktop_config.json:

json
{
  "mcpServers": {
    "my-server": {
      "command": "/Users/you/.nvm/versions/node/v20.11.0/bin/node",
      "args": ["/Users/you/projects/my-mcp-server/index.js"]
    }
  }
}

You can also pass environment variables explicitly:

json
{
  "mcpServers": {
    "my-server": {
      "command": "/opt/homebrew/bin/python3",
      "args": ["-m", "my_mcp_server"],
      "env": {
        "API_KEY": "your-key-here",
        "PYTHONPATH": "/Users/you/projects/my-mcp-server"
      }
    }
  }
}

Confirm recovery: Restart Claude Desktop and check mcp.log — the spawn ENOENT line should be gone, replaced by a successful initialization sequence.


2. stdout Contamination (stdio Transport)

For stdio-based MCP servers, Claude reads the process's stdout as a newline-delimited JSON-RPC stream. Any non-JSON output breaks the parser immediately.

Evidence in logs:

JSON parse error: Unexpected token 'S' at position 0
Failed to parse message: "Server starting...\n"

Common culprits:

  • console.log("Server started") in Node.js startup
  • Python print() debug statements
  • Third-party libraries that print banners on import
  • npm package postinstall scripts printing to stdout

Fix: In Node.js servers:

javascript
// WRONG — this breaks stdio MCP transport
console.log("Server initialized");

// CORRECT — stderr is safe
console.error("Server initialized");
process.stderr.write("Server initialized\n");

In Python:

python
import sys

# WRONG
print("Server ready")

# CORRECT
print("Server ready", file=sys.stderr)

Confirm recovery: The JSON parse error disappears from mcp.log and the server progresses to the initialization handshake.


3. Server Process Exits Immediately

If the server exits before completing the MCP initialization handshake, Claude logs a non-zero exit code.

Evidence in logs:

[mcp] Server my-server exited with code 1
[mcp] Server my-server exited with code 127

Exit code 1 = generic error (check server stderr log for the actual exception). Exit code 127 = shell can't find the command (PATH problem).

What to do:

bash
# Read what the server printed before dying
cat ~/Library/Logs/Claude/mcp-server-my-server.log

# Common output you'll see:
# Error: Cannot find module 'some-package'
# ModuleNotFoundError: No module named 'mcp'
# SyntaxError: Unexpected token

Fix by error type:

  • Cannot find module → run npm install in the server directory, or check the cwd config field points to the right directory
  • ModuleNotFoundError → activate the correct virtualenv; use pip install in the right environment
  • SyntaxError → server code has a bug; fix the syntax error

4. MCP Initialization Handshake Failures

Even if the server process starts successfully, it must complete the MCP initialize/initialized handshake before Claude considers it connected. A server that hangs or responds incorrectly during handshake results in a timeout.

Evidence in logs:

[mcp] Initialization timeout for server: my-server
[mcp] Server my-server failed to respond to initialize request

Most common causes:

  • Server is waiting for user input on stdin instead of reading JSON-RPC
  • Server's initialize handler throws an uncaught exception
  • Server sends the initialized notification before receiving initialize (protocol order violation)

Verify with MCP Inspector:

bash
npx @modelcontextprotocol/inspector node /path/to/your/server.js

MCP Inspector opens a browser UI that shows the exact JSON-RPC messages exchanged. You'll immediately see if initialize/initialized is completing.


5. HTTP and Authentication Errors (SSE / HTTP Transport)

For servers using SSE or HTTP transport, Claude logs the HTTP status code. Each code points to a different problem.

Evidence in mcp.log:

[mcp] HTTP 401 connecting to https://api.example.com/mcp
[mcp] HTTP 403 connecting to https://api.example.com/mcp
[mcp] HTTP 404 connecting to https://api.example.com/mcp

401 — Unauthorized: The Authorization header is missing or the token is expired.

bash
# Test manually
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.example.com/mcp/health

Fix: Refresh the OAuth token; re-run the authorization flow; check the headers field in your MCP config.

403 — Forbidden: The token is valid but lacks required scopes or the server's authorization policy blocks the request. Check what scopes your OAuth application requested vs what the server requires.

404 — Not Found: The URL in your config is wrong, or the server path changed. Verify the exact endpoint URL with the server operator.

429 — Too Many Requests: You've hit the server's rate limit. This often happens during reconnect storms — each retry counts as a new request. Check your server's rate limit documentation and add delay between retries.

5xx — Server Error: The remote MCP server itself is crashing or misconfigured. Check the server's own deployment logs — this is outside Claude's control.


6. Server Connects but Tools Don't Appear

The hardest failure to diagnose: Claude reports the server as connected, but the tool list is empty.

Evidence in logs:

[mcp] Server connected: my-server
[mcp] tools/list returned 0 tools

Or no tools/list line at all — meaning Claude hasn't even requested tools yet.

Checklist:

  1. Confirm the server sends capabilities.tools in its initialize response
  2. Confirm tools/list returns a non-empty array
  3. Check that tool definitions have valid name, description, and inputSchema fields
  4. Verify the server doesn't throw during tools registration

Test with MCP Inspector:

bash
npx @modelcontextprotocol/inspector node /path/to/server.js

Navigate to the Tools tab in the Inspector UI. If tools appear there but not in Claude, the issue is in Claude's tool rendering or a capability negotiation mismatch. If tools don't appear in Inspector either, the server's tool registration code has a bug.


Correlating Timestamps Across Logs

When you have multiple log sources — Claude's mcp.log, your server's stderr, and a deployment log from a remote service — timestamps are your alignment anchor.

Practical approach:

  1. Note the timestamp of the first failure in mcp.log
  2. Search your server's log for entries within ±5 seconds of that timestamp
  3. Note the timestamp of the last successful log line before the failure
bash
# Find all log entries from both files around a specific time
grep '10:14:0[0-9]' ~/Library/Logs/Claude/mcp.log
grep '10:14:0[0-9]' ~/Library/Logs/Claude/mcp-server-my-server.log

If the server log shows a crash at 10:14:01 and Claude's log shows a disconnect at 10:14:01.300, the server crashed first — that's your root cause direction.


Testing MCP Servers Independently with MCP Inspector

Before filing a bug report or spending more time in logs, test the server directly:

bash
# Install and run inspector
npx @modelcontextprotocol/inspector <command> [args]

# Example: Node.js server
npx @modelcontextprotocol/inspector node /path/to/server/index.js

# Example: Python server
npx @modelcontextprotocol/inspector python3 -m my_mcp_server

# Example: HTTP server
npx @modelcontextprotocol/inspector --transport sse https://my-server.com/sse

The Inspector UI shows:

  • Whether initialize/initialized completes
  • What tools, resources, and prompts the server exposes
  • The raw JSON-RPC messages in both directions
  • Any errors during tool calls

If the server fails in Inspector with the same error as in Claude, the bug is in the server. If it works in Inspector but fails in Claude, the bug is in Claude's config or environment.


Minimal Reproduction Steps

If you need to report a bug, gather these before opening an issue:

  1. Exact error — the first error line from mcp.log, not the reconnect spam
  2. Server stderr — full content of mcp-server-{name}.log
  3. Config excerpt — the relevant block from claude_desktop_config.json or ~/.claude/claude.json with secrets redacted
  4. MCP Inspector result — does the server work outside Claude?
  5. Versions — Claude Desktop/Code version, Node/Python version, OS version, server package version
  6. Reproduction steps — exact sequence to trigger the failure from a fresh Claude restart

Bug Report Checklist

Before sharing logs:

  • Remove API keys, OAuth tokens, and Bearer tokens — replace with [REDACTED_API_KEY]
  • Remove full file paths that contain your username — replace /Users/yourname/ with [HOME]/
  • Remove any personal data from tool call arguments visible in logs
  • Strip database connection strings, including passwords
  • Verify no internal hostnames or IP addresses are exposed
  • Confirm you're sharing only the relevant time window, not hours of log history

MCP Inspector is safer for sharing than raw logs because you can screenshot only the specific interaction, without exposing system paths or environment.


Visual: stdio MCP Connection Lifecycle

Claude Desktop
     │
     │  1. Read claude_desktop_config.json
     │  2. Resolve command + args
     ▼
  spawn(command, args)
     │
     ├─ FAIL: spawn ENOENT → command not found → check PATH
     │
     ▼
  Child Process (MCP Server)
     │  stdout → Claude reads JSON-RPC stream
     │  stderr → captured to mcp-server-{name}.log
     │
     │  3. Server sends: initialize request
     │  4. Server responds: initialize response + capabilities
     │  5. Claude sends: initialized notification
     │
     ├─ FAIL: timeout → server hung or not reading stdin
     ├─ FAIL: parse error → stdout contaminated with non-JSON
     │
     ▼
  6. Claude requests: tools/list
     │
     ├─ FAIL: empty array → server registered no tools
     ├─ FAIL: error response → server tools handler threw
     │
     ▼
  7. Tools appear in Claude UI ✓

If this guide didn't resolve your specific failure:


Key Takeaways

  • Claude Desktop and Claude Code have separate log systems. Never apply Desktop log paths to Code or vice versa.
  • The root cause is always before the first reconnect message. Don't read the reconnect spam — grep for errors and look at the first hit.
  • Per-server stderr logs (mcp-server-{name}.log) are the most underused diagnostic. They capture what the server printed before dying.
  • PATH problems cause the majority of Desktop failures. GUI apps don't inherit your shell PATH. Use absolute paths.
  • stdout contamination silently breaks stdio servers. Any non-JSON on stdout is a protocol violation.
  • MCP Inspector is the fastest way to confirm a server works outside Claude. If it fails in Inspector too, the bug is in the server.
  • Redact logs before sharing. Tokens and API keys appear in logs more often than developers expect.

Frequently Asked Questions

Where are Claude Desktop MCP logs stored on macOS?

Claude Desktop writes MCP logs to ~/Library/Logs/Claude/. The main files are mcp.log (connection lifecycle events) and mcp-server-{name}.log (per-server stderr). Open them with Console.app or tail -f from the terminal.

Where are Claude Desktop MCP logs stored on Windows?

On Windows, Claude Desktop logs are in %APPDATA%\Claude\logs\. Look for mcp.log and individual mcp-server-{name}.log files in that directory.

How do I enable MCP debug logging in Claude Code?

Run Claude Code with the --mcp-debug flag: claude --mcp-debug. This increases verbosity for MCP transport events, initialization messages, and connection lifecycle. You can also set MCP_DEBUG=1 in your environment before launching.

My MCP server connects but no tools appear in Claude. What do I check?

First confirm the server completes the MCP initialization handshake — search the logs for 'initialized' or 'tools/list'. If the handshake succeeds but tools are missing, the server may be returning an empty tools array or a tools/list error. Run the server through MCP Inspector to see exactly what it returns.

What does 'spawn ENOENT' mean in Claude MCP logs?

ENOENT means the executable or command Claude is trying to launch does not exist at that path. Claude cannot find the binary defined in your MCP server's 'command' field. Fix by providing the absolute path to the binary or ensuring the binary is on the PATH Claude inherits at startup.

How do I find the first useful error before repeated reconnect messages?

Reconnect attempts flood the log quickly. Open the log file and search backward from the first 'reconnect' or 'retry' message — the root cause error appears just before the first reconnect attempt. In terminal: grep -n 'error\|fail\|exit\|ENOENT' mcp.log | head -20

Can stdout output from my MCP server break the connection?

Yes. For stdio transport, Claude reads the server's stdout as the JSON-RPC message stream. Any non-JSON output on stdout — console.log statements, startup banners, debug prints — corrupts the message stream and causes a parse failure. All server logging must go to stderr only.

How do I safely share MCP logs without exposing secrets?

Before sharing, search logs for API keys, tokens, passwords, and user paths. Replace them with placeholders like [REDACTED_API_KEY] and [USER_HOME]. Never share raw logs from production environments. MCP Inspector captures the same protocol data in a controlled local environment, which is safer for sharing.

What does HTTP 401 mean in Claude MCP logs for an HTTP-based server?

HTTP 401 means the server rejected the request because no valid credentials were provided. For OAuth-based servers, your token may have expired or the Authorization header is missing. Check the server's authentication configuration and refresh or re-authorize the token.

Does Claude Code use the same MCP log files as Claude Desktop?

No. Claude Desktop writes to ~/Library/Logs/Claude/ (macOS) or %APPDATA%\Claude\logs\ (Windows). Claude Code outputs MCP diagnostics to its own session output — use claude --mcp-debug or check MCP server stderr directly. The two clients have completely separate log systems.

Check your MCP security posture

Generate a Security Score, detect risky tools, and review permissions before exposing APIs to AI agents.