mcp-debugger

Step-through debugging over MCP: breakpoints, stepping, stack and variables via real language debuggers

By Debug MCP JavaScript Local · stdio Developer tools

55 popularity score ★ 185 ↓ 3.2k/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server.

Or add it by command or config

Claude CodeTerminal
claude mcp add debugger -- npx -y @debugmcp/mcp-debugger stdio
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "debugger": {
      "command": "npx",
      "args": [
        "-y",
        "@debugmcp/mcp-debugger",
        "stdio"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "debugger": {
      "command": "npx",
      "args": [
        "-y",
        "@debugmcp/mcp-debugger",
        "stdio"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "debugger": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@debugmcp/mcp-debugger",
        "stdio"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.debugger]
command = "npx"
args = ["-y", "@debugmcp/mcp-debugger", "stdio"]
Gemini CLITerminal
gemini mcp add --scope user debugger npx -- -y @debugmcp/mcp-debugger stdio
Local (Docker)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

Claude CodeTerminal
claude mcp add debugger -- docker run -i --rm -v '<ABSOLUTE_PATH>:/workspace' debugmcp/mcp-debugger:latest
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "debugger": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-v",
        "<ABSOLUTE_PATH>:/workspace",
        "debugmcp/mcp-debugger:latest"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "debugger": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-v",
        "<ABSOLUTE_PATH>:/workspace",
        "debugmcp/mcp-debugger:latest"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "debugger": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-v",
        "<ABSOLUTE_PATH>:/workspace",
        "debugmcp/mcp-debugger:latest"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.debugger]
command = "docker"
args = ["run", "-i", "--rm", "-v", "<ABSOLUTE_PATH>:/workspace", "debugmcp/mcp-debugger:latest"]
Gemini CLITerminal
gemini mcp add --scope user debugger docker -- run -i --rm -v '<ABSOLUTE_PATH>:/workspace' debugmcp/mcp-debugger:latest

Settings 5

DEBUG_MCP_VARIABLE_ACCESS Optional: open or explicit. explicit makes the variable tools require a list of names. Default open. For get_variables, get_local_variables.
DEBUG_MCP_BP_ADDRESSING Optional: line, assert or content. line allows line numbers only, assert adds expectedContent, content adds statement and function anchors. Default content. For set_breakpoint.
DEBUG_MCP_NO_REDACT Optional: Set to 1 or true to turn off masking of credential-like values in results, which is on by default.
DEBUG_MCP_DISABLE_LANGUAGES Optional: Comma-separated adapters to disable, e.g. go,dotnet.
CODELLDB_PATH Optional: Path to a CodeLLDB binary when the optional platform package was not installed. For Rust, C/C++ and COBOL.

In a container, a setting goes in with -e NAME=value after docker run.

What it does

mcp-debugger turns a debugger into a set of tool calls. An assistant opens a session for a language, sets breakpoints, launches a script or attaches to a running process, then steps through the code and evaluates expressions while the program is paused. Underneath it speaks the Debug Adapter Protocol to existing debuggers: debugpy for Python, rdbg for Ruby, js-debug for JavaScript and TypeScript, Delve for Go, a JDI bridge for Java, netcoredbg for .NET, CodeLLDB for Rust, C/C++ and COBOL, and the SDK's own adapters for Dart and Flutter.

It runs as a standalone Node process with no IDE, so it fits CI runners and containers as well as a terminal. Besides line breakpoints you can pin a breakpoint to a function name or to a statement's text. Logpoints record values without pausing. It keeps the program's stdout and stderr for reading back. A read-only, token-gated endpoint lets a person's IDE watch the same live session. Launch sessions pause on uncaught exceptions by default, except Ruby, where rdbg has no such filter. For Python tests, start_debugging can run a single pytest test and stop at the failing assert without a breakpoint.

Since the Dart release, continue_execution returns at once and wait_for_stop is how you block until the next stop. The Java hot-swap tool is now hot_reload, which also does Flutter hot reload. The tool schema file registers 29 tools. The old name redefine_classes is still accepted on a call, with a deprecation warning, but it is no longer listed by tools/list and goes away at 1.0.

Three settings the README only touches in a table come from the code. DEBUG_MCP_VARIABLE_ACCESS=explicit makes get_variables and get_local_variables demand a list of names instead of dumping whole scopes. DEBUG_MCP_BP_ADDRESSING=line strips the statement and function anchors from set_breakpoint. DEBUG_MCP_DISABLE_LANGUAGES takes a comma-separated list of adapters to switch off.

What it needs

RuntimeNode.js 22+
Runs onmacOS, Windows, Linux
Also
  • The debugger for each language you use (debugpy, rdbg, Delve, JDK 21+, netcoredbg, Dart SDK and so on)
  • Docker, for the container way

Each language you debug needs its own toolchain: Python with debugpy, Ruby with the debug gem (rdbg), Go with Delve, JDK 21+, the .NET SDK with netcoredbg, the Rust toolchain, g++ or clang++ for C/C++ source launch, GnuCOBOL 3.1.2+ for COBOL source launch, and the Dart or Flutter SDK (on PATH, or set DART_SDK or FLUTTER_ROOT) for Dart. Run `flutter --version` once before the first Flutter session. js-debug and CodeLLDB come with the npm package (CodeLLDB as a per-platform optional dependency, so with --omit=optional set CODELLDB_PATH). `npx @debugmcp/mcp-debugger doctor` reports what is missing. The Docker image needs a mounted workspace.

Limits

  • Limit redefine_classes is a deprecated alias of hot_reload. Calls still work with a warning, it is not listed, and it is due to be removed at 1.0.
  • Not covered hot_reload works on Java and Flutter sessions only and is refused for other languages.
  • Not covered Logpoints work in the Python, JavaScript, Go, Rust, C/C++, COBOL, Dart and mock adapters, not in Java, .NET or Ruby.
  • Not covered suspendPolicy works with Java sessions only.
  • Not covered Ruby launch sessions do not pause on uncaught exceptions by default, since rdbg has no uncaught-only filter.
  • Platform In the Docker image Go and .NET are disabled, Ruby can only attach, and Flutter is missing because the image has no Flutter SDK.
  • Platform Rust debugging on Windows needs the GNU toolchain.
  • Limit The HTTP transport listens on 127.0.0.1 port 3001 by default and has no sign-in of its own.
  • Limit wait_for_stop and hot_reload wait 30 seconds by default and at most 600 seconds. A client's own request timeout may cut in sooner.
  • Not covered PHP is not supported.

Launches answer after a short hold. If the program has not stopped by then, start_debugging, pause_execution and the other waiting tools return pending:true and leave the program running with breakpoints armed. Call wait_for_stop to keep waiting. In the Docker image Go and .NET are switched off and Flutter is missing, so run those through npx next to your own toolchain.

Who it suits

Suits developers who want an assistant to debug a program in a terminal, CI job, container or pod, where no IDE is running, including attaching to a remote debugpy, rdbg, JDWP or V8 inspector port. It is local, needs no account, and drives the toolchains you already have. If your assistant works inside a running VS Code and you want VS Code's own debugger, its README points to Microsoft's DebugMCP extension, which also covers PHP. Pick something else if you cannot install the per-language debuggers, or if letting an assistant launch programs and evaluate code on the machine is not acceptable.

Tools 29

11 only read, 18 change things. A ? marks an optional parameter.

create_debug_session changes
Open a session for a language, in launch mode or attached to a running targetlanguage: enumname?: stringexecutablePath?: stringhost?: stringport?: numberprocessId?: anysourcePaths?: arrayjustMyCode?: booleanbreakOnExceptions?: enumstopOnEntry?: booleantimeout?: numberverifyTimeout?: numberadapterConfig?: object
list_supported_languages
Show the language adapters and whether each can launch or attach here
list_debug_sessions
List open sessions, with the reason a paused one last stopped
set_breakpoint changes
Add a breakpoint by line, statement text or function, optionally conditional or as a logpointsessionId: stringfile?: stringline?: numbercondition?: stringlogMessage?: stringsuspendPolicy?: enumexpectedContent?: stringstatement?: stringnearLine?: numberfunction?: string
list_breakpoints
Show a session's breakpoints and whether the debugger verified themsessionId: stringfile?: string
remove_breakpoint changes
Delete a breakpoint by id, function name or file and linesessionId: stringbreakpointId?: stringfunction?: stringfile?: stringline?: number
clear_breakpoints changes
Delete all breakpoints, or those in one filesessionId: stringfile?: string
start_debugging changes
Launch a script, program or pytest test under the debugger and report its first stopsessionId: stringscriptPath: stringargs?: arraydapLaunchArgs?: objectdryRunSpawn?: booleanbreakOnExceptions?: enumtestRunner?: stringtestTarget?: stringadapterLaunchConfig?: object
restart_debugging changes
Relaunch with the previous configuration and breakpointssessionId: string
attach_to_process changes
Attach to a running process by host and port or by process idsessionId: stringport?: numberhost?: stringprocessId?: anytimeout?: numberverifyTimeout?: numbersourcePaths?: arraystopOnEntry?: booleanjustMyCode?: booleanbreakOnExceptions?: enumadapterConfig?: object
detach_from_process changes
Let go of an attached process, optionally ending itsessionId: stringterminateProcess?: boolean
expose_session changes
Open a read-only, token-gated DAP endpoint so an IDE can watch the sessionsessionId: string
unexpose_session changes
Close that endpoint and drop connected IDEssessionId: string
close_debug_session changes
End a sessionsessionId: string
step_over changes
Run the current line and stop at the nextsessionId: string
step_into changes
Step into the function being calledsessionId: string
step_out changes
Run until the current function returnssessionId: string
continue_execution changes
Resume until the next breakpoint or the end, without waitingsessionId: string
wait_for_stop
Wait until the session next pauses or ends, then report where and whysessionId: stringtimeout?: number
pause_execution changes
Pause a running programsessionId: string
list_threads
List the program's threadssessionId: string
get_variables
Read the variables under a scope referencesessionId: stringscope: numbernames?: array
get_local_variables
Read the local variables of the current framesessionId: stringincludeSpecial?: booleannames?: array
get_stack_trace
Return the call stack of a paused threadsessionId: stringincludeInternals?: booleanthreadId?: number
get_scopes
Return the variable scopes of a stack framesessionId: stringframeId: number
evaluate_expression changes
Evaluate an expression in the paused program's contextsessionId: stringexpression: stringframeId?: numbertimeout?: number
get_source_context
Show source lines around a given linesessionId: stringfile: stringline: numberlinesContext?: number
get_output
Read the program's buffered stdout and stderrsessionId: stringsince?: numberlimit?: number
hot_reload changes
Push changed code into the running program: Flutter hot reload or Java class redefinitionsessionId: stringclassesDir?: stringsinceTimestamp?: numbertimeout?: number

Similar servers