debugmcp/mcp-debugger/debugging
Claude Code and agent skill by debugmcp/mcp-debugger
- community
Checking that the SKILL.md file is still in the repository.
Use when investigating a bug, failing test, or unexpected runtime behavior and the mcp-debugger MCP server is available — drives real step-through debuggers (breakpoints, stack traces, variable inspection, expression evaluation) for Python, JavaScript/TypeScript, Ruby, Rust, Go, Java, .NET/C#, C/C++, COBOL, and Dart/Flutter, locally or attached to remote processes.
Install
npx vskill@latest install debugmcp/mcp-debugger/debuggingSKILL.md
Debugging with mcp-debugger
mcp-debugger exposes real language debuggers as MCP tools. Prefer it over print-debugging whenever you would otherwise need more than one edit-run cycle to see program state: a breakpoint plus evaluate_expression answers in one run what printf answers in three.
When to reach for the debugger
- A test fails and the assertion message doesn't explain why the value is wrong.
- Control flow surprises you (a branch that "can't happen", a loop that exits early).
- State mutates somewhere between two known-good points and you need to bisect.
- The bug lives in code you can't easily edit (third-party package, compiled artifact).
- You need ground truth about runtime types/values instead of inferring them from source.
Do NOT reach for it when a single glance at the code or one log line would answer the question — session setup costs a few seconds and the target must be runnable.
The golden path (launch)
Rules that prevent 90% of failed sessions:
- Absolute paths only for
fileandscriptPath(relative paths are rejected in host mode). - Use real frame IDs. Take
idfromget_stack_traceframes; it is adapter-assigned and is not 0-indexed. - Expand variable containers. If a variable entry carries a
variablesReference, callget_variablesagain with that reference to see children (Python's "special variables", object fields, array elements). - Respect session state. Stepping, evaluation, and variable reads require
PAUSED. Aftercontinue_executionthe session isRUNNING; after a step or breakpoint hit it returns toPAUSEDwith a persisted stop reason telling you why it stopped (breakpoint,step,entry,exception, ...).continue_executionreturns at once — callwait_for_stop {sessionId}to block until the program stops again or ends; it answers with the stop (lastStop,location) or the exit code. A session whose program spawned child sessions (Python, on by default;dapLaunchArgs: { subProcess: false }opts a launch out) is waited on as a tree: the answer'ssessionIdnames the session that stopped — use it to inspect — andchildrenlists the rest with their states. - A `start_debugging` that answers `running` with `pending: true` is not stuck. The launch holds its answer only briefly — about a second — for the program's first stop, so a breakpoint reached as the program starts is answered in the one call, and anything later is collected with
wait_for_stop {sessionId}, which blocks until the program stops or ends. Nothing was cancelled: breakpoints stay armed for as long as the program runs, and the message says what is armed. For a server, this is the workflow: set the breakpoint in the handler,start_debugging(answerspending), send the request,wait_for_stop. The same goes for any step, pause or attach that answerspending: true.wait_for_stoptakes atimeoutin ms (default 30000); when it runs out it answerspending: trueagain — just call it again. Keep each call under your MCP client's own request cap (45 s is safe under the common 60 s cap): a longer wait is several calls, not one longtimeout, or the client times out first. - Breakpoints may verify late. Some adapters (debugpy, JDI) report breakpoints unverified until the module/class loads; that is normal, not an error.
- `<redacted:...>` placeholders are masking, not program state. Credential-shaped values and values of sensitive variable names (
password,api_key, ...) are masked by default in variable/evaluate/output results; aredactionfield reports what was hidden. The real value is intact in the debuggee — don't "fix" it, and don't retry the read. The user can disable masking by restarting the server withDEBUG_MCP_NO_REDACT=1. - If `get_variables` demands `names`, the server is in least-privilege mode (
DEBUG_MCP_VARIABLE_ACCESS=explicit): pass the exact variable names you need (names: ["user", "total"]; case-sensitive, misses reported innotFound) instead of dumping the scope.evaluate_expressionstill works for targeted reads. - Always `close_debug_session` when done — it tears down the debuggee process tree.
Root-cause discipline
- State a hypothesis about where reality diverges from expectation before setting breakpoints.
- Set at most two breakpoints: last-known-good and first-known-bad. Run, inspect, halve the interval. Bisection beats stepping line-by-line from the top. Move the window mid-session with
remove_breakpoint/clear_breakpoints;list_breakpointsshows what is currently set (with verified state and adapter ids).
- Prefer
statement: "<line text>"over line numbers: it matches like an Edit-toolold_string(whole line or a distinctive substring — whitespace-trimmed, trailing comments ignored, exact matches win), only lands on a line containing your text (inexact or multi-candidate matches are flagged in the responsewarning), lists every occurrence on ambiguity (addnearLineto pick one), and re-resolves acrossrestart_debuggingafter you edit the file. When you do address by line, passexpectedContent: "<line text or distinctive substring>"(trailing comments ignored) so a stale or off-by-one line number fails immediately with the actual nearby lines. A response sayingrequested line N, bound to line Mmeans the adapter moved the breakpoint — trust the bound line. function: "name"breaks on entry to a symbol with no file or line at all — names survive edits best. Supported by Python/Go/Rust/.NET/Java/JavaScript, C/C++ and COBOL (paragraph, section or PROGRAM-ID names) — not Ruby or Dart/Flutter, which reject it up front (Java accepts baremethod,Class.method, or fully-qualified names and binds every concrete overload; JavaScript names are dotted runtime paths likeobj.methodbound to the current function value — main-module function declarations bind at launch, functions in lazily-loaded modules bind at the next pause).
- When pausing is too disruptive (hot loops, live or attached processes), use a logpoint:
set_breakpointwithlogMessage: "x={x}"streams interpolated values intoget_outputwithout stopping the program (Python/JS/Go/Rust, C/C++, COBOL — where{WS-NAME}is a COBOL data reference — and Dart/Flutter, where aconditionon the logpoint is ignored and every hit logs; Java, .NET and Ruby reject it with a clear error). - At each pause, record what you learned (variable values, actual control flow), not just where you are.
- When the diverging line is found, inspect every input to that line before concluding — the bug is usually an operand, not the operator.
- Fix, then
restart_debugging {sessionId}— one call relaunches with the same configuration and re-applies every breakpoint (the output buffer resets; readget_outputfromsince: 0). Confirm the observed state changed as predicted. Works even after the program exited; attach sessions are rejected (detach and re-attach instead).
Program output
get_output {sessionId} returns buffered debuggee stdout/stderr with a cursor: pass the returned nextSince back as since to read only new output. Each session also exposes the transcript as MCP resource debug://sessions/{id}/output with subscription support. Caveat: Ruby attach sessions capture no stdout (launch sessions stream it) — when attached to Ruby, verify behavior via evaluate_expression/breakpoints or have the program write a file.
Attach instead of launch
For an already-running process (including remote machines, containers, and Kubernetes pods via port-forward):
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/debugging/SKILL.md
Popularity
- Repository stars
- 144
- Repository forks
- 20
- 7-day trend score
- 25
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/debugmcp/mcp-debugger/debugging)