Skip to content

Release 0.24.0

Choose a tag to compare

@github-actions github-actions released this 19 Aug 22:18
· 372 commits to main since this release
3c9536d

🎉 Release 0.24.0

[0.24.0] - 2026-08-19

Changed

  • Variable responses are size-guarded — values truncate past 1024 chars, per-call variable count and total response size are capped (all env-tunable), with a truncation object explaining what was cut and pointing at the names: [...] filter or a targeted evaluate_expression; keeps huge scopes from blowing out agent context windows (#356, #359)
  • BREAKING (behavioral): launch sessions now default to breakOnExceptions: "uncaught" — a crashing script pauses at the uncaught exception (lastStop.reason: "exception", stack/locals inspectable, exceptionInfo where supported) instead of running to termination. Applies uniformly to Python, JavaScript, Java, Go (panics), .NET, Rust (panics), and the mock adapter; Ruby keeps the old run-to-termination behavior (rdbg has no uncaught-only filter). Pass breakOnExceptions: "none" to restore the old behavior per session. Attach sessions are unchanged — no default is ever applied on attach (fixes #244)

Added

  • C/C++ debugging support — new @debugmcp/adapter-cpp package driving CodeLLDB with a single cpp language id for C and C++: launch a prebuilt executable, or pass a lone .c/.cpp file and the adapter auto-compiles it (-gdwarf-4 -O0 into .debug-mcp/ — DWARF-4 explicitly, since MinGW's default DWARF-5 line tables are unreadable by LLDB in PE-COFF; forceRebuild: true to override). Attach by PID (attach_to_process {processId}) makes it the first native-code attach adapter. Advanced CodeLLDB config passes through: initCommands, targetCreateCommands (core dumps), processCreateCommands (gdbserver/QEMU/rr remote stubs), sourceMap. MSVC-built binaries are detected with configurable handling (CPP_MSVC_BEHAVIOR=warn|error|continue — PDB fidelity is partial; prefer MinGW-w64/DWARF on Windows). Exceptions map all → cpp_throw (SIGABRT and signals pause natively). CodeLLDB vendoring/resolution/spawn glue is extracted to a shared @debugmcp/codelldb-common package — one ~vendored copy per platform now serves both Rust and C/C++ (#324, #325)

  • get_output tool + per-session output resource — debuggee stdout/stderr is captured into a bounded per-launch ring buffer readable any time (during the run or after exit) via get_output {sessionId, since} with cursor-based pagination (nextSince); each session also exposes the transcript as MCP resource debug://sessions/{id}/output with resources/subscribe support and coalesced update notifications (#218)

  • Per-mode language availability + toolchain-less attach — list_supported_languages now reports modes.launch / modes.attach per language, each with {supported, available, reason}; direct-connect attach modes (debugpy, rdbg) no longer require a local language toolchain (the debug engine runs inside the target), and attach_to_process on adapters with no attach support (rust, go, mock) fails fast with a clear error instead of timing out (#331)

  • Multi-language Docker image — the published image now debugs Python, JavaScript, Java, Rust, and C/C++ natively (shared vendored linux-x64 CodeLLDB via CODELLDB_PATH, plus g++); Ruby ships attach-only (no Ruby runtime in the image); only Go and .NET remain disabled (#328)

  • Kubernetes ephemeral debug sidecar flow — documented, tested recipe for debugging compiled processes in running pods with no in-process debug agent: kubectl debug --target=<container> --profile=general --image=debugmcp/mcp-debugger shares the target's PID namespace (and injects SYS_PTRACE), then attach_to_process {processId: 1, adapterConfig: {program: "/proc/1/root/<binary>"}} attaches CodeLLDB by PID; examples/sick-pod-cpp is the runnable demo (#332)

  • adapterConfig passthrough on attach_to_process / create_debug_session — arbitrary adapter-specific attach/launch keys (e.g. CodeLLDB's program for symbol resolution) flow through to the DAP config, making flows like the k8s sidecar self-contained; reserved keys (request, __attachMode) are stripped with a warning (#336)

  • Launch-time toolchain gate — create_debug_session and start_debugging fail fast with an actionable message when the language's launch toolchain is missing, instead of a silent no-op launch (#360)

  • Anchor matching: distinctive substrings + match-quality reporting — statement:/expectedContent anchors accept a distinctive substring of the line (not just whole-line equality) and tolerate trailing comments; every inexact match is surfaced via matchQuality (exact/substring/comment-stripped) with candidate lists in warnings, so a weak anchor is visible instead of silently trusted (#367, #379)

  • Stop reason persisted on the session — the most recent stop's reason/location survives past the stop event as lastStop, reported by list_debug_sessions and get_stack_trace, so a late-arriving client can tell why the session is paused (#214)

  • Agent skill + in-band guidance — skills/debugging/ ships an installable agent skill (golden path, bisection discipline, attach recipes, per-language references); the server serves condensed MCP instructions on connect and a debugging-workflow prompt (#239)

  • JIT-diagnostics demos — .github/actions/debug-failing-test composite action (auto-debug a failing test in CI and post root-cause analysis), examples/sick-pod (attach to a live Kubernetes service), and the docs/jit-diagnostics/ tutorial (#241)

  • Four more adapter packages published to npm — @debugmcp/adapter-javascript, @debugmcp/adapter-go, @debugmcp/adapter-java, and @debugmcp/adapter-dotnet are now published standalone for programmatic embedding (the CLI bundle continues to include everything); adapter-rust, adapter-cpp, and codelldb-common remain bundle-only (marked private)

  • Startup reaper for orphaned proxy worker chains — proxy workers are tagged at spawn with --mcp-owner-pid / --mcp-session-id argv markers; on startup the server scans for workers whose owner process is dead (server SIGKILLed or hard-crashed — the residual #337 gap) and tears them down: POSIX SIGTERMs the worker so its own shutdown cascades the adapter group/tree kill, with bounded SIGKILL escalation for wedged workers; Windows sweeps the tree directly via taskkill /T /F. Workers owned by live servers (concurrent instances) and untagged pre-upgrade workers are never touched. In Kubernetes shared-PID-namespace sidecars this means a fresh debug sidecar automatically reaps chains a hard-killed predecessor left behind (#343)

  • DAP mirror: read-only IDE attach to agent-owned debug sessions — new expose_session / unexpose_session tools open a per-session DAP endpoint (loopback-only, random per-expose token presented as mirrorToken in the IDE's attach config) hosted in the session's proxy worker, so a human can attach VS Code ("debugServer": <port> + mirrorToken), nvim-dap, or any DAP client to a live session that no IDE launched — CI, containers, terminal-driven runs — and inspect the actual paused state: threads, stacks, scopes, variables, evaluate (incl. exceptionInfo/loadedSources/modules). A late-joining IDE lands directly on the paused frame via a synthesized stopped event from the persisted stop. Execution control stays with the MCP session: continue/step/pause/setVariable and breakpoint changes are rejected (breakpoint config requests soft-succeed as unverified so IDE attach flows survive), and the served capability mask hides control affordances up front. Endpoint closes on unexpose/close/restart/debuggee exit; list_debug_sessions shows exposure: {host, port} (never the token, which is also redacted from logs). The DAP Content-Length codec was extracted into a shared dap-framing module reused by client and mirror (#217)

  • JavaScript function breakpoints via js-debug's CDP proxy — set_breakpoint {function} now works for JavaScript even though upstream js-debug implements no DAP setFunctionBreakpoints (declared out of scope in vscode-js-debug#952): the proxy obtains js-debug's requestCDPProxy WebSocket from the child session and arms V8's Debugger.setBreakpointOnFunctionCall — the same primitive behind Chrome DevTools' debug(fn) — with zero new dependencies (Node ≥22's global WebSocket). Names are dotted runtime paths bound to the current function value, not a source-symbol search: main-module function declarations bind at the (auto-continued) entry pause, functions in lazily-loaded modules stay pending with an explanatory message and bind automatically at the next pause (verification via breakpoint events), and globally reachable names resolve even while running — attach mode works. Conditions evaluate in callee scope with arguments bound; stops report reason: "function breakpoint"; boundFile/boundLine come from [[FunctionLocation]] with scriptParsed/__filename fallbacks; remove/clear/restart_debugging behave like every other adapter. Name resolution is side-effect-free (V8 throwOnSideEffect, retried permissively only on V8's false-positive vetoes such as ESM namespace reads) (#295)

  • Java function breakpoints — the JDI bridge now implements setFunctionBreakpoints natively: set_breakpoint {function} accepts bare method, Class.method, fully-qualified, Outer.Inner.method, and Class.<init> names, binds every concrete overload at its entry location (jdb's stop in technique — full speed, no MethodEntryRequest), defers not-yet-loaded classes via ClassPrepareRequest with verification reported through breakpoint events, honors condition, and stops with reason: "function breakpoint". Bare names skip JDK-internal classes; qualified names can still target them (#292)

  • Function breakpoints: symbol-addressed breakpoints — set_breakpoint accepts function: "name" (with optional condition): break on entry to a symbol via DAP setFunctionBreakpoints, with no file or line at all — names survive edits better than lines or statements, and restart_debugging re-applies them natively. Session-global semantics throughout: list_breakpoints reports them in a separate functionBreakpoints array with the adapter's bound location (boundFile/boundLine), remove_breakpoint accepts function: "name", an unscoped clear_breakpoints removes them while a file-scoped clear does not. Capability-gated per adapter (Python/Go/Rust/.NET/Java/JavaScript supported — JavaScript via the CDP bridge above; Ruby accepted with a warning and re-checked at launch), with the same launch-time capability drift warning as logpoints. The mock adapter simulates binding via a deterministic function→line table for hermetic e2e coverage (#271)

  • statement + matching expectedContent accepted — combining a statement anchor with an expectedContent that trim-matches it is now treated as a redundant-but-valid assertion instead of a hard error; only a different expectedContent (contradictory intent) errors. Controlled trials showed agents combine the two on essentially every content-addressed set, making the old rejection a systematic one-round tax (fixes #280)

  • Statement anchors: content-addressed breakpoints — set_breakpoint accepts statement: "<exact line text>" instead of line: whole-line trimmed-equality matching (the Edit-tool old_string skill agents already practice, instead of line arithmetic they're demonstrably bad at). Ambiguity is an error that lists every line: content match (the error is the disambiguation UI; nearLine binds to the closest match); blank/comment anchors are rejected. The anchor is stored on the breakpoint record and re-resolves on restart_debugging against the current file — breakpoints survive the edit that was the point of the session, with moves reported in data.anchorResolution.moved and no-longer-matching anchors kept at their previous line with a warning (data.anchorResolution.stale) instead of failing the restart. Gated to the content addressing mode (the default) (#271)

  • expectedContent breakpoint assertions + loud snapping — set_breakpoint accepts an optional expectedContent: the exact text you expect on the target line (whitespace-trimmed). On a mismatch the breakpoint is NOT set and the error shows expected vs actual plus the surrounding lines — converting an off-by-one line number from confusing session behavior into an immediate, self-explanatory failure. When an adapter binds a breakpoint to a different line than requested, the response now reports it prominently (requested line N, bound to line M in message/warning, with requestedLine alongside the bound line) instead of silently mutating the line; asynchronous relocations (js-debug-style breakpoint events) surface in list_breakpoints as line ≠ requestedLine. Session-layer live-sync failures now also reach the set_breakpoint response as a warning (previously discarded). Content assertions require a server-readable source file (rejected for Java FQCNs and attach sessions with a clear error), and the source-line cache is now mtime-validated so mid-session edits are seen immediately. The new DEBUG_MCP_BP_ADDRESSING env flag (line | assert | content, default content) restricts addressing features — runtime behavior, tool schema, server instructions, and prompt text all gate together, enabling controlled A/B comparisons of agent debugging behavior (#271)

  • Stop-reason normalization + stopReason in pause results — a new per-adapter normalizeStopReason policy hook maps misleading raw DAP stop reasons to canonical ones before they drive auto-continue, lastStop, and exceptionInfo enrichment: CodeLLDB reports an explicit pause (delivered via SIGSTOP) as "exception", and js-debug reports it as "step" — both now surface as "pause", with the adapter's original value preserved as lastStop.rawReason. Real exceptions (SIGSEGV, panics) are never reclassified, and normalized pauses no longer trigger a spurious exceptionInfo request. pause_execution now reports data.stopReason/data.rawStopReason for fresh stops (stale earlier stops are never echoed)

  • Optimized-binary warning on get_local_variables — when the adapter annotates the locals scope (Delve's "Locals (warning: optimized function)" for optimized frames), the response now reports the actual scope name and a warning field with remediation guidance (rebuild with -gcflags="all=-N -l", or use Delve debug mode). Previously Go's exact-name scope match silently returned [] for optimized frames; the scope is now prefix-matched so available variables are returned. examples/go/README.md no longer suggests buildFlags with mode: "exec" (Delve ignores it there)

  • restart_debugging tool — one call terminates the current debuggee (if any) and relaunches it with the same configuration as the last start_debugging, re-applying every current breakpoint; the edit-rerun loop no longer costs close + create + re-set breakpoints + start. Implemented uniformly as terminate+relaunch (the DAP-spec-blessed emulation — no adapter advertises native restart), so all launch-mode languages work identically; runs while running, paused, or after the program exited. The response's data.outputReset: true signals that each launch starts a fresh output buffer — read get_output from since: 0. Attach sessions and never-launched (or dry-run-only) sessions are refused with clear errors (fixes #238)

  • Logpoints — set_breakpoint accepts an optional logMessage: instead of pausing, the adapter logs the message (expressions in {curly braces} interpolated with live values) as output that lands in get_output and the session output resource while the program runs at full speed — the prod-safe just-in-time diagnostics primitive, combinable with condition. A single shared toSourceBreakpoint mapper now feeds every setBreakpoints construction site (live re-send, launch-time initial breakpoints, js-debug handshake), which also fixes suspendPolicy being silently dropped on the launch path. Support is gated per adapter: Python/JavaScript/Go/Rust/mock work; Java/.NET fail fast with a clear error; unknown support (Ruby) is accepted with a warning and re-checked against the adapter's live capabilities at launch. The mock adapter simulates logpoints (logs without stopping) for hermetic e2e coverage (fixes #235)

  • Breakpoint management tools — new list_breakpoints (per-session listing with verified state and adapter-assigned ids, optional file filter), remove_breakpoint (by breakpoint id, or by file+line which removes every breakpoint at that location), and clear_breakpoints (whole session or one file). Removal and clearing take effect immediately while the debuggee is running or paused (the file's remaining set is re-sent, DAP replace-all) and deliberately keep working after the program exits so breakpoints can be adjusted between launches. DAP breakpoint events — previously dropped — are now wired end-to-end, so deferred verifications (debugpy module load, JDI class load, js-debug async binding, netcoredbg pending breakpoints) update the stored state; pre-launch breakpoints are also re-synced once a launch completes so their verified state and adapter ids reach the store on adapters that don't push events (fixes #236)

  • Break-on-exception support — new breakOnExceptions option ("uncaught" | "all" | "none", default "none") on start_debugging and attach_to_process: an uncaught exception now pauses at the crash site with the stack and locals inspectable instead of terminating the session. The abstract mode is resolved to per-language debugger filter IDs by the adapter policy (Python uncaught/raised+uncaught, JavaScript uncaught/all — runtime-verified against js-debug, Java uncaught/caught+uncaught, .NET user-unhandled/all, Go fatal+panic, Rust rust_panic/+cpp_throw, Ruby all-only via any); an unsupported mode is skipped with a warning and never aborts the launch (fixes #220)

  • Exception detail on stops — lastStop now records the DAP stopped event's description and text (e.g. exception class and message), surfaced via list_debug_sessions, get_stack_trace, and the start_debugging response (#220)

  • Debuggee exit code surfaced — the exit code from the DAP exited event is stored on the session and returned as exitCode in list_debug_sessions, making a crash (non-zero) distinguishable from a clean exit (#220)

  • Adapter capabilities captured per session — the DAP initialize response body is no longer discarded: the worker forwards it to the session (adapterCapabilities), enabling capability-gated behavior and a startup drift warning when a policy's static exception-filter table references filter IDs the live adapter doesn't advertise (fixes #243)

  • exceptionInfo enrichment on exception stops — when a session pauses with reason exception and the adapter supports the DAP exceptionInfo request, lastStop.exceptionInfo is populated best-effort with exceptionId, breakMode, and details (message, type names, adapter-side stack trace); surfaced via list_debug_sessions and get_stack_trace. The request is fire-and-forget after the pause, so the field may appear a moment after the stop; failures are swallowed (#243)

Fixed

  • JavaScript breakpoints no longer flip back to unverified — for js-debug's parent/child session architecture, the child session owns the runtime and is now authoritative for breakpoint verified state: child setBreakpoints responses are forwarded as synthesized breakpoint events (previously their verified state never reached the session store), and the parent session's pessimistic responses/events can no longer downgrade child-verified breakpoints or clobber child adapter ids. Genuine child-side unbinding (id-matched downgrade) still applies

  • Java stacks paused inside the JDK now show your frames — the JDK-internal frame filter matched java.* prefixes against frame names, but the JDI bridge emits bare method names (sleep0), so it never matched; it now also recognizes the declaring-type FQCN that lands in the file slot for no-debug-info frames (prefix list extended with jdk. and com.sun.), with an all-internal fallback so pure-JDK stacks still show frames, and get_local_variables picks the first user frame automatically. The JDI bridge also emits fully qualified frame names (PauseTest.main, java.lang.Thread.sleep0), matching JDWP/IDE conventions

  • get_local_variables on a terminated session explains the program finished and suggests restart_debugging, instead of the generic "must be paused at a breakpoint" message

  • start_debugging / attach_to_process on a session with a live proxy no longer destroys the session — the "already has an active proxy" path called closeSession, which removes the session from the store, so the immediately-following state update threw and the tool reported a bogus "Session not found" with the session gone. Both paths now use a session-preserving teardown (listeners removed, worker stopped, adapter slot released) and the relaunch proceeds normally; per-launch breakpoint state (verified/message/adapter id) is also reset on every new launch so a relaunch reports honest verification (#238)

  • Go exception filters actually arm now — the #220 filter table used shorthand IDs (panic, fatal) that Delve silently accepts and ignores; corrected to Delve's real filter IDs (unrecovered-panic, runtime-fatal-throw), so breakOnExceptions (and the new launch default) genuinely pauses Go panics. Caught live by the #243 capability drift warning during #244 validation (#244)

  • Ruby and Rust-on-Windows debuggee output captured — adapters whose debuggee inherits the adapter process's stdio (rdbg -c on all platforms, CodeLLDB's console mode on Windows) now opt into proxy-side forwarding: the adapter's stdout/stderr lines are synthesized into DAP output events and land in the same per-session buffer get_output reads. rdbg's own DEBUGGER: stderr banners are excluded (they still go to the session log, sanitized, as before); the forwarded copy is raw, matching how debugpy/js-debug output reaches the buffer. Ruby attach mode is unchanged — no adapter process exists there, so output stays on the target's own terminal (fixes #222, fixes #223)

  • Go debuggee output captured — the Go adapter now launches Delve with outputMode: 'remote', so the target program's stdout/stderr arrives as DAP output events and shows up in get_output instead of vanishing into dlv's own stdio (fixes #225)

  • Rust launch config uses CodeLLDB's canonical terminal attribute — the adapter emitted a debugpy-style console key that CodeLLDB only honors as a legacy alias; it now emits terminal: 'console', translating any user-supplied legacy console values (#223 — the Windows output-capture gap the issue uncovered is tracked separately: LLDB's console mode inherits the debuggee's stdio rather than emitting DAP output events)

  • js-debug launch no longer hangs on fast-exiting scripts — the launch barrier now settles when the debuggee emits terminated/exited during the launch window, and dispose() rejects a still-pending wait as a structural backstop; start_debugging for a JavaScript script that crashes (or completes) within seconds of launch now returns promptly with state stopped instead of hanging past the MCP client timeout. Also removes an intermittent ~10s stall when js-debug's initialized event raced the handshake listener (fixes #242)

  • Mock adapter now answers setExceptionBreakpoints (previously an unhandled-command error) and emits exited before terminated, matching real adapter ordering (#220)

  • Corrected the JavaScript adapter's declared exceptionBreakpointFilters to the IDs js-debug actually reports (all, uncaught) (#220)

  • Published adapter packages are installable standalone — npm publish from the pnpm workspace shipped literal workspace:* dependency ranges that npm cannot install (EUNSUPPORTEDPROTOCOL); the release pipeline now resolves them to pinned concrete versions at publish time

  • No more flashing console windows on Windows — a 30-site windowsHide sweep across every spawn path; user-requested console modes are still honored, and Python launches run under pythonw.exe where appropriate (#215)

  • Session-lifecycle failures return structured success: false with the session's actual state across all session-scoped tools, instead of protocol-level errors (#203)

  • JavaScript debuggee exit code reported — js-debug never emits a DAP exited event; a preload shim now captures and reports the real exit code (#247)

  • npx bundle completeness — the published CLI bundle now resolves its vendored js-debug (JavaScript sessions previously reported unavailable / silently no-opped), and ships the Java JDI bridge source and the JS exit-code shim (#354, #364)

  • Ruby: mid-run stdout streaming via an injected sync prelude (output used to arrive only at exit), launchConfig.env and launchConfig.cwd now reach the debuggee spawn (rdbg -c starts the target at spawn time, so DAP-launch fields were dead letters), and launch sessions ending in a crash now finish stopped with a synthesized exitCode instead of error (terminal-signal FIFO ordering) (#317, #318, #320, #258)

  • Attach lifecycle hardening — attach failure/teardown now kills the full adapter chain including lldb-server (no more orphans), CLI exit paths are bounded and always stop the server, and crash-abandoned HTTP MCP sessions are reaped on a 60s sweep (MCP_HTTP_STALE_SESSION_MS, default 30 min) — an HTTP client crash could previously leave an immortal session holding its debuggee (#337)

  • Attach verification surfaces real adapter errors (bad PID, missing binary, ptrace denial) instead of a generic verify-timeout (#371)

  • .NET attach pauses the target — netcoredbg does not suspend on attach; the adapter now issues the pause so attach lands inspectable, matching every other adapter (#353); Java attach pause similarly picks a reportable thread (#352)

  • Java: launch sessions report exitCode (#368) and redefine_classes re-plants breakpoints in redefined classes — JDWP invalidates them on hot-swap; they are re-created against the new class version (#370)

  • Stack traces never come back empty — frame-classification fallbacks guarantee at least the top frame with a hiddenFrames annotation (#346); LLDB/libc internal frames in Rust/C++ stacks are classified and filtered consistently (#369)

  • Output pipeline correctness — per-launch output-buffer isolation after restart_debugging (no cross-launch sequence bleed) (#358); LLDB DWARF-warning noise filtered from captured output via a policy hook (#361); child-session output events flushed at run-to-completion so fast Docker JS runs don't lose output (#366); non-child adapters no longer pay a 300–450 ms child-event settle at teardown (#378)

  • Host-built Rust/C++ binaries debugged in the container get a derived source map — DWARF compile dirs are read from the binary and mapped to /workspace automatically (#363)

  • mcp_debugger_launcher (PyPI) command construction unified — dry-run output and the executed npx/docker command are now generated from the same source of truth (#345)

Security

  • Secret redaction on by default — 17 credential-shape rules (gitleaks-derived: PATs, cloud keys, JWTs, private key blocks, …) plus a sensitive-variable-name set mask values as labeled placeholders (<redacted:github-pat>) across get_variables, get_local_variables, child expansion, evaluate_expression, and captured output before they reach the MCP client; the env sanitizer shares the same rule table, closing a raw-DAP-body log leak. Opt out per server with DEBUG_MCP_NO_REDACT=1. pwd was later dropped from the name set (too many false positives on working-directory variables) (#237, #315, #365)
  • Least-privilege variable access mode — DEBUG_MCP_VARIABLE_ACCESS=explicit makes get_variables require explicit names: [...] instead of dumping whole scopes; the names filter also works in open mode (misses reported via notFound) (#316)
  • Vendored debug engines are digest-pinned — js-debug (previously vendored from the floating latest release) is pinned to v1.112.0 and CodeLLDB to 1.11.8 via committed vendor-manifest.json files; both vendor scripts verify every downloaded artifact against the pinned SHA-256s and fail closed, since GitHub release assets are mutable ("same tag" ≠ "same bytes")
  • npm OIDC trusted publishing — previously published @debugmcp/* packages now publish via npm trusted publishing (short-lived OIDC credentials bound to the release workflow; no long-lived token), with sigstore provenance on every package; first-ever publishes use a scoped token once, then migrate
  • Ownership + SBOMs — Sycamore LLC named as the accountable steward (MAINTAINERS/GOVERNANCE/SUPPORT.md); SPDX + CycloneDX SBOMs attached to every GitHub release; project contacts moved to security@debugmcp.io / admin@debugmcp.io; a security assurance case documents threats → controls → residual risks (#240)

📦 Installation

Docker:

docker pull debugmcp/mcp-debugger:0.24.0

npm (global install):

npm install -g @debugmcp/mcp-debugger@0.24.0

npx (no install):

npx @debugmcp/mcp-debugger@0.24.0 stdio

PyPI:

pip install debug-mcp-server-launcher==0.24.0

Optional adapters (for programmatic embedding; the CLI above bundles all of them):

npm install @debugmcp/adapter-python   # or: adapter-ruby, adapter-javascript,
                                       # adapter-go, adapter-java, adapter-dotnet,
                                       # adapter-mock

🔏 Verify this release

gh attestation verify <asset>.tgz --repo debugmcp/mcp-debugger
npm audit signatures   # in a project that installs @debugmcp packages

SBOMs (SPDX + CycloneDX) are attached as release assets.

📚 Documentation

See the README for usage instructions.