MCP Troubleshooting: Not Connecting, Zero Tools, Timeouts

A practical fix guide for Model Context Protocol failures in Claude Desktop, Cursor, Claude Code, Windsurf, Cline, and other MCP hosts. Prefer a clean install first? See the setup guide or client pages for Cursor and Claude Desktop.

TL;DR:Do not guess from the status dot. Open the client’s MCP log, map the error to config / PATH / crash / stdout / env, run the same command in a terminal, fix, then fully restart the host. Use the config validator before hand-editing JSON.

Symptom → likely cause

Most “MCP is broken” reports collapse into a short list of root causes. Match your symptom first:

  • Server never appears / config rejected — invalid JSON, wrong config file path, or client not reloaded.
  • Server shows error / disconnected within seconds — command not found, crash on startup, missing env, or stdout corruption.
  • Connected but zero tools — failed tools/list, exception during initialize, or incomplete server implementation.
  • Tool call hangs or times out — slow external API, blocked network, deadlock, or waiting on interactive input.
  • Remote URL never connects — wrong endpoint, TLS/CORS, missing auth header, or server only speaking stdio.

Find the real error (logs by client)

The UI almost always under-reports. The MCP log (or the server process stderr) contains the fix. Common places to look:

  • Claude Desktop (macOS): ~/Library/Logs/Claude/
  • Claude Desktop (Windows): %APPDATA%\Claude\logs\
  • Claude Code: run with claude --debug, or check ~/.claude/logs/
  • Cursor: Output / MCP panels in the IDE, plus any MCP log channel in developer tools
  • Windsurf / Cline / VS Code forks: extension or agent output panels labeled MCP

Copy the first stack trace or ENOENT / parse error for the specific server id, then jump to the matching section below. A longer walkthrough of failure modes lives in MCP server not connecting.

Config JSON mistakes

Client configs are strict JSON. Trailing commas, single quotes, comments, or a mistyped mcpServers key will fail silently or disable every server in the file.

A minimal local stdio entry looks like:

config.json
{
  "mcpServers": {
    "example": {
      "command": "npx",
      "args": ["-y", "some-mcp-package"],
      "env": {
        "API_KEY": "your-key"
      }
    }
  }
}

Validate with the free MCP config validator, or generate a clean snippet with the config generator. After saving, fully quit and reopen the host app — many clients do not hot-reload MCP process trees.

PATH and “command not found”

Desktop hosts launched from a dock or Start menu often inherit a minimal PATH. Your terminal has npx via nvm/fnm/Homebrew; the GUI app does not. Symptoms include ENOENT, spawn npx ENOENT, or “command not found.”

  • Prefer an absolute path to node / npx / uvx in the command field.
  • On macOS, which npx in the same shell you use daily shows the path to paste.
  • Alternatively launch the client from a terminal so it inherits your shell environment.

Zero tools / silent crash

If the server appears then shows 0 tools, the process usually started and then died before answering tools/list. Check for:

  • Missing required environment variables (API keys, database URLs).
  • Unhandled exceptions in the server’s startup or tool registration path.
  • Wrong package name or version so the process exits immediately.
  • Working-directory issues when the server expects files relative to cwd.

Reproduce outside the client: run the exact command + args in a terminal with the same env. If it crashes there, the client will never stay healthy. For author-side debugging (Inspector, unit tests, CI), read Testing and debugging MCP servers.

Stdout corruption on stdio transport

On stdio MCP servers, stdout is the protocol wire. Anything else on that stream — console.log, print(), a noisy dependency — breaks framing. Clients then hang, report parse errors, or flip to disconnected with a cryptic message.

  • Log only to stderr (console.error, or a logger bound to stderr).
  • Never print banners or progress bars to stdout in production MCP servers.
  • If you maintain the server, add a CI check that fails if tests capture unexpected stdout.

Missing env vars & secrets

Many directory listings require API keys or connection strings. If the README lists required env vars, put them under the server’s envobject (or the host’s secret store) — do not assume the GUI inherits your shell exports.

  • Use least-privilege keys; prefer read-only tokens when the task allows.
  • Avoid committing secrets into shared config files — see MCP security best practices.
  • After changing env, restart the host so child processes pick up the new values.

Timeouts & hanging tools

A connected server with tools that hang usually means the tool handler is waiting on the network, a lock, or user input. Check:

  • External API latency, rate limits, or blocked egress.
  • Tools that prompt interactively (MCP tools should not block on stdin prompts).
  • Deadlocks when multiple tools share a single connection pool.
  • Client-side timeouts that are shorter than a legitimate long-running job — split work or stream progress via logging on stderr.

Remote HTTP / SSE failures

Remote servers use a URL instead of a local command. Failures usually come from endpoint shape, TLS, authentication, or mixing transports:

  • Confirm the host documents the correct path (often an SSE or streamable HTTP endpoint, not the marketing homepage).
  • Require HTTPS in production; mixed content and expired certs fail closed.
  • Send the auth scheme the server expects (Bearer token, OAuth) — see the auth guide on the blog.
  • A package built only for stdio will not magically work as a remote URL — deploy it first (deploy guide).

Fix checklist

  1. Open the MCP log and copy the exact error for this server.
  2. Validate config JSON (validator).
  3. Run the same command + args in a terminal with the same env.
  4. Switch to absolute paths if you see PATH / ENOENT errors.
  5. Remove stdout logging on stdio servers; keep logs on stderr.
  6. Fill required env vars; restart the host completely.
  7. Still stuck? Compare a known-good listing from the directory or re-test with the MCP playground / protocol inspector.

Deeper guides & tools

Frequently asked questions

Why is my MCP server not connecting?

Almost always one of: invalid JSON in the client config, the launch command not found on the client PATH, a server that crashes before answering initialize/tools/list, non-JSON text written to stdout on stdio transport, or the client never restarted after the config change. Find the MCP log first — the UI status alone is rarely enough.

Why does my MCP server show zero tools?

The process started but failed before (or during) tools/list. Common causes are missing environment variables, an exception in server startup, wrong working directory, or stdout pollution corrupting the JSON-RPC stream. Check the client’s MCP log for that server’s stderr output.

Where are Claude Desktop MCP logs?

On macOS, logs are typically under ~/Library/Logs/Claude/. On Windows, check %APPDATA%\Claude\logs\. Look for MCP-related files and the stderr of the specific server process, not only the main app log.

Why does Cursor or Claude Desktop say command not found for npx?

GUI apps often launch with a minimal PATH that does not include nvm, fnm, Homebrew, or your shell profile. Use absolute paths to node/npx in the config command field, or start the client from a terminal so it inherits your shell environment.

Can console.log break an MCP server?

Yes on stdio transport. stdout is reserved for JSON-RPC frames. Any console.log, print(), or library that writes to stdout can corrupt the stream so the client hangs or reports a parse error. Log only to stderr (console.error / logging to stderr).

How do I validate my MCP client config?

Paste the JSON into the free AllMCPs config validator, or lint it as strict JSON (no trailing commas, no comments). Then confirm each server entry has a command (or url for remote servers) and that args is an array of strings.