dap-mcp-server 0.1.5

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.
Files changed (65) hide show
  1. package/.claude/settings.local.json +31 -0
  2. package/.forgejo/workflows/publish.yml +63 -0
  3. package/CLAUDE.md +71 -0
  4. package/LICENSE +21 -0
  5. package/README.md +105 -0
  6. package/SKILL.md +62 -0
  7. package/build/adapters/builtin.d.ts +24 -0
  8. package/build/adapters/builtin.js +46 -0
  9. package/build/adapters/builtin.js.map +1 -0
  10. package/build/adapters/detect.d.ts +23 -0
  11. package/build/adapters/detect.js +36 -0
  12. package/build/adapters/detect.js.map +1 -0
  13. package/build/adapters/registry.d.ts +39 -0
  14. package/build/adapters/registry.js +79 -0
  15. package/build/adapters/registry.js.map +1 -0
  16. package/build/dap/dap-client.d.ts +46 -0
  17. package/build/dap/dap-client.js +190 -0
  18. package/build/dap/dap-client.js.map +1 -0
  19. package/build/dap/protocol.d.ts +32 -0
  20. package/build/dap/protocol.js +71 -0
  21. package/build/dap/protocol.js.map +1 -0
  22. package/build/dap/ring-buffer.d.ts +35 -0
  23. package/build/dap/ring-buffer.js +57 -0
  24. package/build/dap/ring-buffer.js.map +1 -0
  25. package/build/dap/types.d.ts +87 -0
  26. package/build/dap/types.js +25 -0
  27. package/build/dap/types.js.map +1 -0
  28. package/build/index.d.ts +24 -0
  29. package/build/index.js +30 -0
  30. package/build/index.js.map +1 -0
  31. package/build/server.d.ts +24 -0
  32. package/build/server.js +735 -0
  33. package/build/server.js.map +1 -0
  34. package/build/session/session-manager.d.ts +32 -0
  35. package/build/session/session-manager.js +60 -0
  36. package/build/session/session-manager.js.map +1 -0
  37. package/build/session/session.d.ts +85 -0
  38. package/build/session/session.js +374 -0
  39. package/build/session/session.js.map +1 -0
  40. package/docs/plans/2026-03-05-dap-wrapper-mcp-design.md +326 -0
  41. package/docs/plans/2026-03-05-dap-wrapper-mcp-implementation.md +2815 -0
  42. package/package.json +43 -0
  43. package/src/adapters/builtin.ts +47 -0
  44. package/src/adapters/detect.test.ts +36 -0
  45. package/src/adapters/detect.ts +36 -0
  46. package/src/adapters/registry.test.ts +73 -0
  47. package/src/adapters/registry.ts +86 -0
  48. package/src/dap/dap-client.test.ts +87 -0
  49. package/src/dap/dap-client.ts +216 -0
  50. package/src/dap/protocol.test.ts +82 -0
  51. package/src/dap/protocol.ts +78 -0
  52. package/src/dap/ring-buffer.test.ts +82 -0
  53. package/src/dap/ring-buffer.ts +64 -0
  54. package/src/dap/types.ts +92 -0
  55. package/src/index.ts +30 -0
  56. package/src/integration/debug-lifecycle.test.ts +107 -0
  57. package/src/server.ts +866 -0
  58. package/src/session/session-manager.test.ts +74 -0
  59. package/src/session/session-manager.ts +67 -0
  60. package/src/session/session.test.ts +84 -0
  61. package/src/session/session.ts +435 -0
  62. package/src/test-fixtures/crash-adapter.js +23 -0
  63. package/src/test-fixtures/mock-adapter.js +142 -0
  64. package/src/test-fixtures/silent-adapter.js +24 -0
  65. package/tsconfig.json +16 -0
@@ -0,0 +1,326 @@
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