-32000 connection closed means the MCP session started, then terminated before the client received a valid response. The server process crashed, timed out, or wrote invalid output to stdout.
This is the most common MCP error across Cursor, VS Code, and Claude Desktop. It affects both stdio and HTTP servers, but the causes differ completely between the two.
The short answer: If you're running a local stdio server, the cause is almost always stdout contamination or a PATH issue. If you're running a remote HTTP server, it's usually a timeout, auth failure, or proxy misconfiguration.
The MCP stdio transport uses your server process's standard output exclusively for JSON-RPC messages. If anything else writes to stdout — a debug log, a startup banner, a print() statement, a deprecation warning from a dependency — the client receives invalid JSON, drops the connection, and logs -32000.
The server runs fine in your terminal (where you read mixed output) and fails inside the IDE.
How to verify:
bash# Run your server and check if stdout contains anything other than JSON-RPC # If you see ANY non-JSON output, that's the problem node your-server.js 2>/dev/null | head -c 500 # For Python servers python your-server.py 2>/dev/null | head -c 500
If the output starts with a log message, a banner, or anything that isn't {"jsonrpc":"2.0"..., you've found the cause.
How to fix:
python# Python — WRONG: writes to stdout, breaks MCP stream print("Server starting...") # Python — CORRECT: stderr is invisible to the MCP client import sys print("Server starting...", file=sys.stderr)
typescript// TypeScript — WRONG: console.log writes to stdout console.log("Debug info"); // TypeScript — CORRECT: console.error goes to stderr console.error("Debug info");
Search your entire codebase for console.log, print(), and sys.stdout.write calls. Also check dependencies — a third-party library printing a deprecation notice on import will break your server without any change to your code.
For SDK-specific guidance, see the MCP Python SDK and TypeScript SDK documentation on stderr-safe logging.
Your IDE launches MCP servers as subprocesses using its own shell environment — which is not the same as your terminal. It doesn't source .bashrc, .zshrc, or your version manager's shell hooks.
If you use nvm, pyenv, fnm, or Homebrew-managed runtimes, the node or python binary your IDE finds may be different from — or completely absent from — what you see in your terminal.
How to verify:
bash# Find where your actual binaries live which node # → /Users/you/.nvm/versions/node/v22.4.0/bin/node which npx # → /Users/you/.nvm/versions/node/v22.4.0/bin/npx which python3 # → /Users/you/.pyenv/shims/python3
How to fix:
Use the absolute path in your MCP config instead of just the command name:
json{ "mcpServers": { "my-server": { "command": "/Users/you/.nvm/versions/node/v22.4.0/bin/npx", "args": ["-y", "some-mcp-package"] } } }
On Windows, use where node instead of which node to find the path.
If the server takes too long to respond to the initialize request — common with serverless platforms (Vercel, Cloudflare Workers, AWS Lambda) during cold starts — the IDE drops the connection.
How to verify:
bash# Time the handshake response curl -s -w "\nResponse time: %{time_total}s\n" \ -X POST https://your-server-url/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}'
If response time is over 3 seconds, IDE timeouts are likely. Solutions:
A wrong or malformed Authorization header causes the server to reject the request silently. No useful error is surfaced — the IDE sees a closed connection and reports -32000.
A single extra space — Bearer token instead of Bearer token — is enough to cause this.
Corporate proxies, VPNs, and load balancers with aggressive idle timeouts close the connection before the server responds. Check:
If the client sends plain HTTP but the server expects SSE (or vice versa), the connection is established but immediately closed when the first message doesn't match the expected format.
Help → Toggle Developer Tools → Console tab
— or —
Output panel (Ctrl+Shift+U) → select "MCP" from dropdown
Look for Starting new stdio process, Client closed for command, or the raw error code after Connection closed.
Output panel (Ctrl+Shift+U) → select "MCP" from dropdown
— or —
Help → Toggle Developer Tools → Console → filter for "mcp"
bash# macOS — stream log entries live tail -f ~/Library/Logs/Claude/mcp*.log # Windows — read the latest log file type %APPDATA%\Claude\logs\mcp*.log
Remember: Claude Desktop needs a full application quit, not just a window close, to reload config.
| Symptom | Most likely cause | Fix |
|---|---|---|
-32000 immediately on server start | Stdout contamination | Move all logs to stderr |
-32000 after "Starting new stdio process" | PATH issue — binary not found | Use absolute path from which node |
-32000 only on first call, works on retry | Cold start timeout (serverless) | Add keep-warm ping or increase timeout |
-32000 after config change | Config syntax error or wrong key | Paste config into jsonlint.com |
-32000 intermittently | Proxy/firewall idle timeout | Increase idle timeout to 30s+ |
-32000 only on specific machine | Different PATH environments | Use absolute paths on both machines |
npx @modelcontextprotocol/inspector node your-server.jsFor a complete testing workflow, see How to Test MCP Servers.
IDE setup guides: VS Code · Cursor · Claude Desktop · Windsurf