
Connects AI agents to debugpy, js-debug, CodeLLDB, Delve, JDI, and netcoredbg through the Debug Adapter Protocol. Exposes operations like create_debug_session, set_breakpoint, step_over, and get_variables as MCP tools with structured JSON responses. Ships with 1266+ tests and runs via npx with zero runtime dependencies. Reach for this when you want Claude to step through Python, JavaScript, Rust, Go, Java, or .NET code instead of just reading it. The mock adapter lets you test integration logic without spinning up actual debuggers. Available as npm package or Docker image, though Rust debugging needs local deployment to access your toolchain.
A headless, agentic debugger over MCP — let your AI agents debug running programs in nine languages.
mcp-debugger is a Model Context Protocol (MCP) server that exposes step-through debugging as structured tool calls. It lets AI agents set breakpoints, inspect variables, evaluate expressions, and step through running programs across nine languages — driving real language debuggers through the Debug Adapter Protocol (DAP).
No IDE required. mcp-debugger runs anywhere Node.js runs: CI runners, Docker containers, Kubernetes pods, SSH boxes, and the sandboxes that cloud coding agents live in. It's the debugger for where IDEs can't go.
Microsoft's DebugMCP exposes VS Code's debugger over MCP and is a good choice when your agent works inside a running VS Code. The two projects make different structural trade-offs:
| mcp-debugger | microsoft/DebugMCP | |
|---|---|---|
| Runs headless (CI, containers, k8s, cloud agents) | ✅ standalone Node process | ❌ requires a running VS Code |
| Transports | stdio + Streamable HTTP | Streamable HTTP (localhost) |
| Distribution | npx, npm, Docker image | VS Code Marketplace extension |
| Remote attach without an IDE | ✅ debugpy / rdbg / JDWP, incl. pods via port-forward | ❌ |
| Per-session process isolation | ✅ one proxy process per session | shares the VS Code instance |
Java hot-swap (redefine_classes) | ✅ | ❌ |
| Debuggee output as subscribable MCP resource | ✅ | ❌ |
| In-IDE debugging UX alongside the agent | ✅ read-only IDE mirror (expose_session) — the IDE joins the agent's live session | ✅ native |
| Logpoints without pausing (prod-safe value watching) | ✅ logMessage breakpoints | ✅ via VS Code |
Content/function-addressed breakpoints (statement:, function:, expectedContent) | ✅ agent-native addressing that survives edits | — |
| Secret redaction on by default | ✅ variable/evaluate/output masking + least-privilege mode | — |
| Kubernetes ephemeral debug sidecar (native attach-by-PID) | ✅ kubectl debug flow | ❌ |
| C/C++ | ✅ via CodeLLDB (launch + attach-by-PID) | ✅ via VS Code extensions |
| COBOL | ✅ via GnuCOBOL + CodeLLDB (launch + attach-by-PID, COBOL-shaped variables) | — |
| PHP | ❌ | ✅ via VS Code extensions |
| Languages | Python, JS/TS, Ruby, Rust, Go, Java, .NET, C/C++, COBOL | Python, JS/TS, Ruby, Rust, Go, Java, .NET, C/C++, PHP |
If your agent runs in a terminal, a pipeline, or a cloud sandbox — or needs to attach to a process on another machine — you want mcp-debugger.
🆕 v0.25.0 — COBOL debugging lands (GnuCOBOL + CodeLLDB, with COBOL-shaped variables, PERFORM-aware stepping and paragraph breakpoints), and Rust and C/C++ work out of the box on every platform npm installs now that CodeLLDB ships as per-platform packages. Also new:
mcp-debugger doctor, a Kubernetes debugging recipe, an HTTP transport locked to127.0.0.1with Host/Origin checks, launch responses that say how a run ended, exit codes for Go and Docker JavaScript, and a lighter startup. See the CHANGELOG for the full release history.
.cob/.cbl sources (auto-compiled with cobc) or prebuilt executables, attach by PID; WORKING-STORAGE / LOCAL-STORAGE / LINKAGE scopes with DISPLAY, COMP, COMP-3 and 88-level values decoded, breakpoints in copybooks, statement-granular stepping, and a pause on libcob runtime errors (the S0C7/SSRANGE analogues) — built for mainframe-to-GnuCOBOL migrations (guide)list_supported_languages reports per-mode availability with reasonsstatement: "total = sum(prices)"), by symbol (function: "main"), or assert line content with expectedContent; anchors re-resolve across restart_debugging and weak matches warn loudlyset_breakpoint with logMessage: "x={x}" streams interpolated values into get_output without pausing — prod-safe value watching on hot pathslist_breakpoints / remove_breakpoint / clear_breakpoints work live mid-run; restart_debugging relaunches with the same config and re-applies everything in one callget_output returns debuggee stdout/stderr with a cursor, and each session exposes its transcript as a subscribable MCP resourcebreakOnExceptions; exception class/message surfaced via lastStop)expose_session opens a loopback, token-gated DAP endpoint so a human's IDE can inspect the agent's live session without taking controlkubectl debug --target + attach-by-PID for native processes (recipe, turnkey manifests)npx @debugmcp/mcp-debugger - no installation neededDEBUG_MCP_NO_REDACT=1)Tools tell an agent what it can do; a skill teaches it how to debug well. This repo ships an agent skill covering the session golden path, root-cause discipline (bisection over line-by-line stepping), attach/remote recipes, and per-language quirks:
# Claude Code (user-level)
cp -r skills/debugging ~/.claude/skills/mcp-debugger
# Cross-agent directories (Copilot CLI and friends)
cp -r skills/debugging ~/.agents/skills/mcp-debugger
The server also serves condensed guidance in-band: MCP instructions on connect, plus a debugging-workflow prompt any MCP client can request. See skills/debugging/README.md for details.
Requirements: Node.js 22+ for the server. Each language you debug also needs its own toolchain installed (Python + debugpy, Ruby + the
debuggem /rdbg, Node.js, Go + Delve, JDK 21+, .NET SDK, the Rust toolchain, a C/C++ compiler — g++/clang++, only needed for source-file launch — or GnuCOBOL 3.1.2+ for COBOL source launch). Not sure what's installed? Runnpx @debugmcp/mcp-debugger doctorfor a per-adapter toolchain report.CodeLLDB platform note (npx/npm installs): the CodeLLDB debug engine ships as per-platform optional dependencies (
@debugmcp/codelldb-win32-x64,-darwin-x64,-darwin-arm64,-linux-x64,-linux-arm64) — npm installs exactly the one matching your platform, so Rust and C/C++ debugging work out of the box everywhere npm serves. If you install with--omit=optional, setCODELLDB_PATHto a CodeLLDB release binary instead, or use the Docker image.
Add to your MCP settings configuration:
{
"mcpServers": {
"mcp-debugger": {
"command": "node",
"args": ["C:/path/to/mcp-debugger/dist/index.js", "stdio", "--log-level", "debug", "--log-file", "C:/path/to/logs/debug-mcp-server.log"],
"disabled": false,
"autoApprove": ["create_debug_session", "set_breakpoint", "get_variables"]
}
}
}
Register the published stdio server with the Codex CLI:
codex mcp add mcp-debugger -- npx -y @debugmcp/mcp-debugger stdio
codex mcp list
Codex stores this entry in ~/.codex/config.toml. The ChatGPT desktop app, Codex CLI,
and Codex IDE extension share that configuration when they run on the same Codex host.
Restart the active desktop client or IDE extension (or start a new CLI session), then use
/mcp to confirm that mcp-debugger is connected. See the official
Codex MCP documentation for configuration and
troubleshooting details.
Developing mcp-debugger itself? Use the restartable source dev proxy instead of the published package.
For Claude Code users, we provide an automated installation script:
Prerequisite: The Claude CLI must be installed and available on your PATH before running the installation script. See Claude Code documentation for installation instructions.
# Clone the repository
git clone https://github.com/debugmcp/mcp-debugger.git
cd mcp-debugger
# Run the installation script
./scripts/install-claude-mcp.sh
# Verify the connection (use 'claude mcp list' if claude is on your PATH)
claude mcp list
Important: The stdio argument is required to prevent console output from corrupting the JSON-RPC protocol. See CLAUDE.md for detailed setup and troubleshooting.
pi 0.99 and later has built-in MCP support. The published @debugmcp/mcp-debugger package is
also a pi package: one install adds the mcp-debugger agent skill and an extension that registers
the server with pi's MCP support:
pi install npm:@debugmcp/mcp-debugger # the mcp-debugger skill, and the server via pi's built-in MCP
pi list # shows the package
The extension runs the CLI that pi install put on disk, so the server matches the skill and
starts without an npx download. It registers with deferred exposure: pi lists the debugger in
its system prompt, and the model loads the tools it needs with tool_search, named
mcp__mcp_debugger__<tool>. /mcp shows the server and changes its exposure for a session. A
mcp-debugger entry in ~/.pi/agent/mcp.json replaces the registration, for example to debug a
source build through the dev proxy.
To add only the server, without the skill: pi mcp add mcp-debugger -- npx -y @debugmcp/mcp-debugger stdio.
pi older than 0.99 has no built-in MCP support; the extension then does nothing, so upgrade pi.
docker run -i --rm -v $(pwd):/workspace debugmcp/mcp-debugger:latest
The Docker image debugs Python, JavaScript, Java, Rust, C/C++, and COBOL natively (toolchains — GnuCOBOL included — plus a shared vendored CodeLLDB), plus the mock adapter. Ruby is attach-only in the image (the adapter ships without a Ruby runtime — attach to any
rdbg --openprocess, local or remote). Only Go and .NET are disabled in the container — run those via npm/npx next to your local toolchain. Host-built Rust/C++ binaries debugged in the container get an auto-derived source map back to/workspace.list_supported_languagesreports per-mode availability (modes.launch/modes.attach) with reasons. See Docker support.
npm install -g @debugmcp/mcp-debugger
mcp-debugger --help
Or use without installation via npx:
npx @debugmcp/mcp-debugger --help
stdio is the default and is what most clients want. When the server has to run somewhere else
— a CI runner, a container, a Kubernetes pod — start it on a port instead:
mcp-debugger http --port 3001 # or: node dist/index.js http -p 3001
and point the client at it:
{
"mcpServers": {
"mcp-debugger": {
"type": "http",
"url": "http://127.0.0.1:3001/mcp"
}
}
}
Each HTTP client gets its own isolated server: debug sessions are never visible to another
client. A client that disconnects without DELETE /mcp keeps its debug sessions — and any
paused attach target — alive until the server reaps it: 2 minutes after its SSE stream
dropped (MCP_HTTP_STREAM_LOST_SESSION_MS), or 30 minutes idle if it never opened one
(MCP_HTTP_STALE_SESSION_MS). GET /health lists what each session is holding.
The port defaults to 3001, and the server listens on 127.0.0.1 only. --bind 0.0.0.0 (or
MCP_HTTP_BIND=0.0.0.0) listens on every interface — pair it with --allowed-host for the names other
machines will use; --bind localhost means 127.0.0.1, and only IP addresses are accepted. GET /health
on the same port answers a liveness check and reports the bound address and port under listening. The
legacy sse subcommand still exists but is deprecated — use http.
The server accepts only loopback Host headers by default — localhost, 127.0.0.1, [::1] —
as DNS-rebinding protection for an unauthenticated endpoint that can spawn processes and attach to
PIDs. A client on another machine reaches it through a port-forward or an SSH tunnel
(ssh -L 3001:127.0.0.1:3001 user@server, then http://127.0.0.1:3001/mcp), or you bind an
interface with --bind; any other Host gets a 403 that says so. To accept a service name directly — http://mcp-debugger:3001/mcp on a
container network — start the server with --allowed-host mcp-debugger (repeatable) or
MCP_HTTP_ALLOWED_HOSTS=mcp-debugger (comma-separated). That opt-in means another access control
fronts the server; there is no wildcard. Browser clients are checked against the same list by
their Origin, so a cross-site page cannot drive the debugger. The deprecated sse subcommand
applies the same allowlist and accepts the same flag.
mcp-debugger exposes debugging operations as MCP tools that can be called with structured JSON parameters:
// Tool: create_debug_session
// Request:
{
"language": "python", // or "ruby", "javascript", "rust", "go", "java", "dotnet", "cpp", "cobol", or "mock" for testing
"name": "My Debug Session"
}
// Response:
{
"success": true,
"sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
"message": "Created python debug session: My Debug Session"
}
All 29 tools below are implemented — see the tool reference for parameters and response shapes.
| Tool | Description | Status |
|---|---|---|
create_debug_session | Create a new debugging session | ✅ Implemented |
list_debug_sessions | List all active sessions | ✅ Implemented |
list_supported_languages | Show available language adapters | ✅ Implemented |
set_breakpoint | Set a breakpoint in a file | ✅ Implemented |
list_breakpoints | List a session's breakpoints with verified state | ✅ Implemented |
remove_breakpoint | Remove a breakpoint by id or file+line | ✅ Implemented |
clear_breakpoints | Remove all breakpoints (optionally per file) | ✅ Implemented |
start_debugging | Start debugging a script | ✅ Implemented |
restart_debugging | Relaunch with the same config, breakpoints re-applied | ✅ Implemented |
attach_to_process | Attach debugger to a running process | ✅ Implemented |
detach_from_process | Detach debugger from a process | ✅ Implemented |
expose_session | Open a read-only DAP mirror endpoint so an IDE can attach and inspect | ✅ Implemented |
unexpose_session | Close the mirror endpoint and disconnect IDE clients | ✅ Implemented |
get_stack_trace | Get the current stack trace | ✅ Implemented |
list_threads | List all threads in the debug session | ✅ Implemented |
get_scopes | Get variable scopes for a frame | ✅ Implemented |
get_variables | Get variables in a scope | ✅ Implemented |
get_local_variables | Get local variables in current frame | ✅ Implemented |
step_over | Step over the current line | ✅ Implemented |
step_into | Step into a function | ✅ Implemented |
step_out | Step out of a function | ✅ Implemented |
continue_execution | Continue running | ✅ Implemented |
wait_for_stop | Block until the session next pauses or ends | ✅ Implemented |
pause_execution | Pause running execution | ✅ Implemented |
evaluate_expression | Evaluate expressions in debug context | ✅ Implemented |
get_source_context | Get source code context | ✅ Implemented |
get_output | Read captured debuggee output (stdout/stderr) | ✅ Implemented |
close_debug_session | Close a session | ✅ Implemented |
redefine_classes | Hot-swap changed Java classes into a running JVM (Java only) | ✅ Implemented |
Version 0.10.0 introduces a clean adapter pattern that separates language-agnostic core functionality from language-specific implementations:
┌─────────────┐ ┌────────────────┐ ┌──────────────┐ ┌─────────────────┐
│ MCP Client │────▶│ DebugMcpServer │────▶│SessionManager│────▶│ AdapterRegistry │
└─────────────┘ └────────────────┘ └──────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────┐ ┌─────────────────┐
│ ProxyManager │◀─────│ Language Adapter│
└──────────────┘ └─────────────────┘
│
┌───────────┬───────────┬───────────┼───────────┬───────────┬───────────┬───────────┬───────────┬───────────┐
│ │ │ │ │ │ │ │ │ │
┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐┌─────▼────┐
│Python ││Ruby ││JavaScript││Rust ││Go ││Java ││.NET ││C/C++ ││COBOL ││Mock │
│Adapter ││Adapter ││Adapter ││Adapter ││Adapter ││Adapter ││Adapter ││Adapter ││Adapter ││Adapter │
└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘
Want to add debugging support for your favorite language? Check out the Adapter Development Guide!
Here's a complete debugging session example:
# buggy_swap.py
def swap_variables(a, b):
a = b # Bug: loses original value of 'a'
b = a # Bug: 'b' gets the new value of 'a'
return a, b
// Tool: create_debug_session
// Request:
{
"language": "python",
"name": "Swap Bug Investigation"
}
// Response:
{
"success": true,
"sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
"message": "Created python debug session: Swap Bug Investigation"
}
// Tool: set_breakpoint
// Request:
{
"sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
"file": "C:\\path\\to\\buggy_swap.py",
"line": 2
}
// Response:
{
"success": true,
"breakpointId": "28e06119-619e-43c0-b029-339cec2615df",
"file": "C:\\path\\to\\buggy_swap.py",
"line": 2,
"verified": false,
"message": "Breakpoint set at C:\\path\\to\\buggy_swap.py:2"
}
// Tool: start_debugging
// Request:
{
"sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
"scriptPath": "C:\\path\\to\\buggy_swap.py"
}
// Response:
{
"success": true,
"state": "paused",
"message": "Debugging started for C:\\path\\to\\buggy_swap.py. Current state: paused",
"data": {
"message": "Debugging started for C:\\path\\to\\buggy_swap.py. Current state: paused",
"reason": "breakpoint"
}
}
First, get the scopes:
// Tool: get_scopes
// Request:
{
"sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
"frameId": 3
}
// Response:
{
"success": true,
"scopes": [
{
"name": "Locals",
"variablesReference": 5,
"expensive": false,
"presentationHint": "locals",
"source": {}
},
{
"name": "Globals",
"variablesReference": 6,
"expensive": false,
"source": {}
}
]
}
Then get the local variables:
// Tool: get_variables
// Request:
{
"sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
"scope": 5
}
// Response:
{
"success": true,
"variables": [
{"name": "a", "value": "10", "type": "int", "variablesReference": 0, "expandable": false},
{"name": "b", "value": "20", "type": "int", "variablesReference": 0, "expandable": false}
],
"count": 2,
"variablesReference": 5
}
rdbg, including remote attachevaluate_expression to catch a race strace couldn't seemcp-debugger doctor, per-language prerequisites, failure signatures, env-var referenceWe welcome contributions! See CONTRIBUTING.md for guidelines.
# Development setup
git clone https://github.com/debugmcp/mcp-debugger.git
cd mcp-debugger
# Install dependencies and vendor debug adapters
pnpm install
# Vendored debug engines (Microsoft's js-debug; CodeLLDB, shared by Rust, C/C++ and COBOL)
# are downloaded automatically and verified against committed SHA-256 digest pins
# Build the project
pnpm build
# Run tests
pnpm test
# Check adapter vendoring status
pnpm vendor:status
# Force re-vendor all adapters (if needed)
pnpm vendor:force
The project automatically vendors debug adapters during pnpm install:
packages/codelldb-common)vendor-manifest.json; mismatches fail the buildSKIP_ADAPTER_VENDOR=true to skip vendoringTo manually manage adapters:
# Check current vendoring status
pnpm vendor:status
# Re-vendor all adapters
pnpm vendor
# Clean and re-vendor (force)
pnpm vendor:force
# Clean vendor directories only
pnpm clean:vendor
We use Act to run GitHub Actions workflows locally:
# Build the Docker image first
docker build -t mcp-debugger:local .
# Run tests with Act (use WSL2 on Windows)
act -j build-and-test --matrix os:ubuntu-latest
See tests/README.md for detailed testing instructions.
{WS-NAME} logpoints)mcp-debugger is stewarded by Sycamore LLC and led by John Franklin (@debugmcpdev). The project uses an agent-first development model with human accountability: AI agents write most of the code; a human maintainer makes every merge, release, and security decision. See MAINTAINERS.md, GOVERNANCE.md, and SUPPORT.md (including commercial support).
Supply-chain posture: pinned CI actions, OIDC trusted publishing, sigstore provenance on every npm package, SBOMs attached to releases, and an OpenSSF Scorecard score we actively maintain — details in SUPPLY-CHAIN-SECURITY.md. Report vulnerabilities via SECURITY.md.
MIT License - see LICENSE for details.
Built with:
Give your AI agents a real debugger — in any language.