Skip to content
Debugging
Skill

/debugging

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,

BOOST
From plugin
mcp-debugger
1791 skill
Install
$ npx -y skills add debugmcp/mcp-debugger --skill debugging --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/debugging

Context preview

The summary Claude sees to decide when to auto-load this skill.

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,

SKILL.md

debugging.SKILL.md
name: mcp-debugger
description: 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.

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)

1. create_debug_session   {language: "python"}                 -> sessionId
2. set_breakpoint         {sessionId, file: "<ABSOLUTE path>", statement: "<line text or distinctive substring>"}   (or line: N + expectedContent)
3. start_debugging        {sessionId, scriptPath: "<ABSOLUTE path>"}   -> paused at the breakpoint, or pending: true -> wait_for_stop {sessionId}
4. get_stack_trace        {sessionId}                          -> frames (use frame.id, never assume 0)
5. get_scopes             {sessionId, frameId: <frame.id>}     -> scope variablesReference
6. get_variables          {sessionId, scope: <variablesReference>}
   ... or get_local_variables {sessionId} for the common case
7. evaluate_expression    {sessionId, expression: "x + y"}
8. step_over / step_into / step_out / continue_execution
   wait_for_stop          {sessionId}                          -> blocks until the next stop or the exit (continue_execution does not wait)
9. get_output             {sessionId}                          -> captured debuggee stdout/stderr
10. close_debug_session   {sessionId}                          -> ALWAYS, even on failure

Rules that prevent 90% of failed sessions:

  • **Absolute paths only** for `file` and `scriptPath` (relative paths are rejected in host mode).
  • **Use real frame IDs.** Take `id` from `get_stack_trace` frames; it is adapter-assigned and is not 0-indexed.
  • **Expand variable containers.** If a variable entry carries a `variablesReference`, call `get_variables` again with that reference to see children (Python's "special variables", object fields, array elements).
  • **Respect session state.** Stepping, evaluation, and variable reads require `PAUSED`. After `continue_execution` the session is `RUNNING`; after a step or breakpoint hit it returns to `PAUSED` with a persisted stop reason telling you why it stopped (`breakpoint`, `step`, `entry`, `exception`, ...). `continue_execution` returns at once — call `wait_for_stop {sessionId}` to block until the program stops again or ends; it answers with the stop (`lastStop`, `location`) or the exit code.
  • **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` (answers `pending`), send the request, `wait_for_stop`. The same goes for any step, pause or attach that answers `pending: true`. `wait_for_stop` takes a `timeout` in ms (default 30000); when it runs out it answers `pending: true` again — 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 long `timeout`, 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; a `redaction` field 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 with `DEBUG_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 in `notFound`) instead of dumping the scope. `evaluate_expression` still works for targeted reads.
  • **Always `close_debug_session`** when done — it tears down the debuggee process tree.

Root-cause discipline

1. State a hypothesis about where reality diverges from expectation *before* setting breakpoints. 2. 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_breakpoints` shows what is currently set (with verified state and adapter ids).

  • Prefer `statement: "<line text>"` over line numbers: it matches like an Edit-tool
Read more
Ships withmcp-debugger

A headless, agentic debugger over MCP — let your AI agents debug running programs in ten languages.

Get the whole plugin
Stats
179
Stars
24
Forks
Active
Maintenance
TypeScript
Language
MIT
License
1h ago
Last commit
1y ago
Created
4h ago
Added

Repo: debugmcp/mcp-debugger