Back to Blog
DevelopmentFeb 18, 202618 min read

MCP Server Not Working? Fix Error -32000, Timeouts, and Connection Failures (2026)

NT

Nikhil Tiwari

MCP Playground

QUICK FIX CHECKLIST

  • Error -32000 → Your server is printing to stdout. Redirect all logs to stderr.
  • Connection timeout → Wrong transport type (HTTP vs SSE vs stdio) or incorrect URL path.
  • 406 Not Acceptable → Server expects SSE transport, not HTTP. Switch transport in your client.
  • "Spawn ENOENT" → Node.js or Python path is wrong. Use absolute paths in your config.
  • Works locally, fails remotely → Missing CORS headers, or Vercel Deployment Protection is blocking.

MCP servers fail silently, throw cryptic error codes, and give almost no useful feedback when something goes wrong. If you're staring at a broken connection with no idea why, you're not alone — error -32000 alone accounts for 97% of all MCP connection failures.

This guide covers every common MCP error, explains what's actually happening, and gives you the exact fix. We've organized it by error type so you can jump straight to your problem.

Error -32000: Connection Closed

This is the most common MCP error by far. It means the JSON-RPC connection was terminated unexpectedly. The server started but crashed or produced invalid output before completing the handshake.

Cause 1: stdout pollution (43% of cases)

The MCP stdio transport uses stdout exclusively for JSON-RPC messages. If your server code — or any dependency — writes anything else to stdout, it corrupts the protocol stream and the client drops the connection.

BAD — These break MCP

print("Server starting...")           # Python
console.log("Debug info")              # Node.js
logger.info("Processing request")      # If logger writes to stdout

GOOD — These are safe

print("Server starting...", file=sys.stderr)   # Python
console.error("Debug info")                    # Node.js
logging.basicConfig(stream=sys.stderr)         # Python logging

