Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ jobs:
node -e 'console.log("ADAPTER_JAVA_VERSION="+require("./packages/adapter-java/package.json").version)' >> $GITHUB_ENV
node -e 'console.log("ADAPTER_DOTNET_VERSION="+require("./packages/adapter-dotnet/package.json").version)' >> $GITHUB_ENV
node -e 'console.log("CLI_VERSION="+require("./packages/mcp-debugger/package.json").version)' >> $GITHUB_ENV
# CodeLLDB platform packages are versioned by the vendored CodeLLDB release (issue #383)
node -e 'console.log("CODELLDB_PKG_VERSION="+require("./packages/codelldb-common/vendor-manifest.json").codelldb.version)' >> $GITHUB_ENV
- name: Set npm dist-tag
run: |
if [[ "${CLI_VERSION}" == *"-beta"* ]] || [[ "${CLI_VERSION}" == *"-alpha"* ]]; then
Expand All @@ -317,6 +319,17 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Downloads the digest-pinned VSIXs for all five platforms (the build above
# vendored linux-x64 only under CI=true) and copies the payloads into the
# @debugmcp/codelldb-* platform packages. Verification runs in a SEPARATE
# process: a vendoring process that died silently (issue #389) cannot
# vouch for itself, and --verify-only fails the job if any package would
# pack without its binaries (issue #383).
- name: Stage CodeLLDB platform packages
run: |
node scripts/stage-codelldb-packages.mjs
node scripts/stage-codelldb-packages.mjs --verify-only

# npm (unlike pnpm) does not rewrite workspace:* at publish time; without
# this step the published adapter packages carry an uninstallable
# "workspace:*" dependency on @debugmcp/shared (EUNSUPPORTEDPROTOCOL).
Expand All @@ -335,6 +348,46 @@ jobs:
npm pack --dry-run -w @debugmcp/adapter-java
npm pack --dry-run -w @debugmcp/adapter-dotnet
npm pack --dry-run -w @debugmcp/mcp-debugger
npm pack --dry-run -w @debugmcp/codelldb-win32-x64
npm pack --dry-run -w @debugmcp/codelldb-darwin-x64
npm pack --dry-run -w @debugmcp/codelldb-darwin-arm64
npm pack --dry-run -w @debugmcp/codelldb-linux-x64
npm pack --dry-run -w @debugmcp/codelldb-linux-arm64

# CodeLLDB platform packages (issue #383). Published BEFORE the CLI package
# so its optionalDependencies always resolve on the registry. Versioned by
# the CodeLLDB release and tagged latest explicitly (they are shared across
# beta/latest channels), so re-releases at an unchanged pin are skipped by
# the npm-view guards. First publish must use the token flow; once the five
# exist, configure trusted publishers and move them into the OIDC step.
- name: Publish CodeLLDB platform packages to npm (token, first publish)
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
# trap (not a trailing rm) so the token file cannot survive a
# mid-loop publish failure on the runner.
trap 'rm -f "$HOME/.npmrc"' EXIT
echo "//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}" > "$HOME/.npmrc"

# "already exists" is the NORMAL path here (every re-release at an
# unchanged CodeLLDB pin walks it), so the guard must distinguish a
# true 404 from a transient registry error - publishing over an
# existing version would otherwise kill the job before the OIDC step.
for pkg in codelldb-win32-x64 codelldb-darwin-x64 codelldb-darwin-arm64 codelldb-linux-x64 codelldb-linux-arm64; do
set +e
VIEW_OUT=$(npm view @debugmcp/${pkg}@${CODELLDB_PKG_VERSION} version 2>&1)
VIEW_CODE=$?
set -e
if [ "$VIEW_CODE" -eq 0 ]; then
echo "@debugmcp/${pkg}@${CODELLDB_PKG_VERSION} already exists, skipping"
elif echo "$VIEW_OUT" | grep -q "E404"; then
npm publish -w @debugmcp/${pkg} --access public --provenance --tag latest
else
echo "npm view for @debugmcp/${pkg}@${CODELLDB_PKG_VERSION} failed with a non-404 error; refusing to guess:"
echo "$VIEW_OUT"
exit 1
fi
done

# Existing packages publish via OIDC trusted publishing: no token anywhere,
# npm mints a short-lived credential from the workflow's OIDC identity and
Expand Down Expand Up @@ -423,6 +476,11 @@ jobs:
npm pack -w @debugmcp/adapter-java --pack-destination release-artifacts
npm pack -w @debugmcp/adapter-dotnet --pack-destination release-artifacts
npm pack -w @debugmcp/mcp-debugger --pack-destination release-artifacts
npm pack -w @debugmcp/codelldb-win32-x64 --pack-destination release-artifacts
npm pack -w @debugmcp/codelldb-darwin-x64 --pack-destination release-artifacts
npm pack -w @debugmcp/codelldb-darwin-arm64 --pack-destination release-artifacts
npm pack -w @debugmcp/codelldb-linux-x64 --pack-destination release-artifacts
npm pack -w @debugmcp/codelldb-linux-arm64 --pack-destination release-artifacts

- name: Upload release artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- **CodeLLDB ships as per-platform npm packages (esbuild pattern)** — five new packages `@debugmcp/codelldb-{win32-x64,darwin-x64,darwin-arm64,linux-x64,linux-arm64}` (versioned by the CodeLLDB release, currently 1.11.8, payload staged from the digest-pinned VSIXs) are `optionalDependencies` of `@debugmcp/mcp-debugger`, so npm installs exactly the one matching your os/cpu. Rust and C/C++ debugging now work out of the box on every platform npm serves — previously the CLI tarball bundled linux-x64 only — and the core tarball shrinks from ~54 MB to a few MB. The resolver probes the installed platform package last — after the vendor tree and after `CODELLDB_PATH` — so an explicit `CODELLDB_PATH` still overrides the auto-installed package, and installs with `--omit=optional` keep working via `CODELLDB_PATH` (#383)

### Fixed
- **vendor-codelldb.js can no longer die silently with exit 0** — the script-level root cause behind #389 (the Docker workaround shipped in v0.24.2 stands): a stalled extract-zip promise drained the event loop and Node exited 0 with no failure output. Extraction now runs under a watchdog (default 120 s, `CODELLDB_EXTRACT_TIMEOUT_MS`) whose pending timer keeps the event loop alive and converts a stall into a normal retry/failure, and a premature-exit guard forces exit code 1 with a requested/completed/unresolved-platforms diagnostic if the process would otherwise exit 0 before vendoring finished (#389)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ The server also serves condensed guidance in-band: MCP `instructions` on connect

> **Requirements:** Node.js 22+ for the server. Each language you debug also needs its own toolchain installed (Python + debugpy, Ruby + the `debug` gem / `rdbg`, Node.js, Go + Delve, JDK 21+, .NET SDK, the Rust toolchain, or a C/C++ compiler — g++/clang++, only needed for source-file launch).
>
> **CodeLLDB platform note (npx/npm installs):** the npm package bundles the CodeLLDB debug engine for **linux-x64 only**, so Rust and C/C++ debugging work out of the box on Linux (CI, containers, cloud sandboxes). On Windows/macOS set `CODELLDB_PATH` to a [CodeLLDB release](https://github.com/vadimcn/codelldb/releases) binary, build from source (vendors your platform automatically), or use the Docker image.
> **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`, set `CODELLDB_PATH` to a [CodeLLDB release](https://github.com/vadimcn/codelldb/releases) binary instead, or use the Docker image.

### For MCP Clients (Claude Desktop, etc.)

Expand Down
2 changes: 1 addition & 1 deletion SUPPLY-CHAIN-SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Two upstream debug engines are vendored (as prebuilt artifacts) into distributed
| Component | Upstream | License | Pin manifest | Embedded in |
|-----------|----------|---------|--------------|-------------|
| js-debug (VS Code JavaScript debugger, DAP server build) | [microsoft/vscode-js-debug](https://github.com/microsoft/vscode-js-debug) | MIT | [`packages/adapter-javascript/vendor-manifest.json`](packages/adapter-javascript/vendor-manifest.json) | `@debugmcp/adapter-javascript`, `@debugmcp/mcp-debugger` CLI bundle, Docker image |
| CodeLLDB (LLDB-based DAP adapter) | [vadimcn/codelldb](https://github.com/vadimcn/codelldb) | MIT | [`packages/codelldb-common/vendor-manifest.json`](packages/codelldb-common/vendor-manifest.json) | `@debugmcp/mcp-debugger` CLI bundle (linux-x64), Docker image |
| CodeLLDB (LLDB-based DAP adapter) | [vadimcn/codelldb](https://github.com/vadimcn/codelldb) | MIT | [`packages/codelldb-common/vendor-manifest.json`](packages/codelldb-common/vendor-manifest.json) | `@debugmcp/codelldb-{win32-x64,darwin-x64,darwin-arm64,linux-x64,linux-arm64}` platform packages (optionalDependencies of `@debugmcp/mcp-debugger`, versioned by the CodeLLDB release, payload staged from the digest-pinned VSIXs by `scripts/stage-codelldb-packages.mjs`), Docker image |

The manifests pin the upstream version, the SHA-256 of each release asset, and (for js-debug) the digest of the derived server file. Overriding the pinned version requires an explicit `*_ALLOW_UNPINNED=true` escape hatch intended for local experiments only; release builds always verify against the committed digests. Version bumps are deliberate PRs that update the manifest (the bump procedure is documented inside each manifest file).

Expand Down
2 changes: 1 addition & 1 deletion docs/cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ MCP Client → mcp-debugger → proxy worker → CodeLLDB (vendored) → LLDB

- CodeLLDB binaries are vendored in `packages/codelldb-common/vendor/codelldb/<platform>/` (shared with the Rust adapter — one ~150 MB copy per platform, downloaded automatically during `pnpm install`).
- The adapter spawns CodeLLDB in TCP mode and speaks DAP to it. No system LLDB or gdb installation is required.
- `CODELLDB_PATH` env var overrides the vendored binary (e.g. npm users on macOS/Windows pointing at the VSCode extension's copy).
- npm/npx installs get CodeLLDB via the per-platform `@debugmcp/codelldb-*` optional dependencies; setting `CODELLDB_PATH` (e.g. to the VSCode extension's copy) overrides the installed platform package, though a repo/Docker vendored copy still wins over both.

## Prerequisites

Expand Down
5 changes: 3 additions & 2 deletions docs/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Pre-release validation for mcp-debugger. Run `npm run release:dry-run` to automa
## Before Tagging

### Automated (via `npm run release:dry-run`)
- [ ] Package versions match (the dry-run script checks root plus **all 12** workspace packages, including the private/bundle-only `adapter-rust`, `adapter-cpp`, and `codelldb-common`)
- [ ] Package versions match (the dry-run script checks root plus **all 17** workspace packages, including the private/bundle-only `adapter-rust`, `adapter-cpp`, and `codelldb-common`; the five `codelldb-<platform>` payload packages are checked against the **CodeLLDB pin**, not the repo version)
- [ ] `CHANGELOG.md` has `[x.y.z] - YYYY-MM-DD` entry with date
- [ ] `CHANGELOG.md` has empty `[Unreleased]` section at top
- [ ] `npm run build` succeeds
Expand All @@ -18,13 +18,14 @@ Pre-release validation for mcp-debugger. Run `npm run release:dry-run` to automa

### Manual
- [ ] **npm trusted publishing configured** — every *previously published* `@debugmcp/*` package must have a trusted publisher at npmjs.com → package Settings → Trusted Publisher (GitHub Actions; org/user: `debugmcp`, repo: `mcp-debugger`, workflow: `release.yml`, environment: blank). These packages publish token-free via OIDC; a publish without this config fails (404/permission error) — configure, then re-run via workflow_dispatch.
- [ ] **First-time packages** — any package that has never been on npm publishes via the `NPM_TOKEN` step in `release.yml` this once. After the release: configure its trusted publisher, then move it from the token step into the OIDC step. When no first-publishes remain, delete the token step and the `NPM_TOKEN` secret.
- [ ] **First-time packages** — any package that has never been on npm publishes via the `NPM_TOKEN` step in `release.yml` this once. After the release: configure its trusted publisher, then move it from the token step into the OIDC step. When no first-publishes remain, delete the token step and the `NPM_TOKEN` secret. (The five `@debugmcp/codelldb-<platform>` packages have their own token step and follow the same dance after their first release.)
- [ ] **Docker Hub credentials** — `DOCKER_USERNAME` and `DOCKER_PASSWORD` secrets are current
- [ ] **PyPI token** — `PYPI_TOKEN` secret is current
- [ ] `release.yml` default ref updated to current tag (for workflow_dispatch reruns)
- [ ] All new adapters have their toolchain in `release.yml` **both** `build-and-test` and `npm-publish` jobs
- [ ] New adapters intended for npm publishing have `publishConfig.access: "public"`, a `git+https` `repository.url` with `directory`, and appear in: `release.yml` (pack dry-run, publish, pack-artifacts) and `PUBLISHED_PKGS` in `scripts/release-dry-run.sh`. Bundle-only packages carry `"private": true`.
- [ ] Vendored-engine pins current: `packages/adapter-javascript/vendor-manifest.json` and `packages/codelldb-common/vendor-manifest.json` match the versions you intend to ship (digest verification fails the build on drift)
- [ ] **CodeLLDB bump procedure** (when bumping the CodeLLDB pin): update `vendor-manifest.json` (version + all five VSIX digests), update `DEFAULT_CODELLDB_VERSION` in `packages/codelldb-common/src/codelldb-resolver.ts`, run `node scripts/sync-versions.cjs` (it writes the pin into the five `packages/codelldb-<platform>/package.json` versions automatically), re-vendor, and run the rust + cpp + codelldb-common test suites (drift guards enforce manifest ↔ resolver ↔ package versions stay in sync). The next release then republishes exactly the five platform packages; at an unchanged pin the npm-view guards skip them.
- [ ] Contributors credited in CHANGELOG (check `git log --format="%an" | sort -u`)

## Common Failures
Expand Down
2 changes: 1 addition & 1 deletion docs/rust-debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ npm run build:adapter # Downloads and extracts CodeLLDB

## CodeLLDB Vendoring

The Rust adapter bundles the CodeLLDB binaries into `packages/codelldb-common/vendor/codelldb`. Vendoring runs automatically when you install or build the workspace. To keep the published npm package within registry limits, the pre-built CLI ships only the Linux x64 CodeLLDB runtime. If you are on macOS or Windows, set the `CODELLDB_PATH` environment variable to your local CodeLLDB installation (for example from the VSCode extension) or run `pnpm --filter @debugmcp/codelldb-common run build:adapter` from a cloned repository to download your platform binaries.
The Rust adapter bundles the CodeLLDB binaries into `packages/codelldb-common/vendor/codelldb`. Vendoring runs automatically when you install or build the workspace. The published CLI installs CodeLLDB via per-platform `@debugmcp/codelldb-*` optional dependencies — npm picks the one matching your os/cpu, so no manual setup is needed. If you installed with `--omit=optional`, set the `CODELLDB_PATH` environment variable to a local CodeLLDB installation (for example from the VSCode extension) or run `pnpm --filter @debugmcp/codelldb-common run build:adapter` from a cloned repository to download your platform binaries.

- `pnpm install` (postinstall hook)
- `pnpm vendor` or `pnpm vendor:adapters`
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-cpp/src/cpp-adapter-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class CppAdapterFactory implements IAdapterFactory {
// Check CodeLLDB — the only hard requirement
const resolvedCodelldb = await resolveCodeLLDBExecutable();
if (!resolvedCodelldb) {
errors.push('CodeLLDB not found. Run: npm run build:adapter');
errors.push('CodeLLDB not found. It normally ships via the @debugmcp/codelldb-* optional dependencies; set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter');
} else {
codelldbPath = resolvedCodelldb;
codelldbVersion = await getCodeLLDBVersion() || undefined;
Expand Down
6 changes: 3 additions & 3 deletions packages/adapter-cpp/src/cpp-debug-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export class CppDebugAdapter extends EventEmitter implements IDebugAdapter {
if (!codelldbPath) {
errors.push({
code: 'CODELLDB_NOT_FOUND',
message: 'CodeLLDB executable not found. Run: npm run build:adapter',
message: 'CodeLLDB executable not found. It normally ships via the @debugmcp/codelldb-* optional dependencies (reinstall without --omit=optional), or set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter',
recoverable: true
});
}
Expand Down Expand Up @@ -439,7 +439,7 @@ export class CppDebugAdapter extends EventEmitter implements IDebugAdapter {

if (!resolvedPath) {
throw new AdapterError(
'CodeLLDB executable not found. Run: npm run build:adapter',
'CodeLLDB executable not found. It normally ships via the @debugmcp/codelldb-* optional dependencies (reinstall without --omit=optional), or set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter',
AdapterErrorCode.ENVIRONMENT_INVALID
);
}
Expand Down Expand Up @@ -788,7 +788,7 @@ Install:
const message = error.message.toLowerCase();

if (message.includes('codelldb') && message.includes('not found')) {
return 'CodeLLDB is not installed. Please run: npm run build:adapter';
return 'CodeLLDB is not installed. It normally ships via the @debugmcp/codelldb-* optional dependencies; set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter';
}

if (message.includes('compiler') && message.includes('not found')) {
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-rust/src/rust-adapter-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class RustAdapterFactory implements IAdapterFactory {
// Check CodeLLDB
const resolvedCodelldb = await resolveCodeLLDBExecutable();
if (!resolvedCodelldb) {
errors.push('CodeLLDB not found. Run: npm run build:adapter');
errors.push('CodeLLDB not found. It normally ships via the @debugmcp/codelldb-* optional dependencies; set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter');
} else {
codelldbPath = resolvedCodelldb;
codelldbVersion = await getCodeLLDBVersion() || undefined;
Expand Down
6 changes: 3 additions & 3 deletions packages/adapter-rust/src/rust-debug-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export class RustDebugAdapter extends EventEmitter implements IDebugAdapter {
if (!codelldbPath) {
errors.push({
code: 'CODELLDB_NOT_FOUND',
message: 'CodeLLDB executable not found. Run: npm run build:adapter',
message: 'CodeLLDB executable not found. It normally ships via the @debugmcp/codelldb-* optional dependencies (reinstall without --omit=optional), or set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter',
recoverable: true
});
}
Expand Down Expand Up @@ -579,7 +579,7 @@ export class RustDebugAdapter extends EventEmitter implements IDebugAdapter {

if (!resolvedPath) {
throw new AdapterError(
'CodeLLDB executable not found. Run: npm run build:adapter',
'CodeLLDB executable not found. It normally ships via the @debugmcp/codelldb-* optional dependencies (reinstall without --omit=optional), or set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter',
AdapterErrorCode.ENVIRONMENT_INVALID
);
}
Expand Down Expand Up @@ -948,7 +948,7 @@ You can also specify the Rust executable path explicitly in your debug configura
const message = error.message.toLowerCase();

if (message.includes('codelldb') && message.includes('not found')) {
return 'CodeLLDB is not installed. Please run: npm run build:adapter in packages/adapter-rust/';
return 'CodeLLDB is not installed. It normally ships via the @debugmcp/codelldb-* optional dependencies; set CODELLDB_PATH, or in a repo checkout run: npm run build:adapter';
}

if (message.includes('cargo') && message.includes('not found')) {
Expand Down
Loading
Loading