Debugging MCP Servers with Client Logs

Where Claude Desktop, Cursor, and Cline write MCP server logs, what to look for when a server fails to connect, and how to add stderr instrumentation to custom servers.

Operations

Detailed Explanation

Where the Logs Live

Each client writes its own MCP debug log separately from the main app log:

  • Claude Desktop (macOS): ~/Library/Logs/Claude/mcp.log plus one file per server, e.g. mcp-server-filesystem.log.
  • Claude Desktop (Windows): %APPDATA%\Claude\logs\mcp.log.
  • Cursor: View → Output panel → select MCP from the dropdown.
  • Cline: Output → Cline dropdown → search for "MCP".

What to look for

A healthy server logs an "Initialized" line shortly after the client launches. Common failure modes:

[error] Failed to spawn server "github": ENOENT

The command value couldn't be resolved. For npx/uvx this usually means PATH doesn't include the binary in the GUI app's environment — see troubleshooting common errors.

[error] Server "postgres" exited with code 1: connection refused

Postgres isn't running on the host:port in the connection string. Start the database or fix the URI.

[error] Invalid env var GITHUB_PERSONAL_ACCESS_TOKEN: 401 Bad credentials

The token is wrong or expired. Generate a new one — see github with token.

Instrumenting your own server

Custom servers (see custom stdio server) should write structured logs to stderr:

console.error(JSON.stringify({
  level: "info",
  msg: "tool called",
  tool: name,
  ts: new Date().toISOString(),
}));

stderr is captured by the client into the per-server log file, so anything you write there is visible without affecting MCP's stdio JSON-RPC frames.

Live tailing

For Claude Desktop on macOS:

tail -F ~/Library/Logs/Claude/mcp*.log

Open this in a terminal before restarting Claude — you'll see exactly when each server connects (or fails) during launch.

Making sense of warnings

A noisy "deprecated" warning from @modelcontextprotocol/server-... packages is usually safe to ignore short-term, but check the package's CHANGELOG before updating in case the env var names changed.

Use Case

Diagnosing why a config that 'worked yesterday' suddenly stopped — token expired, postgres restarted, npx cache corrupt, or PATH missing in the GUI's environment.

Try It — MCP Server Config Generator

Open full tool