MCP Forge

How to debug an MCP server: common errors and fixes

A practical guide. Updated 2026.

When an MCP server breaks, the client usually tells you almost nothing. Claude Desktop shows a red dot, Cursor says the server "failed to start," and you are left guessing. The good news is that nearly every failure falls into one of four buckets: the handshake never completes, a tool is registered but not found, the client and server disagree on transport, or an environment variable never reached the process. Here is how to diagnose each one with the MCP Inspector and your logs.

Start with the Inspector, not the client

Before you touch your client config, run the server in isolation with the official MCP Inspector. It launches your server, drives the protocol by hand, and prints every JSON-RPC message, which removes the client from the equation entirely.

npx @modelcontextprotocol/inspector node build/index.js

Open the printed URL, click Connect, then List Tools. If the Inspector connects and lists your tools, the server is fine and your bug is in the client config. If it fails here, you have isolated the problem to the server itself. Always confirm which side is broken before changing anything.

Handshake fails: the server never initializes

The MCP handshake is an initialize request followed by an initialized notification over JSON-RPC. If the client hangs on "connecting" or drops immediately, the handshake never completed. The most common cause on stdio servers is that something other than protocol traffic landed on stdout.

In the Inspector you will see the initialize request go out with no valid response coming back. That confirms a handshake fault rather than a tool bug.

Tool not found: registered but invisible

Here the server connects but a tool the model tries to call returns "method not found" or simply never appears in the list. Check these in order:

Transport mismatch: stdio vs HTTP

A server speaks one transport and the client expects another. If your config points at a command, the client launches it and talks stdio. If it points at a URL, the client expects streamable HTTP (or the older SSE transport). Mixing them produces immediate connection failures.

// stdio: client spawns the process
{ "command": "node", "args": ["build/index.js"] }

// HTTP: client connects to a running endpoint
{ "url": "http://localhost:3000/mcp" }

If you wrote an HTTP server but configured a command, the client spawns a process that exits because nothing is listening on stdin. If you wrote a stdio server but gave a url, there is no endpoint to reach. Match the transport in your server code to the shape of the client config, and confirm an HTTP server is actually running and reachable before pointing a client at it.

Env vars not passed: works in your shell, fails in the client

This is the classic "it runs when I run it" bug. The client does not inherit your shell environment. Your API_KEY exported in .zshrc is invisible to a server spawned by Claude Desktop or Cursor, so the process starts and then fails the moment it reads a missing variable.

Pass variables explicitly in the client config:

{
  "mcpServers": {
    "myserver": {
      "command": "node",
      "args": ["build/index.js"],
      "env": { "API_KEY": "sk-...", "LOG_LEVEL": "debug" }
    }
  }
}

You can reproduce the same empty-environment condition in the Inspector by passing the variables there, which proves whether the missing value is the cause. Also use an absolute path for command and args: the client may launch with a different working directory and a minimal PATH, so a bare node or a relative script path can fail to resolve.

Where the logs actually live

When the Inspector is not enough, read the client logs. Claude Desktop writes per-server logs you can tail:

tail -f ~/Library/Logs/Claude/mcp-server-myserver.log   # macOS

On Windows look under %APPDATA%\Claude\logs. Cursor exposes MCP output in its Output panel. Because stdout is reserved for the protocol, send your own diagnostics to stderr and the client will capture them here. A handshake failure, a missing module, or an unset key almost always shows up in plain text in these files.

Stop guessing at MCP failures

MCP Forge Kit ships a working server with stderr-only logging, schema-validated tools, correct transport setup, and env handling baked in, so the four failure modes above never bite you in the first place.

Get MCP Forge Kit, €39

Related: Claude and Cursor setup · Deploy securely · Write a secure tool