DEA MCP server
Commit Oct 21, 2026Provides coding agents with asynchronous control over GDB, LLDB, and PDB using delta-compressed JSON to minimize context window usage.
Also known as prolegendluv/DEA
- Stars
- 2
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- —
- Last commit
- Oct 21, 2026
- License
- —
What is DEA MCP?
DEA provides coding agents with asynchronous control over GDB, LLDB, and PDB using delta-compressed JSON to minimize context window usage.
Summary generated from the project's README
About DEA MCP server
Debugging live processes through coding agents is made more efficient with DEA, which provides asynchronous control over GDB, LLDB, and PDB. Instead of flooding an AI's context window with thousands of tokens of raw debugger output, this server uses delta-compressed JSON to transmit only the specific changes in registers and variables. This approach ensures that agents receive compact updates, typically staying under a strict 191-token limit per step.
Developers can integrate this server into clients like Claude Code, Cursor, or Antigravity by configuring the absolute path to their Python executable to run the server via stdio. The system supports launching or attaching to processes, setting conditional breakpoints, and inspecting frames. While PDB and GDB are verified on Windows, LLDB is also supported provided the local environment has compatible Python bindings. Users manage debugging sessions by starting a session, waiting for events, and using cursors to access larger, paginated details when necessary.
What you can do with it
- 1Debug off-by-one errorsAn agent can find the first incorrect item in a checksum calculation by setting a conditional breakpoint and inspecting local variables.
- 2Minimize context window usageDevelopers can prevent debugger dumps from consuming thousands of tokens by using delta-compressed state updates.
- 3Trace variable mutationsAn AI can step through code to see exactly how a specific variable changes between execution steps.
Written from the project's README. Every use case is checked against a quote from it.
README
View on GitHubDEA — Debug Everything Autonomously
Static tools read dead binaries. DEA debugs live processes—in ≤191 tokens per step.
DEA is an MCP server that gives coding agents persistent, asynchronous control over GDB, LLDB, and PDB. Set a conditional breakpoint, stop at the first bad value, inspect a frame, and see exactly what changed when execution advances.
Raw debugger dumps can flood an agent's context window with 5,000+ tokens of hex, frames, arrays, and unchanged locals. DEA retains the captured state and sends delta-compressed JSON: changed registers and variables, compact stop metadata, and cursors for details. Agents spend their context on the failure.
Raw output vs. a DEA delta
An illustrative excerpt beside the corresponding kind of compact response:
The example uses illustrative IDs and omits unchanged values. Actual payloads are canonical JSON on one line; the excerpt is not a measured compression benchmark. Raw dump size depends on the target and requested debugger commands.
A measured response budget
Every tool response must satisfy:
max(tokens_cl100k_base(JSON), tokens_o200k_base(JSON)) <= 191
This is an executable bound on the final canonical JSON, enforced with both pinned tokenizers by WireGuard. It includes errors, omission counts, hints, and cursor handles. Each MCP tool returns exactly one JSON text block without duplicated structured output. MCP envelopes, initialization, and tool definitions are outside the budget; other tokenizers may count differently.
DEA compares original captured values, preserves unknown observations, and resets baselines when frame context changes. Large values and omitted changes live in immutable, paginated details. JSON is never cut mid-record to meet the limit.
Real Agent Trace
Captured from the real MCP stdio server (python -m dea serve) using the PDB
backend and demos/python_offbyone/buggy.py on Windows / Python 3.14.6. These
are the exact, unmodified canonical JSON strings delivered in MCP text blocks.
Every emitted field, including scoped delta IDs, paths, omission counts, and
cursor handles, is preserved. Optional fields absent below were absent in the
server response. Session/cursor handles belong to this captured run; new sessions
return their own handles.
Conditional breakpoint hit — stop: 2
The conditional breakpoint stops before line 9 at index == 4096, without
single-stepping through the loop. Measured on the exact string below using DEA's
wire token counter: cl100k_base: 173 tokens; o200k_base: 175 tokens.
{"cursor":"0000000000000004","eid":4,"frames":[{"at":{"file":"E:\\Projects\\stars\\demos\\python_offbyone\\buggy.py","fn":"checksum","line":9},"i":0}],"omitted":{"frames":1,"regs":0,"vars":0},"reason":"breakpoint","sid":"9a054a628c8d7973","stop":2,"type":"stop","v":1,"vars":[{"after":"4096","id":"thread:1/frame:2/local:index","name":"index","op":"add"},{"after":"4096","id":"thread:1/frame:2/local:item","name":"item","op":"add"},{"after":"8386560","id":"thread:1/frame:2/local:total","name":"total","op":"add"}]}
Step over the corrupting assignment — stop: 3
Executing line 9 advances to line 10. The base: 2 delta records item changing
from 4096 to 4095. Measured on the exact string below using DEA's wire token
counter: cl100k_base: 177 tokens; o200k_base: 179 tokens.
{"at":{"file":"E:\\Projects\\stars\\demos\\python_offbyone\\buggy.py","fn":"checksum","line":10},"base":2,"eid":6,"frames":[{"at":{"file":"E:\\Projects\\stars\\demos\\python_offbyone\\buggy.py","fn":"checksum","line":10},"i":0},{"at":{"file":"E:\\Projects\\stars\\demos\\python_offbyone\\buggy.py","fn":"<module>","line":15},"i":1}],"reason":"step","sid":"9a054a628c8d7973","stop":3,"thread":1,"type":"stop","v":1,"vars":[{"after":"4095","before":"4096","id":"thread:1/frame:2/local:item","name":"item","op":"set"}]}
Both payloads validate as CompactDebugState and round-trip through WireGuard
without changing a byte. Counts include the complete JSON payload and exclude
the MCP envelope. Both stops satisfy the 191-token budget under both encodings.
Quickstart
Requires Python 3.12+. From a checkout of this repository:
pip install -e .
dea doctor
PDB uses the standard-library debugger. Install GDB separately for native targets;
LLDB needs a Python interpreter compatible with its local Python bindings.
dea doctor reports the live runtime/session/state classes, adapter implementations,
local installation eligibility, and both loaded tokenizers. An implemented adapter
can be unavailable locally. Doctor does not launch a target or certify native support.
Connect your agent
Use the absolute Python executable from the environment where DEA is installed
in place of /absolute/path/to/python. On Windows, forward slashes work, for example
C:/Python314/python.exe. The client starts python -m dea serve and keeps that
server process alive across tool calls.
Use this MCP JSON entry with Claude Code, Cursor, or Antigravity:
{
"mcpServers": {
"dea": {
"command": "/absolute/path/to/python",
"args": ["-m", "dea", "serve"]
}
}
}
| Client | Configuration |
|---|---|
| Claude Code | Add the JSON to project .mcp.json; the dea entry may include "type": "stdio". |
| Cursor | Add it to .cursor/mcp.json; set "type": "stdio" in the dea entry. |
| Antigravity | Open Manage MCP Servers → View raw config and add it to mcp_config.json. |
| Codex | Register the same launcher with the command below; Codex stores MCP configuration in TOML rather than the JSON format above. |
codex mcp add dea -- /absolute/path/to/python -m dea serve
For Claude Code, registration can also be done from its CLI:
claude mcp add --transport stdio --scope project dea -- /absolute/path/to/python -m dea serve
Every DEA tool accepts one request object. For example, session_start takes:
{
"request": {
"backend": "pdb",
"binary_path": "/absolute/path/to/DEA/demos/python_offbyone/buggy.py"
}
}
Keep the returned session ID. Launch/continue/step acknowledgements mean the command
was accepted; use session_wait after the last event ID to observe a stop. Inspect
while stopped, follow state_page cursors for detail, and call session_terminate
when finished. Explicit expression evaluation can execute target code and resets
the affected baseline. A wait timeout leaves target execution unchanged.
Backend status
| Backend | Status | Supported flow |
|---|---|---|
| GDB | Verified on native Windows | Launch + attach/detach, MI async, conditional breakpoints, stepping, signals/watchpoint events, registers, memory, isolated target output. |
| PDB | Verified on native Windows / Python 3.14 | Launch, conditional breakpoints, stepping, locals, evaluation, exceptions, cooperative interruption, stdout/stderr isolation. |
| LLDB | Adapter & helper implemented; requires local lldb Python bindings |
Async listener, launch/attach, frames, values, registers, and memory. Helper/protocol tests pass; native LLDB verification requires a compatible local installation. |
Recorded native coverage is Windows with CPython 3.14.6 and GDB 17.2. Linux and macOS are target platforms; their native integrations are not claimed as verified by this Windows run. See GDB coverage, PDB coverage, and LLDB coverage.
For a vendor LLDB installation, set DEA_LLDB_PYTHON to its compatible interpreter
and, if needed, DEA_LLDB_MODULE_PATH to the directory containing the lldb
package. ABI initialization runs outside the MCP interpreter during session startup.
Check session_capabilities after startup before requesting registers or memory.
Sessions live for the MCP server's lifetime. Owned processes are contained and reaped; attached targets are detached. PDB attach/registers/raw memory, interactive target terminal input, remote debugging, reverse execution, and automatic source patching are outside the current public debugging flow.
Try the 10,000-item off-by-one benchmark
The included Python demo silently undercounts a checksum. It has no exception or useful stack trace, no randomness, and no timing dependence:
python demos/python_offbyone/buggy.py
# 49994999
python demos/python_offbyone/fixed.py
# 49995000
Connect an agent to DEA and give it this task:
Use DEA's PDB backend to debug
demos/python_offbyone/buggy.pyusing its absolute path. The expected checksum is 49,995,000. Find the first incorrect item using a conditional breakpoint and captured locals. Evaluate a focused expression, step over the suspicious assignment, and show the compact delta that proves the bug. Terminate the session. Apply the smallest source fix with your editor, then run the program and compare it with the separate fixed reference. Establish the cause before readingfixed.py.
For a guided reproduction, set a conditional breakpoint on item = index - 1
with index == 4096 (the 4097th iteration). Inspect index, item, and total;
evaluate item - index, await the baseline recapture, then step over. The item
delta from 4096 → 4095 reveals the corruption. The expected fix is documented
in the demo README, separately from its program source.
Run the same flow as executable integration checks, including the real MCP stdio client/server path:
pip install -e ".[dev]"
python -m pytest tests/integration/test_pdb_python_offbyone.py tests/gateways/test_stdio_pdb_python_offbyone.py -q
This is a deterministic correctness/debugging benchmark; it makes no agent speed, cost, or solve-rate claim.
Validate the release
python -m dea.contracts.ownership
python -m pytest -q -ra
The suite covers contracts, bounded process I/O, lifecycle races, snapshot history, dual-tokenizer packing, adapters, process cleanup, and real MCP/PDB integration. Unavailable native prerequisites produce explicit skips. Passing API doubles is not evidence that a missing native debugger works.
Architecture · Frozen API specification · Work-package ownership · Python integration coverage
DEA MCP questions
What debuggers does DEA support?
DEA provides control over GDB, LLDB, and PDB.
How does DEA help with context window limits?
Instead of sending large raw debugger dumps, DEA sends delta-compressed JSON containing only changed registers and variables.