oh-mcp-dap
An MCP server that provides a real debugger via the Debug Adapter Protocol, exposing a single 'debug' tool to launch/attach, control execution, and inspect program state across gdb, lldb, debugpy, and more.
README
oh-mcp-dap
An MCP server that gives an AI agent a real debugger. It speaks the Debug Adapter Protocol (DAP) to gdb, lldb, debugpy, delve, and any other adapter you configure — launch or attach to a program, set breakpoints, step, and inspect threads, frames, variables, memory, and disassembly.
It is a thin MCP wrapper around the DAP engine from
oh-my-pi (@oh-my-pi/pi-coding-agent),
reusing its session manager and adapter-config system rather than reimplementing
DAP. See Attribution.
⚗️ Experiment. This is an exploratory project — an experiment in reusing oh-my-pi's DAP engine behind a single-tool MCP server. Interfaces may change, it has not been battle-tested, and it has not yet been run end-to-end against a live client in this form. Feedback and breakage reports welcome.
Runs on Bun (see Requirements).
Why one tool (the design difference)
Most MCP DAP servers expose one MCP tool per DAP operation:
set_breakpoint, continue, step_over, evaluate, stack_trace,
read_memory, … — twenty-plus separate tools.
oh-mcp-dap exposes a single debug tool with an action field that selects
the operation. This is the same shape oh-my-pi uses internally, and it's a
deliberate choice:
| Tool-per-function | Single action tool (this server) | |
|---|---|---|
| Tools added to the model's context | 20–30 | 1 |
| Token cost of the tool list | High, always present | Low |
| Where the operation lives | The tool name | The action argument |
| Adding a new DAP op | New tool, new registration | New action enum value |
| Discoverability for the model | Many shallow tools | One tool whose description lists the workflow |
Why the single tool wins for a debugger specifically:
- Context economy. Every registered tool's name + schema sits in the model's context on every turn. A debugger's operations are numerous but individually tiny; paying 25 tool-schemas' worth of tokens to describe them crowds out the tools the agent actually reasons about. One tool keeps the surface flat.
- The operations are one workflow, not 25 capabilities.
launch → set_breakpoint → continue → stack_trace → variables → stepis a single stateful conversation with one session. Modeling it as one tool with anactionmirrors that: the description teaches the flow, and the shared parameter set (file,line,frame_id,expression, …) is documented once. - Coherent state. There is exactly one active session. A single tool makes that constraint obvious instead of spreading it across many tools that all implicitly mutate the same hidden session.
- Cheap evolution. New adapter capabilities become new
actionvalues; no client re-discovery churn.
The tradeoff is honest: a single tool has a broader input schema, and a client UI that renders per-tool affordances sees only one entry. For an agent driving a debugger, the context savings and workflow clarity are worth it. If you want the per-tool model instead, this server isn't that — by design.
What it exposes
One tool, debug. Required field action; the rest are that action's
arguments. Actions:
Session: launch, attach, terminate, sessions, output
Breakpoints: set_breakpoint, remove_breakpoint,
set_instruction_breakpoint, remove_instruction_breakpoint,
data_breakpoint_info, set_data_breakpoint, remove_data_breakpoint
Execution: continue, step_over, step_in, step_out, pause
Inspection: threads, stack_trace, scopes, variables, evaluate,
modules, loaded_sources, read_memory, write_memory, disassemble
Escape hatch: custom_request (any raw DAP request)
Typical flow:
{ "action": "launch", "program": "./my_app" }
{ "action": "set_breakpoint", "file": "src/main.c", "line": 42 }
{ "action": "continue" }
{ "action": "stack_trace" }
{ "action": "scopes", "frame_id": 0 }
{ "action": "variables", "scope_id": 1001 }
{ "action": "terminate" }
Requirements
- Bun ≥ 1.3.14. The upstream DAP engine is Bun-native (ships TypeScript, uses Bun's YAML). This server runs on Bun; Node is not supported.
- The debug adapter(s) for your language on
PATH(e.g.gdb,lldb-dap,debugpy,dlv). Adapters are external programs — this server only drives them.
Install
git clone <this-repo> oh-mcp-dap
cd oh-mcp-dap
bun install
Smoke-check that it starts (it will wait on stdin for a client — Ctrl-C to exit):
bun run src/server.ts --workspace .
Configure your MCP client
Point your client at the server with Bun. Set the workspace to the project you
want to debug — that's where dap.json and root markers are resolved from.
Claude Code / Claude Desktop (mcpServers):
{
"mcpServers": {
"dap": {
"command": "bun",
"args": ["run", "/absolute/path/to/oh-mcp-dap/src/server.ts"],
"env": { "OH_MCP_DAP_WORKSPACE": "/absolute/path/to/your/project" }
}
}
}
The workspace can be set three ways (first wins): --workspace <dir> /
-w <dir> arg, OH_MCP_DAP_WORKSPACE env, else the server's process.cwd().
Any individual call may also override it with a cwd argument.
Adapter configuration (dap.json)
Adapters are configured exactly as in oh-my-pi. A set of built-in adapters
ships out of the box and any dap.json you provide is merged over them, so
you can add new debuggers or tweak existing ones without redefining everything.
Built-ins include: gdb, lldb-dap, codelldb, debugpy, dlv,
js-debug-adapter, netcoredbg, kotlin-debug-adapter, rdbg,
php-debug-adapter, bash-debug-adapter, dart, flutter,
elixir-ls-debugger.
Add any adapter
Drop a dap.json in your workspace (the file is auto-discovered — see
discovery order). Example: a custom 4D adapter that this
repo ships in dap.json:
{
"adapters": {
"4d": {
"command": "node",
"args": ["4d-dap-bridge.js", "${port}"],
"connectMode": "tcp",
"languages": ["4d"],
"fileTypes": [".4dm"],
"rootMarkers": [".4DProject", "Project"],
"launchDefaults": { "request": "launch" },
"attachDefaults": { "request": "attach" }
}
}
}
Adapter fields
| Field | Meaning |
|---|---|
command |
Adapter executable (resolved on PATH, or a relative/absolute path). |
args |
Launch args. ${port} is substituted with a free port for socket/tcp adapters. |
connectMode |
"stdio" (default), "socket", or "tcp". How the server talks to the adapter. |
languages |
Language ids this adapter serves (informational / selection). |
fileTypes |
File extensions (e.g. .py) used to auto-select the adapter for a target. |
rootMarkers |
Files/dirs that mark a project root (e.g. Cargo.toml), used for selection. |
launchDefaults / attachDefaults |
Default DAP request bodies merged into every launch/attach. |
acceptsDirectoryProgram |
true if the adapter accepts a directory as program (e.g. dlv). |
Auto-selection: when a call omits adapter, the server picks one by the
target's file type and nearest root marker. Pass adapter to force a choice.
Discovery order
dap.json (also .dap.json, dap.yaml, dap.yml) is discovered from, and
merged in this precedence (later overrides earlier), all on top of the
built-ins:
- built-in defaults
~/dap.json(home)- user config dirs
- project config dirs (relative to the workspace)
<workspace>/dap.json
So a workspace-local dap.json has the final say.
How it works
MCP client ──stdio JSON-RPC──▶ src/server.ts (one "debug" tool)
│
▼
src/dispatch.ts (action → engine → text)
│
▼
src/dap-core.ts ──▶ @oh-my-pi/pi-coding-agent/dap
• dapSessionManager (the real DAP client + session)
• dap.json config + adapter selection
src/server.ts— MCP stdio server; registers the single tool and routes calls.src/schema.ts— the tool's JSON Schema + description.src/dispatch.ts— the action switch (adapted from oh-my-pi'sdebugtool, agent-framework couplings removed).src/format.ts— plain-text renderers for DAP responses.src/dap-core.ts— the single import seam onto the engine.
Depending vs. vendoring
This server depends on the published @oh-my-pi/pi-coding-agent package and
imports its official /dap subpath — no engine code is copied in. That keeps the
debugger logic upstream (bug fixes flow in) at the cost of pulling a large dep
tree at install time (only DAP-reachable code loads at runtime).
If you ever need to cut that dependency, everything the engine provides is behind
src/dap-core.ts. Vendoring packages/coding-agent/src/dap/**
(MIT) and its few internal helpers, then rewriting only that one file, is the
supported escape hatch.
A note on stdout
The MCP stdio transport owns stdout for JSON-RPC. The server forces the
upstream logger's console transport off and mirrors diagnostics to stderr, so
adapter/engine logs never corrupt the protocol stream. Watch stderr for
[oh-mcp-dap] lines.
Attribution
Built on oh-my-pi by Mario Zechner and Can Bölük (MIT). The DAP engine is
used as a dependency; the formatters and dispatch logic are adapted from
packages/coding-agent/src/tools/debug.ts. See NOTICE and
LICENSE.
This project is MIT-licensed.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。