| name | mcp-debugger |
| description | Deep, evidence-first debugging for Model Context Protocol (MCP) servers and client integrations across Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, and Claude.ai remote connectors. Use when diagnosing why an MCP server fails to appear, connect, or stay connected: stdio launch failures (spawn ENOENT/EINVAL, npx/uvx on Windows, stdout JSON-RPC contamination, missing env/PATH, stale build, exit codes); Streamable HTTP or legacy SSE transport, session-id and protocol-version errors; remote server and OAuth 2.1 problems (401/403 loops, WWW-Authenticate discovery, audience/resource binding, DCR, PKCE, mcp-remote); MCP Inspector testing; tool/resource/prompt schema and capability-negotiation failures; or config/log issues in any client. Use this whenever MCP tools or a server misbehave, even if the user only names a symptom (server disconnected, no tools showing, spawn ENOENT, connection failed) and does not say "MCP". |
MCP Debugger
Operating Rules
Debug MCP issues as a layered system: client host, launch configuration, server process,
transport, protocol lifecycle, capability negotiation, MCP features, and upstream services.
Do not diagnose from UI symptoms alone. Gather evidence, isolate one failing layer, change
one thing, and retest through the same path.
Anchor modern protocol facts to MCP 2026-07-28. A modern request carries per-request _meta; it has no initialize exchange or Mcp-Session-Id. Treat a 2025-11-25 initialize flow as explicitly legacy or a deliberate dual-era branch.
For version negotiation, server/discover, the -32020/-32021/-32022 error triad, or dual-era diagnosis, route to $mcp-2026-migration and run its modern-first probe.
Protect secrets in every artifact. Redact API keys, bearer tokens, session IDs, private
data, and env values before showing logs or config. Keep path details when they are
relevant to startup or filesystem permission failures.
Dependencies
The bundled scripts need Python 3.8+ (invoke as python on Windows, python3 on
macOS/Linux). Reproduction commands assume node/npx (Inspector and npm servers),
uv/uvx (Python servers), and curl/openssl (network triage). Do not assume these are
installed — check, and adapt to what the host has.
Resource Routing
Load deeper resources only when the layer points there:
references/clients.md: Identify the client host, then get its config path, top-level JSON
key, server-entry shape, add-server command, logs, and reload action. Read this first when
the host is not Claude Desktop.
references/claude-desktop.md: Claude Desktop config paths (incl. MSIX/LocalCache),
Windows launcher fixes (cmd /c), PATH/env inheritance, logs, exit codes, DevTools.
references/claude-code.md: Claude Code CLI — claude mcp commands, scopes/precedence,
project approval, /mcp, claude --debug mcp, OAuth.
references/protocol-and-transport.md: legacy lifecycle, stdio purity, Streamable HTTP, and transport detection. For 2026 per-request metadata and dual-era routing, use $mcp-2026-migration.
references/remote-and-auth.md: remote endpoints — network/TLS/proxy failures, the OAuth 2.1 discovery chain, DCR/PKCE/audience binding, mcp-remote, hosted connectors.
references/tool-resource-prompt-checks.md: a server that starts but whose tools,
resources, prompts, schemas, or results fail.
references/debugging.md: local stdio deep-dive — launchers, exit codes, stdout
contamination, env/cwd, build staleness, permissions.
references/mcpinspector.md: MCP Inspector 2.0 — web/CLI/TUI modes, API-token auth,
binding and origin controls, transports, and security model.
Scripts (execute, do not read into context):
scripts/claude_desktop_diagnostics.py: validate a Claude Desktop config — JSON, env
redaction, command resolution, Windows shim-spawn (cmd /c) detection, BOM, and MSIX
path divergence, plus a recent-log preview.
scripts/mcp_http_probe.py --legacy <url>: explicitly probe a legacy endpoint — initialize handshake, session ID, tool list, and any 401 + WWW-Authenticate challenge. For a modern-first or dual-era endpoint, execute ../mcp-2026-migration/scripts/mcp_2026_probe.py <url> instead.
Initial Triage
Collect the smallest complete case:
- Client host and version: Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, a custom
client, or a Claude.ai remote connector.
- OS, shell, and runtime managers: Windows/macOS/Linux, PowerShell/bash/zsh,
nvm, pyenv,
uv, Docker, etc.
- Transport:
stdio, Streamable HTTP, older HTTP+SSE, or unknown.
- Server implementation: language, SDK, package manager, repo path, build output path.
- Launch source: client config, terminal command, Docker,
npx, uvx, uv, node,
python, mcp-remote, or a binary.
- Config excerpt: server name,
command, args, env, HTTP URL, auth settings.
- Exact symptom: absent server, connection error, initialization error, missing tools, failed
tool call, timeout, auth failure, or client UI error.
- Fresh logs from both server and client.
- Reproduction surface: Inspector, target client, both, or only one.
Client Router
Identify the client host before validating config or reloading — the config path, top-level
key, log location, and reload action all differ. Open references/clients.md to get them.
One trap worth checking immediately: the top-level key is mcpServers for Claude Desktop,
Cursor, Windsurf, and Claude Code, but servers (with a required type) for VS Code.
Failure Map
Classify before editing:
| Symptom | Likely failed layer | Load / run |
|---|
| Server absent from the client | Client config / launch config | clients.md, claude-desktop.md; run claude_desktop_diagnostics.py |
spawn ENOENT/EINVAL on Windows | Command resolution or launcher type | claude-desktop.md; resolve command, wrap only a failing .cmd/.bat shim |
| Connects then drops / "disconnected" | Server process / stdout framing | debugging.md (read mcp-server-<NAME>.log) |
| Silent failure after a Desktop update, no logs | Unknown config/log root or process never launched | claude-desktop.md; enumerate candidates and reproduce |
| Tools/resources/prompts missing | Features / stale build | tool-resource-prompt-checks.md, debugging.md |
| Tool call fails or times out | Schema / handler / upstream | tool-resource-prompt-checks.md |
HTTP -32020/-32021/-32022, 404 initialize, or per-request metadata error | Protocol era / request contract | $mcp-2026-migration; run mcp_2026_probe.py |
| HTTP 401/403 or OAuth loop | Remote auth | remote-and-auth.md; use the era-appropriate probe |
| Remote URL rejected by a command-only client entry | Client transport support or missing HTTP bridge | clients.md, then remote-and-auth.md if a bridge is required |
| Unsure whether it's the server or the client | Need isolation | mcpinspector.md (test the server alone) |
| Host is Claude Code CLI (zero tools, scope/approval) | Client-specific config | claude-code.md |
Workflow
-
Identify the client and validate its config (references/clients.md). For Claude Desktop,
run from the skill directory:
python scripts/claude_desktop_diagnostics.py
(If packaged as a plugin, use ${CLAUDE_PLUGIN_ROOT}/scripts/claude_desktop_diagnostics.py.)
-
Prove the server starts outside the client, using the exact command, args, env, and
absolute paths from the config. A healthy stdio server blocks on stdin and appears to
hang — that is normal, not a failure.
-
Isolate with MCP Inspector 2.0 before debugging the target host:
npx --yes @modelcontextprotocol/inspector@2.0.0 --web
npx --yes @modelcontextprotocol/inspector@2.0.0 --cli \
node /absolute/path/server/build/index.js --method tools/list
Inspector 2.0 requires Node >=22.19.0. Keep mode flags before application arguments.
-
For remote HTTP servers, establish the protocol era before editing code:
python ../mcp-2026-migration/scripts/mcp_2026_probe.py https://host/mcp
python scripts/mcp_http_probe.py --legacy https://host/mcp
-
For a modern request, inspect its _meta, response error code, and HTTP/header agreement before feature behavior. For an explicitly legacy request, inspect initialize, initialized, and its negotiated capabilities.
-
Debug the failing feature using the matching reference. Keep stdio stdout protocol-only; send logs to stderr, files, or an appropriate observability pipeline.
-
For HTTP, capture status, response body, headers, declared era, and auth metadata before changing code. Never print raw credentials or opaque state.
-
After each fix, rebuild if needed, rerun the direct command, reconnect in Inspector,
reload the target client the right way for that host (references/clients.md), and confirm
the original user-visible symptom is gone.
Reporting
Return a concise debugging report:
- Root cause and failed layer.
- Evidence used: config validation, log excerpt, Inspector result, probe output, protocol
exchange, or code path.
- Files/settings changed.
- Validation commands and results.
- Remaining risks: version compatibility, auth expiry, permissions, host-specific behaviour,
or unresolved logs.