dap-mcp-server 0.1.12 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -7
- package/SKILL.md +37 -186
- package/build/adapters/detect.d.ts +12 -0
- package/build/adapters/detect.js +91 -0
- package/build/adapters/detect.js.map +1 -1
- package/build/adapters/registry.js +35 -12
- package/build/adapters/registry.js.map +1 -1
- package/build/diagnostics/doctor.d.ts +64 -0
- package/build/diagnostics/doctor.js +209 -0
- package/build/diagnostics/doctor.js.map +1 -0
- package/build/server.js +305 -83
- package/build/server.js.map +1 -1
- package/build/session/inspect.d.ts +6 -2
- package/build/session/inspect.js +24 -8
- package/build/session/inspect.js.map +1 -1
- package/build/session/run.js +2 -9
- package/build/session/run.js.map +1 -1
- package/build/session/session.d.ts +16 -0
- package/build/session/session.js +63 -8
- package/build/session/session.js.map +1 -1
- package/integrations/claude/dap-debugging/.claude-plugin/plugin.json +9 -0
- package/integrations/claude/dap-debugging/.mcp.json +8 -0
- package/integrations/claude/dap-debugging/skills/dap-debugging/SKILL.md +49 -0
- package/package.json +8 -3
- package/.forgejo/workflows/publish.yml +0 -63
- package/CLAUDE.md +0 -71
- package/TODO.md +0 -32
- package/docs/plans/2026-03-05-dap-wrapper-mcp-design.md +0 -326
- package/docs/plans/2026-03-05-dap-wrapper-mcp-implementation.md +0 -2815
- package/src/adapters/builtin.ts +0 -75
- package/src/adapters/detect.test.ts +0 -36
- package/src/adapters/detect.ts +0 -36
- package/src/adapters/registry.test.ts +0 -74
- package/src/adapters/registry.ts +0 -86
- package/src/dap/dap-client.test.ts +0 -118
- package/src/dap/dap-client.ts +0 -588
- package/src/dap/protocol.test.ts +0 -82
- package/src/dap/protocol.ts +0 -78
- package/src/dap/ring-buffer.test.ts +0 -82
- package/src/dap/ring-buffer.ts +0 -64
- package/src/dap/types.ts +0 -115
- package/src/index.ts +0 -30
- package/src/integration/debug-lifecycle.test.ts +0 -131
- package/src/server.ts +0 -1096
- package/src/session/inspect.test.ts +0 -126
- package/src/session/inspect.ts +0 -160
- package/src/session/run.test.ts +0 -74
- package/src/session/run.ts +0 -144
- package/src/session/session-manager.test.ts +0 -74
- package/src/session/session-manager.ts +0 -67
- package/src/session/session.test.ts +0 -126
- package/src/session/session.ts +0 -482
- package/src/test-fixtures/crash-adapter.js +0 -23
- package/src/test-fixtures/mock-adapter.js +0 -164
- package/src/test-fixtures/no-stop-adapter.js +0 -77
- package/src/test-fixtures/silent-adapter.js +0 -24
- package/src/test-fixtures/tcp-mock-adapter.js +0 -87
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dap-debugging
|
|
3
|
+
description: Use a real debugger for opaque test failures, crashes, swallowed exceptions, incorrect runtime state, or a bug that remains unexplained after static inspection or a failed fix. Prefer this over adding multiple print statements when actual values, branches, or call stacks are needed.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Debug Code with DAP
|
|
7
|
+
|
|
8
|
+
Use the `dap` MCP server when static inspection cannot explain a runtime failure. Debugging executes local code and can trigger its normal side effects, so do not run untrusted targets.
|
|
9
|
+
|
|
10
|
+
## Preferred Workflow
|
|
11
|
+
|
|
12
|
+
1. Call `debug_doctor` with the project `cwd`. Follow its remediation when `ready` is false.
|
|
13
|
+
2. Choose an executable line near the first observable bad state.
|
|
14
|
+
3. Call `debug_at` with `file`, `line`, and a small set of hypothesis-driven `expressions`. It detects the adapter, launches, inspects, and cleans up in one call.
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"cwd": "/workspace/project",
|
|
19
|
+
"program": "/workspace/project/app.py",
|
|
20
|
+
"file": "/workspace/project/app.py",
|
|
21
|
+
"line": 42,
|
|
22
|
+
"expressions": ["request.user", "result"]
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Read the outcome precisely:
|
|
27
|
+
|
|
28
|
+
- `hit: true`: use the location and values as evidence.
|
|
29
|
+
- `status: terminated`: execution finished before the breakpoint; verify path, arguments, and branch.
|
|
30
|
+
- `timedOut: true`: inspect captured output and narrow the target.
|
|
31
|
+
- With `hit: false`, `breakpoint.verified: false` means the adapter could not bind the source location.
|
|
32
|
+
|
|
33
|
+
Pass adapter-specific fields through `launchConfig`. Use absolute program and source paths.
|
|
34
|
+
|
|
35
|
+
## Failing Tests
|
|
36
|
+
|
|
37
|
+
Debug the smallest failing test. Supply its runner as `program` or through `launchConfig`, and its selector in `args`. Launch conventions differ across adapters; retain known-good fields from `.vscode/launch.json`. Put the breakpoint in application code before the assertion or exception boundary.
|
|
38
|
+
|
|
39
|
+
## Interactive Exploration
|
|
40
|
+
|
|
41
|
+
Use `debug_launch` only for multiple stops or stepping. A launch with breakpoints waits by default and reports stopped, terminated, or timeout.
|
|
42
|
+
|
|
43
|
+
1. Inspect the state returned by `debug_launch`.
|
|
44
|
+
2. Use `evaluate` for focused questions.
|
|
45
|
+
3. Prefer `step` with `next`; use `stepIn` only when the callee is suspect.
|
|
46
|
+
4. Move breakpoints with `set_breakpoints` as the hypothesis changes.
|
|
47
|
+
5. Finish with `debug_disconnect`.
|
|
48
|
+
|
|
49
|
+
Omit `sessionId` when one session is active. Use `debug_run` when output and termination are sufficient. For repeated observations, use logpoints (`logMessage`) and read them with `get_output` instead of editing source to add prints.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dap-mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "MCP server wrapping the Debug Adapter Protocol for AI-driven debugging",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"LLM",
|
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
"bin": {
|
|
20
20
|
"dap-mcp-server": "build/index.js"
|
|
21
21
|
},
|
|
22
|
+
"files": [
|
|
23
|
+
"build",
|
|
24
|
+
"SKILL.md",
|
|
25
|
+
"integrations/claude/dap-debugging"
|
|
26
|
+
],
|
|
22
27
|
"directories": {
|
|
23
28
|
"doc": "docs"
|
|
24
29
|
},
|
|
@@ -31,7 +36,7 @@
|
|
|
31
36
|
"typecheck": "tsc --noEmit"
|
|
32
37
|
},
|
|
33
38
|
"dependencies": {
|
|
34
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
35
40
|
"@vscode/debugprotocol": "^1.68.0"
|
|
36
41
|
},
|
|
37
42
|
"peerDependencies": {
|
|
@@ -40,6 +45,6 @@
|
|
|
40
45
|
"devDependencies": {
|
|
41
46
|
"@types/node": "^25.3.3",
|
|
42
47
|
"typescript": "^5.9.3",
|
|
43
|
-
"vitest": "^4.
|
|
48
|
+
"vitest": "^4.1.11"
|
|
44
49
|
}
|
|
45
50
|
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
runs-on: docker
|
|
11
|
-
steps:
|
|
12
|
-
- name: Checkout
|
|
13
|
-
uses: actions/checkout@v4
|
|
14
|
-
with:
|
|
15
|
-
fetch-depth: 0
|
|
16
|
-
token: ${{ secrets.REPO_TOKEN }}
|
|
17
|
-
|
|
18
|
-
- name: Setup Node.js
|
|
19
|
-
uses: actions/setup-node@v4
|
|
20
|
-
with:
|
|
21
|
-
node-version: '20'
|
|
22
|
-
registry-url: 'https://registry.npmjs.org'
|
|
23
|
-
|
|
24
|
-
- name: Install dependencies
|
|
25
|
-
run: npm ci
|
|
26
|
-
|
|
27
|
-
- name: Run tests
|
|
28
|
-
run: npm test
|
|
29
|
-
|
|
30
|
-
- name: Run typecheck
|
|
31
|
-
run: npm run typecheck
|
|
32
|
-
|
|
33
|
-
- name: Build
|
|
34
|
-
run: npm run build
|
|
35
|
-
|
|
36
|
-
- name: Configure git
|
|
37
|
-
run: |
|
|
38
|
-
git config user.name "Forgejo Actions"
|
|
39
|
-
git config user.email "actions@forgejo.local"
|
|
40
|
-
|
|
41
|
-
- name: Bump version and publish
|
|
42
|
-
env:
|
|
43
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
44
|
-
run: |
|
|
45
|
-
# Get current version
|
|
46
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
47
|
-
echo "Current version: $CURRENT_VERSION"
|
|
48
|
-
|
|
49
|
-
# Bump patch version
|
|
50
|
-
npm version patch --no-git-tag-version
|
|
51
|
-
NEW_VERSION=$(node -p "require('./package.json').version")
|
|
52
|
-
echo "New version: $NEW_VERSION"
|
|
53
|
-
|
|
54
|
-
# Commit version bump
|
|
55
|
-
git add package.json package-lock.json
|
|
56
|
-
git commit -m "chore: bump version to $NEW_VERSION [skip ci]"
|
|
57
|
-
git tag "v$NEW_VERSION"
|
|
58
|
-
|
|
59
|
-
# Push changes back to repository
|
|
60
|
-
git push origin main --tags
|
|
61
|
-
|
|
62
|
-
# Publish to npm
|
|
63
|
-
npm publish --access public
|
package/CLAUDE.md
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
MCP server wrapping the Debug Adapter Protocol (DAP) for AI agent-driven debugging. TypeScript, Node.js, ESM modules. Published to npm as `dap-mcp-server`.
|
|
8
|
-
|
|
9
|
-
## Commands
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm run build # TypeScript compilation → build/
|
|
13
|
-
npm run typecheck # Type-check without emitting (tsc --noEmit)
|
|
14
|
-
npm test # vitest run (all tests)
|
|
15
|
-
npm run test:watch # vitest in watch mode
|
|
16
|
-
npm run dev # tsc --watch
|
|
17
|
-
npm start # Run the MCP server (stdio transport)
|
|
18
|
-
npx vitest run src/path/to/file.test.ts # Run a single test file
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Architecture
|
|
22
|
-
|
|
23
|
-
Three layers, top to bottom:
|
|
24
|
-
|
|
25
|
-
1. **MCP Layer** (`src/server.ts`, `src/index.ts`) — `McpServer` with 12 tools + 1 resource (`dap://sessions`). All tool handlers return `{ content: [{ type: "text", text: JSON.stringify(...) }] }` with `isError: true` on failure. Entry point connects via `StdioServerTransport`.
|
|
26
|
-
|
|
27
|
-
2. **Session Layer** (`src/session/`) — `DebugSession` wraps a `DAPClient` with state machine (`idle → configuring → running ↔ stopped → terminated`), output buffering (`RingBuffer<OutputEntry>`), and composite state collection (`collectState()` fetches threads + stack + scopes + variables in one call). `SessionManager` handles multi-session tracking with auto-resolution (single active session doesn't need explicit ID).
|
|
28
|
-
|
|
29
|
-
3. **DAP Layer** (`src/dap/`) — `DAPClient` spawns adapter as child process, communicates via stdin/stdout using DAP wire protocol (Content-Length headers + JSON bodies, same framing as LSP). `MessageParser` handles incremental parsing. `DAPClient` extends `EventEmitter`, emitting DAP events and tracking pending request/response correlation by sequence number.
|
|
30
|
-
|
|
31
|
-
4. **Adapters** (`src/adapters/`) — `AdapterRegistry` with three tiers: builtins (`builtin.ts`) < global (`~/.dap-mcp/adapters.json`) < project (`./.dap-mcp/adapters.json`). Higher tiers override lower. `detect.ts` checks adapter binary availability via `which`/`where`.
|
|
32
|
-
|
|
33
|
-
### Request Lifecycle
|
|
34
|
-
|
|
35
|
-
`MCP tool call → server.ts handler → SessionManager.resolve(sessionId) → DebugSession method → DAPClient.sendRequest(command, args) → serialize to DAP wire format → adapter stdin → adapter stdout → MessageParser → response correlation by seq number → resolve Promise`
|
|
36
|
-
|
|
37
|
-
Events flow the reverse direction: adapter emits events → `DAPClient` re-emits → `DebugSession.handleEvent()` updates state machine, resolves waiters, buffers output.
|
|
38
|
-
|
|
39
|
-
## Code Conventions
|
|
40
|
-
|
|
41
|
-
- ESM modules (`"type": "module"` in package.json)
|
|
42
|
-
- Import paths use `.js` extension (e.g., `import { Foo } from "./foo.js"`)
|
|
43
|
-
- Never `console.log()` in server code — stdout is MCP wire protocol; use `console.error()` for diagnostics
|
|
44
|
-
- All tool execution errors use `isError: true` in MCP results, not JSON-RPC protocol errors
|
|
45
|
-
- Types from `@vscode/debugprotocol` for DAP message types
|
|
46
|
-
- Internal/MCP-facing types in `src/dap/types.ts`
|
|
47
|
-
- All source files carry an MIT license header comment — preserve it when creating new files
|
|
48
|
-
|
|
49
|
-
## Testing
|
|
50
|
-
|
|
51
|
-
- Framework: vitest (no config file — uses defaults)
|
|
52
|
-
- Unit tests: co-located with source (`*.test.ts`)
|
|
53
|
-
- Integration tests: `src/integration/` — test full DAP lifecycle against mock adapters
|
|
54
|
-
- Test fixtures: `src/test-fixtures/` — mock DAP adapters written in **plain JS** (not TypeScript), implementing enough of the DAP protocol to test against. `mock-adapter.js` is the full-featured one; `crash-adapter.js` and `silent-adapter.js` test error cases.
|
|
55
|
-
|
|
56
|
-
## Key Design Decisions
|
|
57
|
-
|
|
58
|
-
1. **Coarse-grained tools**: `get_state` returns threads+stack+scopes+variables in one call to minimize AI agent round-trips
|
|
59
|
-
2. **Synchronous stepping**: `step` blocks until stopped, returns new state
|
|
60
|
-
3. **Auto-session resolution**: `sessionId` optional when single session active
|
|
61
|
-
4. **Output ring buffer**: 10K lines max, oldest dropped
|
|
62
|
-
5. **Own DAP client**: Custom implementation (not `@vscode/debugadapter-testsupport`) for full control over event buffering and crash detection
|
|
63
|
-
|
|
64
|
-
## CI/CD
|
|
65
|
-
|
|
66
|
-
Forgejo Actions workflow (`.forgejo/workflows/publish.yml`) runs on push to `main`: tests → typecheck → build → bump patch version → publish to npm. Version bumps are auto-committed with `[skip ci]`.
|
|
67
|
-
|
|
68
|
-
## Design Documents
|
|
69
|
-
|
|
70
|
-
- Design: `docs/plans/2026-03-05-dap-wrapper-mcp-design.md`
|
|
71
|
-
- Implementation plan: `docs/plans/2026-03-05-dap-wrapper-mcp-implementation.md`
|
package/TODO.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# DAP MCP Server — Improvement TODO
|
|
2
|
-
|
|
3
|
-
Findings from a self-review of how usable this MCP is for an AI agent. Ordered by priority (descending). Check items off as completed.
|
|
4
|
-
|
|
5
|
-
## Tier 1 — Documentation (SKILL.md). High leverage, low risk.
|
|
6
|
-
|
|
7
|
-
- [x] **P1 — Logpoints section.** `breakpoints[].logMessage` is already wired through (session.ts:138) but is invisible in SKILL.md. It is the closest thing to a drop-in replacement for `print()` debugging: no code edits, captures every hit, no execution pause. Should have its own headline section with an example.
|
|
8
|
-
- [x] **P2 — "Debug a failing test" section.** Most real bugs surface inside test runners (pytest, vitest, jest, go test, cargo test). Currently zero guidance. Add a per-framework template for launching a single test under the debugger.
|
|
9
|
-
- [x] **P3 — "Switch from print() to debugger" triggers.** Concrete rules an AI agent will actually follow: "if first fix attempt was wrong, stop guessing"; "if about to add 3+ prints, use logpoints"; "if reasoning about iteration N, use `hitCondition`"; "if traceback is non-obvious, launch test under debugger".
|
|
10
|
-
- [x] **P4 — Stepping strategy.** Default to `next`. Use `stepIn` only when you suspect the bug is *inside* the called function. Otherwise agents get lost in library internals.
|
|
11
|
-
- [x] **P5 — Full worked example.** Real bug → real `debug_launch` call → real returned state → identified fix. Replaces all the abstract advice with one concrete walkthrough.
|
|
12
|
-
- [x] **P5b — Node.js adapter recipe.** Builtin was removed; add a ready-to-paste `configure_adapter` snippet for `js-debug-dap`.
|
|
13
|
-
|
|
14
|
-
## Tier 2 — Code changes that materially improve UX.
|
|
15
|
-
|
|
16
|
-
- [x] **P6 — `debug_inspect` macro tool.** One call: launch, run to a breakpoint, evaluate a list of expressions, disconnect. Collapses a 5–7 round-trip workflow into 1. Most likely change to make me reach for the debugger reflexively.
|
|
17
|
-
- [x] **P7 — Flip `stopOnEntry` default to `false` when breakpoints are provided.** Today defaults to `true` regardless (server.ts:206). Doing the right thing automatically is better than relying on the agent reading the SKILL.md.
|
|
18
|
-
- [x] **P8 — Structured deep variables.** `getVariables` with `depth > 1` flattens children into the value string (session.ts:271–278). Hard for the AI to consume. Return nested `children: [...]` instead.
|
|
19
|
-
- [x] **P9 — `list_adapters` summary line + surfaced install hints.** Add `summary: "2/4 installed"` and lift `installHint` for missing adapters to the top level so it's scannable.
|
|
20
|
-
- [x] **P10 — `debug_run` macro tool.** Launch, run to completion, return all stdout/stderr. Zero breakpoints, zero round-trips. For "what does this script actually print/crash with?" cases.
|
|
21
|
-
|
|
22
|
-
## Tier 3 — Polish.
|
|
23
|
-
|
|
24
|
-
- [x] **P11 — Better "session is not stopped" error.** Currently says "use step with action: pause" (server.ts:549) — bad advice (Python `pause` lands in arbitrary library code). Suggest "set a breakpoint where you want to inspect, then continue to it".
|
|
25
|
-
- [x] **P12 — Version drift.** `McpServer` registers as `0.1.0` (server.ts:48); package.json is `0.1.10`. Read from `package.json`.
|
|
26
|
-
- [x] **P13 — `list_breakpoints` tool.** After several `set_breakpoints` calls, no way to introspect what's set. Minor.
|
|
27
|
-
|
|
28
|
-
## Tier 4 — Speculative.
|
|
29
|
-
|
|
30
|
-
- [x] **`get_output({ since })` for incremental polling.** Smaller substitute for streaming subscriptions. Caller passes the `nextSince` value from a prior call to receive only newly-emitted entries. Useful for watching logpoint output during `continue` against long-running programs.
|
|
31
|
-
- [ ] ~~Streaming output via MCP resource subscriptions.~~ AI agents don't watch streams in real time; the request/response pattern doesn't benefit. `since`-based polling covers the practical case.
|
|
32
|
-
- [ ] ~~Auto-detect test runner from program path.~~ Too magic; SKILL.md recipes (P2) make the right call explicit, and silent misfires would be worse than no detection at all.
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
# DAP Wrapper MCP Server — Design Document
|
|
2
|
-
|
|
3
|
-
**Date**: 2026-03-05
|
|
4
|
-
**Status**: Approved
|
|
5
|
-
|
|
6
|
-
## Purpose
|
|
7
|
-
|
|
8
|
-
An MCP server that wraps the Debug Adapter Protocol (DAP), enabling AI agents (Claude, etc.) to use real debuggers instead of relying on print statements and log analysis. The server spawns debug adapters as child processes and exposes a coarse-grained set of MCP tools optimized for agent-driven debugging workflows.
|
|
9
|
-
|
|
10
|
-
## Decisions
|
|
11
|
-
|
|
12
|
-
- **Language**: TypeScript (Node.js)
|
|
13
|
-
- **Transport**: MCP over stdio; DAP over child process stdin/stdout
|
|
14
|
-
- **Adapter management**: Config-based with a registration tool + built-in defaults for Python (debugpy), Node.js (js-debug), Go (delve), C/C++ (lldb-dap)
|
|
15
|
-
- **Tool granularity**: Coarse-grained (~12 tools), composite responses
|
|
16
|
-
- **Execution model**: Synchronous stepping with configurable timeout — `step` blocks until the debuggee stops and returns the new state
|
|
17
|
-
|
|
18
|
-
## Architecture
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
┌──────────────────────────────────────────────────┐
|
|
22
|
-
│ MCP Server (Node.js) │
|
|
23
|
-
│ │
|
|
24
|
-
│ ┌──────────┐ ┌─────────────────────────────┐ │
|
|
25
|
-
│ │ Adapter │ │ Session Manager │ │
|
|
26
|
-
│ │ Registry │ │ │ │
|
|
27
|
-
│ │ │ │ Session ──► DAP Client ─────┼───┼──► adapter (child process)
|
|
28
|
-
│ │ - python │ │ • state (running/stopped) │ │ (stdin/stdout)
|
|
29
|
-
│ │ - node │ │ • breakpoints map │ │
|
|
30
|
-
│ │ - go │ │ • output ring buffer │ │
|
|
31
|
-
│ │ - cppdbg │ │ • event queue │ │
|
|
32
|
-
│ │ - custom │ │ • focused thread │ │
|
|
33
|
-
│ └──────────┘ └─────────────────────────────┘ │
|
|
34
|
-
│ │
|
|
35
|
-
│ ┌───────────────────────────────────────────┐ │
|
|
36
|
-
│ │ MCP Layer (stdio transport) │ │
|
|
37
|
-
│ │ - 12 Tool handlers │ │
|
|
38
|
-
│ │ - Resource: dap://sessions │ │
|
|
39
|
-
│ └───────────────────────────────────────────┘ │
|
|
40
|
-
└──────────────────────────────────────────────────┘
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Components
|
|
44
|
-
|
|
45
|
-
1. **Adapter Registry** — Stores adapter configurations. Each config: `type`, `runtime` (optional), `program` (path to adapter binary), `args`, `launchDefaults`. Built-in defaults for common adapters. Persisted to `~/.dap-mcp/adapters.json` (global) and `./.dap-mcp/adapters.json` (project-local).
|
|
46
|
-
|
|
47
|
-
2. **Session Manager** — Manages active debug sessions. Each session owns a `DAPClient`, tracks state (`idle | configuring | running | stopped | terminated`), maintains breakpoints map, buffers output in a ring buffer (10,000 lines max), and handles adapter crash detection.
|
|
48
|
-
|
|
49
|
-
3. **DAP Client** — Low-level protocol handler. Spawns adapter child process, sends/receives DAP messages with `Content-Length` framing, correlates request/response by `seq`, emits events to the session. Includes startup timeout (10s default).
|
|
50
|
-
|
|
51
|
-
4. **MCP Layer** — Registers tools, handles tool calls, serves the `dap://sessions` resource.
|
|
52
|
-
|
|
53
|
-
## Tools (12)
|
|
54
|
-
|
|
55
|
-
### Session Lifecycle
|
|
56
|
-
|
|
57
|
-
#### `debug_launch`
|
|
58
|
-
Start a new debug session by launching a program.
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
Input: {
|
|
62
|
-
adapter: string, // "python" | "node" | "go" | "cppdbg" | custom
|
|
63
|
-
program: string,
|
|
64
|
-
args?: string[],
|
|
65
|
-
cwd?: string,
|
|
66
|
-
env?: Record<string, string>,
|
|
67
|
-
stopOnEntry?: boolean, // default: true
|
|
68
|
-
breakpoints?: Array<{
|
|
69
|
-
file: string,
|
|
70
|
-
lines: Array<{
|
|
71
|
-
line: number,
|
|
72
|
-
condition?: string,
|
|
73
|
-
hitCondition?: string,
|
|
74
|
-
logMessage?: string
|
|
75
|
-
}>
|
|
76
|
-
}>,
|
|
77
|
-
exceptionBreakpoints?: string[], // e.g., ["uncaught"]
|
|
78
|
-
adapterConfig?: Record<string, any> // pass-through to adapter
|
|
79
|
-
}
|
|
80
|
-
Output: { sessionId: string, state: StoppedState | RunningState }
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
#### `debug_attach`
|
|
84
|
-
Attach to a running process.
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
Input: {
|
|
88
|
-
adapter: string,
|
|
89
|
-
processId?: number,
|
|
90
|
-
host?: string,
|
|
91
|
-
port?: number,
|
|
92
|
-
adapterConfig?: Record<string, any>
|
|
93
|
-
}
|
|
94
|
-
Output: { sessionId: string, state: StoppedState | RunningState }
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
#### `debug_restart`
|
|
98
|
-
Restart the current debug session with the same configuration.
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
Input: { sessionId?: string }
|
|
102
|
-
Output: { sessionId: string, state: StoppedState | RunningState }
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
#### `debug_disconnect`
|
|
106
|
-
End a debug session.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
Input: {
|
|
110
|
-
sessionId?: string,
|
|
111
|
-
terminateDebuggee?: boolean // default: true for launch, false for attach
|
|
112
|
-
}
|
|
113
|
-
Output: { success: boolean }
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Breakpoints
|
|
117
|
-
|
|
118
|
-
#### `set_breakpoints`
|
|
119
|
-
Set or replace breakpoints in a source file. Replaces all breakpoints in the specified file (DAP semantics).
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
Input: {
|
|
123
|
-
sessionId?: string,
|
|
124
|
-
file: string,
|
|
125
|
-
breakpoints: Array<{
|
|
126
|
-
line: number,
|
|
127
|
-
condition?: string,
|
|
128
|
-
hitCondition?: string,
|
|
129
|
-
logMessage?: string
|
|
130
|
-
}>
|
|
131
|
-
}
|
|
132
|
-
Output: {
|
|
133
|
-
breakpoints: Array<{
|
|
134
|
-
id: number,
|
|
135
|
-
verified: boolean,
|
|
136
|
-
line: number,
|
|
137
|
-
message?: string
|
|
138
|
-
}>
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
#### `set_exception_breakpoints`
|
|
143
|
-
Configure which exceptions cause the debugger to break.
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
Input: {
|
|
147
|
-
sessionId?: string,
|
|
148
|
-
filters: string[] // adapter-specific, e.g., ["uncaught", "raised"]
|
|
149
|
-
}
|
|
150
|
-
Output: { filters: string[] }
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### State Inspection
|
|
154
|
-
|
|
155
|
-
#### `get_state`
|
|
156
|
-
Get current debuggee state. When stopped: threads + stack trace + scopes + variables. When running: status + buffered output.
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
Input: {
|
|
160
|
-
sessionId?: string,
|
|
161
|
-
threadId?: number, // default: thread that triggered stop
|
|
162
|
-
depth?: number, // stack frames to return, default 10
|
|
163
|
-
variableDepth?: number, // nested expansion depth, default 1
|
|
164
|
-
timeout?: number // ms to wait if running, default 0
|
|
165
|
-
}
|
|
166
|
-
Output: StoppedState | RunningState
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
#### `evaluate`
|
|
170
|
-
Evaluate an expression in the debuggee's context.
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
Input: {
|
|
174
|
-
sessionId?: string,
|
|
175
|
-
expression: string,
|
|
176
|
-
frameId?: number, // default: top frame
|
|
177
|
-
context?: "repl" | "watch" | "hover" // default: "repl"
|
|
178
|
-
}
|
|
179
|
-
Output: {
|
|
180
|
-
result: string,
|
|
181
|
-
type?: string,
|
|
182
|
-
hasChildren: boolean,
|
|
183
|
-
variablesReference: number
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### `get_output`
|
|
188
|
-
Get buffered program output.
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
Input: {
|
|
192
|
-
sessionId?: string,
|
|
193
|
-
category?: "stdout" | "stderr" | "console", // default: all
|
|
194
|
-
clear?: boolean // clear buffer after reading, default false
|
|
195
|
-
}
|
|
196
|
-
Output: {
|
|
197
|
-
output: Array<{ category: string, text: string, timestamp: string }>,
|
|
198
|
-
truncated: boolean
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### Execution Control
|
|
203
|
-
|
|
204
|
-
#### `step`
|
|
205
|
-
Control execution. Synchronous: blocks until debuggee stops or timeout.
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
Input: {
|
|
209
|
-
sessionId?: string,
|
|
210
|
-
action: "continue" | "next" | "stepIn" | "stepOut" | "pause",
|
|
211
|
-
threadId?: number,
|
|
212
|
-
timeout?: number // ms, default 30000
|
|
213
|
-
}
|
|
214
|
-
Output: StoppedState | { status: "running", elapsedMs: number }
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Adapter Management
|
|
218
|
-
|
|
219
|
-
#### `configure_adapter`
|
|
220
|
-
Register or update a debug adapter configuration.
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
Input: {
|
|
224
|
-
type: string, // adapter identifier
|
|
225
|
-
runtime?: string, // e.g., "node", "python3"
|
|
226
|
-
program: string, // path to adapter binary/script
|
|
227
|
-
args?: string[],
|
|
228
|
-
launchDefaults?: Record<string, any>,
|
|
229
|
-
scope?: "global" | "project" // default: "project"
|
|
230
|
-
}
|
|
231
|
-
Output: { success: boolean }
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
#### `list_adapters`
|
|
235
|
-
List available debug adapter configurations with availability status.
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
Input: {}
|
|
239
|
-
Output: {
|
|
240
|
-
adapters: Array<{
|
|
241
|
-
type: string,
|
|
242
|
-
source: "builtin" | "global" | "project",
|
|
243
|
-
available: boolean, // binary exists on system
|
|
244
|
-
program: string,
|
|
245
|
-
installHint?: string // e.g., "pip install debugpy"
|
|
246
|
-
}>
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
## Common Response Types
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
interface StoppedState {
|
|
254
|
-
status: "stopped";
|
|
255
|
-
reason: "breakpoint" | "step" | "exception" | "pause" | "entry";
|
|
256
|
-
location: {
|
|
257
|
-
file: string;
|
|
258
|
-
line: number;
|
|
259
|
-
column?: number;
|
|
260
|
-
functionName?: string;
|
|
261
|
-
};
|
|
262
|
-
threads: Array<{ id: number; name: string; stopped: boolean }>;
|
|
263
|
-
stackTrace: Array<{
|
|
264
|
-
id: number;
|
|
265
|
-
name: string;
|
|
266
|
-
file: string;
|
|
267
|
-
line: number;
|
|
268
|
-
column?: number;
|
|
269
|
-
}>;
|
|
270
|
-
scopes: Array<{
|
|
271
|
-
name: string;
|
|
272
|
-
variables: Array<{
|
|
273
|
-
name: string;
|
|
274
|
-
value: string;
|
|
275
|
-
type?: string;
|
|
276
|
-
hasChildren: boolean;
|
|
277
|
-
variablesReference: number;
|
|
278
|
-
}>;
|
|
279
|
-
}>;
|
|
280
|
-
output?: string[];
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
interface RunningState {
|
|
284
|
-
status: "running";
|
|
285
|
-
output?: string[];
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
## Built-in Adapter Defaults
|
|
290
|
-
|
|
291
|
-
| Type | Adapter | Detection | Install Hint |
|
|
292
|
-
|---|---|---|---|
|
|
293
|
-
| `python` | debugpy | `python3 -c "import debugpy"` | `pip install debugpy` |
|
|
294
|
-
| `node` | js-debug-dap | `which js-debug-dap` or bundled | Ships with MCP |
|
|
295
|
-
| `go` | delve | `which dlv` | `go install github.com/go-delve/delve/cmd/dlv@latest` |
|
|
296
|
-
| `cppdbg` | lldb-dap | `which lldb-dap` | `apt install lldb` / `brew install llvm` |
|
|
297
|
-
|
|
298
|
-
## Error Handling
|
|
299
|
-
|
|
300
|
-
All execution errors use MCP's `isError: true` in tool results (not JSON-RPC protocol errors), so the AI can read and self-correct.
|
|
301
|
-
|
|
302
|
-
| Scenario | Behavior |
|
|
303
|
-
|---|---|
|
|
304
|
-
| Adapter binary not found | `isError: true` with install instructions |
|
|
305
|
-
| Adapter crash (child exit) | Session marked `terminated`, stderr in error message |
|
|
306
|
-
| DAP protocol error | Adapter's error message surfaced verbatim |
|
|
307
|
-
| Timeout on step/continue | Return `{ status: "running", elapsedMs }` — not an error |
|
|
308
|
-
| Invalid session ID | Error listing available sessions |
|
|
309
|
-
| Expression eval failure | Adapter's error message (e.g., "NameError: ...") |
|
|
310
|
-
|
|
311
|
-
## MCP Resource
|
|
312
|
-
|
|
313
|
-
- `dap://sessions` — List of active sessions with status summary. Subscribable (emits `notifications/resources/updated` on session state changes).
|
|
314
|
-
|
|
315
|
-
## Config Files
|
|
316
|
-
|
|
317
|
-
- `~/.dap-mcp/adapters.json` — Global adapter configurations
|
|
318
|
-
- `./.dap-mcp/adapters.json` — Project-local adapter overrides (takes precedence)
|
|
319
|
-
|
|
320
|
-
## Key Design Principles
|
|
321
|
-
|
|
322
|
-
1. **One call, maximum info**: Composite responses (stack + variables + threads) reduce round-trips
|
|
323
|
-
2. **Smart defaults**: Auto-select single session, auto-select stopped thread, `stopOnEntry: true`
|
|
324
|
-
3. **Errors are information**: Execution errors in results (not protocol errors) let the AI self-correct
|
|
325
|
-
4. **Bounded resources**: Output ring buffer (10K lines), variable depth limits, stack frame limits
|
|
326
|
-
5. **Crash resilience**: Adapter process monitoring with clear error reporting
|