Fix: Search your entire codebase for print( and console.log( calls. Replace every one with stderr equivalents. Check third-party libraries too — some print banners or warnings to stdout on import.

Cause 2: Wrong Node.js or Python path (28% of cases)

MCP clients like Claude Desktop and Cursor launch your server as a subprocess. If the path to node or python is wrong, the process fails to start and you get -32000.

This is especially common with nvm (Node Version Manager) or pyenv, because the shell PATH inside the MCP client process differs from your terminal.

Fix: Use absolute paths in your MCP configuration:

// Find your absolute paths first:
// Terminal: which node → /Users/you/.nvm/versions/node/v22.0.0/bin/node
// Terminal: which python3 → /usr/local/bin/python3

{
  "mcpServers": {
    "my-server": {
      "command": "/Users/you/.nvm/versions/node/v22.0.0/bin/node",
      "args": ["/absolute/path/to/server.js"]
    }
  }
}

Cause 3: JSON config syntax errors (15% of cases)

A single trailing comma or missing quote in your MCP config file silently prevents the server from launching.

Fix: Validate your JSON config. Run it through jq or any JSON validator:

# Validate Claude Desktop config
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | jq .

# Validate Cursor config
cat .cursor/mcp.json | jq .

Cause 4: Missing dependencies (9% of cases)

The server file exists, but a required npm package or Python module isn't installed in the environment the MCP client uses.

Fix: Run the server manually first to catch import errors:

# Python
python3 /path/to/your/server.py

# Node.js
node /path/to/your/server.js

# If using npx
npx -y @modelcontextprotocol/server-filesystem /path/to/dir

Error -32001: Request Timeout

The MCP client sent a request and didn't get a response within the timeout window (typically 60 seconds). Your server is running but a specific tool execution is taking too long.

Common causes

  • Slow external API call — your tool calls a third-party API that hangs or is rate-limited
  • Large data processing — your tool processes large files or datasets synchronously
  • Deadlock or infinite loop — a bug in your tool handler that never returns
  • DNS resolution failure — the server can't reach an external service

Fix: Add timeouts to all external calls in your tool handlers:

# Python — always set a timeout
import httpx

async def my_tool(url: str) -> str:
    async with httpx.AsyncClient(timeout=10.0) as client:
        response = await client.get(url)
        return response.text
// Node.js — use AbortController
async function myTool(url) {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 10000);
  try {
    const res = await fetch(url, { signal: controller.signal });
    return await res.text();
  } finally {
    clearTimeout(timeout);
  }
}

406 Not Acceptable

You're sending HTTP requests to a server that only accepts SSE (Server-Sent Events) transport, or vice versa. This is a transport mismatch.

Fix: Switch the transport type in your client. In MCP Playground, toggle between HTTP and SSE in the transport selector. In your client config, check the server's documentation for the correct transport.

HTTP / Streamable HTTP

The modern standard. Single endpoint at /mcp. Used by most remote servers, Cloudflare, Vercel.

SSE (Server-Sent Events)

Legacy transport. Two endpoints: /sse for streaming + separate POST endpoint. Some older servers still use this.

"Spawn ENOENT" or "Command Not Found"

The MCP client can't find the executable specified in your config. The path to node, python, npx, or uvx doesn't exist in the client's process environment.

Fix:

  1. Find the absolute path: which node or which python3
  2. Use that absolute path in your MCP config instead of just "node" or "python3"
  3. For npx: use the full path like /usr/local/bin/npx

Works Locally, Fails Remotely

Your server works fine with stdio transport on your machine, but remote clients can't connect over HTTP. This is almost always one of these issues:

Missing CORS headers

Browser-based MCP clients (like MCP Playground) need CORS headers. Your server must return:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization

Vercel Deployment Protection

If your server is on Vercel, Deployment Protection blocks non-browser requests by default. Disable it for your MCP route or use the production URL.

Wrong URL path

Most MCP servers expose their endpoint at /mcp, but some use /sse, /api/mcp, or a custom path. Double-check the server's documentation.

Firewall or network

The server may be behind a VPN, firewall, or private network. Ensure the URL is publicly accessible. Test with: curl -X POST https://your-server.com/mcp

Authentication Errors (401 / 403)

The server requires authentication and you're either not sending credentials or sending the wrong ones.

Common patterns

Auth Type Header Format Example
Bearer token Authorization: Bearer TOKEN Most OAuth-based servers
API key X-API-Key: KEY Simple key-based servers
Basic auth Authorization: Basic BASE64 Legacy systems

Fix: In MCP Playground, paste your auth header in the "Auth Header" field. For Claude Desktop or Cursor, add the header in your config's env section and reference it in your server's startup command.

Tools Load But Execution Fails

You can see the tools listed, but running them returns an error. This means the connection and discovery work — the bug is in the tool handler.

Debugging steps

  1. Check the protocol logs — in MCP Playground, open the Logs panel and filter by "error" to see the exact JSON-RPC error
  2. Check parameter types — MCP sends all values as their JSON types. If your tool expects an integer but gets a string, it may crash
  3. Check server-side logs — SSH into your server or check your platform's log viewer (Vercel, Cloudflare, etc.)
  4. Test the tool in isolation — call the underlying function directly without MCP to verify it works

Debugging Tools and Techniques

MCP Playground (Browser-Based)

MCP Playground is the fastest way to debug remote MCP servers. Connect to your server, and the Logs panel shows every JSON-RPC message in real-time — requests, responses, and errors with latency timing.

MCP Inspector (CLI)

The official debugging tool from the MCP team. Launches a browser UI for testing local servers:

npx @modelcontextprotocol/inspector node server.js
# Opens browser at http://localhost:6274

Claude Desktop Logs

# macOS
tail -n 50 -f ~/Library/Logs/Claude/mcp*.log

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

Cursor MCP Logs

Open the Cursor output panel (Ctrl+Shift+U) and select "MCP" from the dropdown. Error messages and connection status appear here.

VS Code MCP Logs

Click on the error notification in the chat panel, or open the Output panel and select the MCP server channel from the dropdown.

Quick Reference: Error Code Table

Error Code Name Most Likely Cause Quick Fix
-32000 Connection Closed stdout pollution or wrong path Redirect logs to stderr, use absolute paths
-32001 Request Timeout Slow external API Add timeouts to all HTTP calls
-32002 Resource Not Found Invalid resource URI Check URI format in resources/list response
-32050 Rate Limited Too many requests Add retry with exponential backoff
-32600 Invalid Request Malformed JSON-RPC Validate your request format
-32601 Method Not Found Server doesn't support that method Check server capabilities
-32602 Invalid Params Wrong argument types Match params to tool's input schema
-32603 Internal Error Unhandled exception in tool Check server logs for stack trace

Still Stuck?

If none of the above solved your issue:

  1. Reproduce minimally — strip your server down to a single tool and test again
  2. Check MCP SDK version — ensure you're on the latest version (pip install --upgrade mcp or npm update @modelcontextprotocol/sdk)
  3. Test with a known-working server — connect to a public MCP server in MCP Playground to confirm your client setup works
  4. Check GitHub Issues — search the MCP GitHub repos for your specific error

Debug Your MCP Server

Connect to your server, inspect tools, and view real-time protocol logs

Open MCP Playground →

Related Content

Frequently Asked Questions

Why does my MCP server work in terminal but not in Claude Desktop?
Claude Desktop launches your server as a subprocess with a different shell environment than your terminal. It doesn't load .bashrc, .zshrc, or nvm. This means node, python, and npx may not be on the PATH. Use absolute paths in your Claude Desktop config to fix this.
How do I debug an MCP server that crashes on startup?
Run the exact command from your MCP config manually in your terminal. For example: /usr/local/bin/node /path/to/server.js. If it prints an error and exits, that's what's happening inside the MCP client too. Fix the error, then restart the client.
Can I use console.log for debugging in an MCP server?
Not with stdio transport — console.log writes to stdout and corrupts the JSON-RPC stream. Use console.error instead, which writes to stderr. For HTTP transport servers, console.log is safe because stdout isn't used for the protocol.
What's the difference between error -32000 and -32603?
Error -32000 means the connection itself failed — the server couldn't start or the transport broke. Error -32603 means the connection is fine but a specific tool call threw an unhandled exception. -32000 is a setup problem; -32603 is a code bug in your tool handler.
My server returns empty tool results — what's wrong?
Your tool handler is likely returning undefined or an empty object. MCP tools must return a content array with at least one item. Ensure your handler returns: { content: [{ type: "text", text: "result" }] }
NT

Written by Nikhil Tiwari

15+ years in product development. AI enthusiast building developer tools that make complex technologies accessible to everyone.