Repository navigation
Release 0.24.0
🎉 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
truncationobject explaining what was cut and pointing at thenames: [...]filter or a targetedevaluate_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,exceptionInfowhere 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). PassbreakOnExceptions: "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-cpppackage driving CodeLLDB with a singlecpplanguage id for C and C++: launch a prebuilt executable, or pass a lone.c/.cppfile and the adapter auto-compiles it (-gdwarf-4 -O0into.debug-mcp/— DWARF-4 explicitly, since MinGW's default DWARF-5 line tables are unreadable by LLDB in PE-COFF;forceRebuild: trueto 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 mapall → cpp_throw(SIGABRT and signals pause natively). CodeLLDB vendoring/resolution/spawn glue is extracted to a shared@debugmcp/codelldb-commonpackage — one ~vendored copy per platform now serves both Rust and C/C++ (#324, #325) -
get_outputtool + 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) viaget_output {sessionId, since}with cursor-based pagination (nextSince); each session also exposes the transcript as MCP resourcedebug://sessions/{id}/outputwithresources/subscribesupport and coalesced update notifications (#218) -
Per-mode language availability + toolchain-less attach —
list_supported_languagesnow reportsmodes.launch/modes.attachper 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), andattach_to_processon 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, plusg++); 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-debuggershares the target's PID namespace (and injectsSYS_PTRACE), thenattach_to_process {processId: 1, adapterConfig: {program: "/proc/1/root/<binary>"}}attaches CodeLLDB by PID;examples/sick-pod-cppis the runnable demo (#332) -
adapterConfigpassthrough onattach_to_process/create_debug_session— arbitrary adapter-specific attach/launch keys (e.g. CodeLLDB'sprogramfor 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_sessionandstart_debuggingfail 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:/expectedContentanchors accept a distinctive substring of the line (not just whole-line equality) and tolerate trailing comments; every inexact match is surfaced viamatchQuality(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 bylist_debug_sessionsandget_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 MCPinstructionson connect and adebugging-workflowprompt (#239) -
JIT-diagnostics demos —
.github/actions/debug-failing-testcomposite action (auto-debug a failing test in CI and post root-cause analysis),examples/sick-pod(attach to a live Kubernetes service), and thedocs/jit-diagnostics/tutorial (#241) -
Four more adapter packages published to npm —
@debugmcp/adapter-javascript,@debugmcp/adapter-go,@debugmcp/adapter-java, and@debugmcp/adapter-dotnetare now published standalone for programmatic embedding (the CLI bundle continues to include everything);adapter-rust,adapter-cpp, andcodelldb-commonremain bundle-only (marked private) -
Startup reaper for orphaned proxy worker chains — proxy workers are tagged at spawn with
--mcp-owner-pid/--mcp-session-idargv 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 viataskkill /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_sessiontools open a per-session DAP endpoint (loopback-only, random per-expose token presented asmirrorTokenin 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 synthesizedstoppedevent 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_sessionsshowsexposure: {host, port}(never the token, which is also redacted from logs). The DAP Content-Length codec was extracted into a shareddap-framingmodule 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 DAPsetFunctionBreakpoints(declared out of scope in vscode-js-debug#952): the proxy obtains js-debug'srequestCDPProxyWebSocket from the child session and arms V8'sDebugger.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-modulefunctiondeclarations 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 reportreason: "function breakpoint";boundFile/boundLinecome from[[FunctionLocation]]with scriptParsed/__filenamefallbacks; remove/clear/restart_debuggingbehave like every other adapter. Name resolution is side-effect-free (V8throwOnSideEffect, retried permissively only on V8's false-positive vetoes such as ESM namespace reads) (#295) -
Java function breakpoints — the JDI bridge now implements
setFunctionBreakpointsnatively:set_breakpoint {function}accepts baremethod,Class.method, fully-qualified,Outer.Inner.method, andClass.<init>names, binds every concrete overload at its entry location (jdb'sstop intechnique — full speed, noMethodEntryRequest), defers not-yet-loaded classes viaClassPrepareRequestwith verification reported through breakpoint events, honorscondition, and stops withreason: "function breakpoint". Bare names skip JDK-internal classes; qualified names can still target them (#292) -
Function breakpoints: symbol-addressed breakpoints —
set_breakpointacceptsfunction: "name"(with optionalcondition): break on entry to a symbol via DAPsetFunctionBreakpoints, with no file or line at all — names survive edits better than lines or statements, andrestart_debuggingre-applies them natively. Session-global semantics throughout:list_breakpointsreports them in a separatefunctionBreakpointsarray with the adapter's bound location (boundFile/boundLine),remove_breakpointacceptsfunction: "name", an unscopedclear_breakpointsremoves 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+ matchingexpectedContentaccepted — combining a statement anchor with anexpectedContentthat trim-matches it is now treated as a redundant-but-valid assertion instead of a hard error; only a differentexpectedContent(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_breakpointacceptsstatement: "<exact line text>"instead ofline: whole-line trimmed-equality matching (the Edit-toolold_stringskill agents already practice, instead of line arithmetic they're demonstrably bad at). Ambiguity is an error that lists everyline: contentmatch (the error is the disambiguation UI;nearLinebinds to the closest match); blank/comment anchors are rejected. The anchor is stored on the breakpoint record and re-resolves onrestart_debuggingagainst the current file — breakpoints survive the edit that was the point of the session, with moves reported indata.anchorResolution.movedand no-longer-matching anchors kept at their previous line with a warning (data.anchorResolution.stale) instead of failing the restart. Gated to thecontentaddressing mode (the default) (#271) -
expectedContentbreakpoint assertions + loud snapping —set_breakpointaccepts an optionalexpectedContent: 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 Minmessage/warning, withrequestedLinealongside the boundline) instead of silently mutating the line; asynchronous relocations (js-debug-style breakpoint events) surface inlist_breakpointsasline≠requestedLine. Session-layer live-sync failures now also reach theset_breakpointresponse as awarning(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 newDEBUG_MCP_BP_ADDRESSINGenv flag (line|assert|content, defaultcontent) 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 +
stopReasonin pause results — a new per-adapternormalizeStopReasonpolicy hook maps misleading raw DAP stop reasons to canonical ones before they drive auto-continue,lastStop, andexceptionInfoenrichment: 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 aslastStop.rawReason. Real exceptions (SIGSEGV, panics) are never reclassified, and normalized pauses no longer trigger a spuriousexceptionInforequest.pause_executionnow reportsdata.stopReason/data.rawStopReasonfor 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 awarningfield 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.mdno longer suggestsbuildFlagswithmode: "exec"(Delve ignores it there) -
restart_debuggingtool — one call terminates the current debuggee (if any) and relaunches it with the same configuration as the laststart_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'sdata.outputReset: truesignals that each launch starts a fresh output buffer — readget_outputfromsince: 0. Attach sessions and never-launched (or dry-run-only) sessions are refused with clear errors (fixes #238) -
Logpoints —
set_breakpointaccepts an optionallogMessage: instead of pausing, the adapter logs the message (expressions in{curly braces}interpolated with live values) as output that lands inget_outputand the session output resource while the program runs at full speed — the prod-safe just-in-time diagnostics primitive, combinable withcondition. A single sharedtoSourceBreakpointmapper now feeds every setBreakpoints construction site (live re-send, launch-time initial breakpoints, js-debug handshake), which also fixessuspendPolicybeing 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), andclear_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. DAPbreakpointevents — 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
breakOnExceptionsoption ("uncaught"|"all"|"none", default"none") onstart_debuggingandattach_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 (Pythonuncaught/raised+uncaught, JavaScriptuncaught/all— runtime-verified against js-debug, Javauncaught/caught+uncaught, .NETuser-unhandled/all, Gofatal+panic, Rustrust_panic/+cpp_throw, Rubyall-only viaany); an unsupported mode is skipped with a warning and never aborts the launch (fixes #220) -
Exception detail on stops —
lastStopnow records the DAP stopped event'sdescriptionandtext(e.g. exception class and message), surfaced vialist_debug_sessions,get_stack_trace, and thestart_debuggingresponse (#220) -
Debuggee exit code surfaced — the exit code from the DAP
exitedevent is stored on the session and returned asexitCodeinlist_debug_sessions, making a crash (non-zero) distinguishable from a clean exit (#220) -
Adapter capabilities captured per session — the DAP
initializeresponse 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) -
exceptionInfoenrichment on exception stops — when a session pauses with reasonexceptionand the adapter supports the DAPexceptionInforequest,lastStop.exceptionInfois populated best-effort withexceptionId,breakMode, and details (message, type names, adapter-side stack trace); surfaced vialist_debug_sessionsandget_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
setBreakpointsresponses 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 thefileslot for no-debug-info frames (prefix list extended withjdk.andcom.sun.), with an all-internal fallback so pure-JDK stacks still show frames, andget_local_variablespicks 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_variableson a terminated session explains the program finished and suggestsrestart_debugging, instead of the generic "must be paused at a breakpoint" message -
start_debugging/attach_to_processon a session with a live proxy no longer destroys the session — the "already has an active proxy" path calledcloseSession, 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), sobreakOnExceptions(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
-con all platforms, CodeLLDB's console mode on Windows) now opt into proxy-side forwarding: the adapter's stdout/stderr lines are synthesized into DAPoutputevents and land in the same per-session bufferget_outputreads. rdbg's ownDEBUGGER: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 inget_outputinstead of vanishing into dlv's own stdio (fixes #225) -
Rust launch config uses CodeLLDB's canonical
terminalattribute — the adapter emitted a debugpy-styleconsolekey that CodeLLDB only honors as a legacy alias; it now emitsterminal: 'console', translating any user-supplied legacyconsolevalues (#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/exitedduring the launch window, anddispose()rejects a still-pending wait as a structural backstop;start_debuggingfor a JavaScript script that crashes (or completes) within seconds of launch now returns promptly with statestoppedinstead of hanging past the MCP client timeout. Also removes an intermittent ~10s stall when js-debug'sinitializedevent raced the handshake listener (fixes #242) -
Mock adapter now answers
setExceptionBreakpoints(previously an unhandled-command error) and emitsexitedbeforeterminated, matching real adapter ordering (#220) -
Corrected the JavaScript adapter's declared
exceptionBreakpointFiltersto the IDs js-debug actually reports (all,uncaught) (#220) -
Published adapter packages are installable standalone —
npm publishfrom the pnpm workspace shipped literalworkspace:*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
windowsHidesweep across every spawn path; user-requestedconsolemodes are still honored, and Python launches run underpythonw.exewhere appropriate (#215) -
Session-lifecycle failures return structured
success: falsewith 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
exitedevent; 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.envandlaunchConfig.cwdnow reach the debuggee spawn (rdbg-cstarts the target at spawn time, so DAP-launch fields were dead letters), and launch sessions ending in a crash now finishstoppedwith a synthesizedexitCodeinstead oferror(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) andredefine_classesre-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
hiddenFramesannotation (#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
/workspaceautomatically (#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>) acrossget_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 withDEBUG_MCP_NO_REDACT=1.pwdwas 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=explicitmakesget_variablesrequire explicitnames: [...]instead of dumping whole scopes; thenamesfilter also works in open mode (misses reported vianotFound) (#316) - Vendored debug engines are digest-pinned — js-debug (previously vendored from the floating
latestrelease) is pinned to v1.112.0 and CodeLLDB to 1.11.8 via committedvendor-manifest.jsonfiles; 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.0npm (global install):
npm install -g @debugmcp/mcp-debugger@0.24.0npx (no install):
npx @debugmcp/mcp-debugger@0.24.0 stdioPyPI:
pip install debug-mcp-server-launcher==0.24.0Optional 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 packagesSBOMs (SPDX + CycloneDX) are attached as release assets.
📚 Documentation
See the README for usage instructions.