Skip to main content
Glama

Aragorn

Direct kernel debugger MCP server for Windows security research. Attaches to a Windows VM kernel in-process via IDebugClient5::AttachKernelWide (no kd.exe subprocess) and exposes 72 tools over the Model Context Protocol.

This process is the debugger. There's no WinDbg GUI and no kd.exe in the loop — Aragorn loads dbgeng.dll directly via ctypes COM and drives the kernel attach itself (direct transport, the default). A legacy kd_server transport that shells out to kd.exe is kept as a fallback. Either way you get full DbgEng COM access — memory, registers, breakpoints, symbols, events — exposed as MCP tools.

MCP Client ──stdio/http──► Aragorn ──┬─► (direct, default)  AttachKernelWide ──► VM kernel
                                      └─► (kd_server)        DebugConnect(TCP) ──► kd.exe ──► VM kernel

The net:port=…,key=…,target=… connection string is the standard Windows kernel-debug network (kdnet) format — that's the wire protocol, not the transport. Both direct and kd_server use it.

Architecture

Aragorn runs as a two-process system:

  • Supervisor — the MCP server that talks to your client. Stays alive across debugger crashes/wedges.

  • Worker — a child Python subprocess that owns dbgeng.dll and the kernel connection.

The worker exists because dbgeng.dll enforces a one-direct-attach-per-process limit. After a wedge or a transport reset, the only reliable fix is a fresh process. Doing that in a worker means the supervisor (and your MCP pipe) keeps running. restart_worker() kills and respawns the worker — your client never has to reconnect.

Each multi-session debugger instance gets its own dedicated COM thread (DbgEng has thread affinity), and all blocking COM calls are wrapped in asyncio.to_thread() so the MCP stdio loop stays responsive.

Related MCP server: procmem

Quick Start

# 1. Install dependencies
pip install -r requirements.txt

# 2. Drop DbgEng DLLs into dbgeng_bin/ (see "DbgEng Binaries" below)

# 3. Configure
cp .env.example .env
# Edit .env: set KD_CONNECTION, KD_EXE_PATH, etc.

# 4. Run (stdio mode — for MCP clients like Claude Code)
python server.py

# Or HTTP mode (for remote/shared access)
python server.py --http

.mcp.json integration

{
  "aragorn": {
    "type": "stdio",
    "command": "python",
    "args": ["path/to/Aragorn/server.py"]
  }
}

Configuration

All settings are via environment variables (or .env file):

Variable

Default

Description

KD_CONNECTION

net:port=55555,key=...,target=...

kdnet connection string

KD_EXE_PATH

WinDbg Preview's kd.exe

Path to kd.exe (only used by kd_server transport)

KD_SERVER_PORT

14500

Local TCP port for kd.exe debug server

ARAGORN_TRANSPORT

direct

direct (in-process AttachKernel) or kd_server (legacy)

KD_SYNC_TIMEOUT_MS

30000

First WaitForEvent timeout after AttachKernel

INITIAL_BREAK_TIMEOUT_MS

10000

SetInterrupt timeout when initial_break=True

DBGENG_PATH

./dbgeng_bin/dbgeng.dll

Path to DbgEng DLL

SYMBOL_PATH

Microsoft symbol server

Symbol search path

ARAGORN_HOST

127.0.0.1

HTTP mode bind address

ARAGORN_PORT

14401

HTTP mode port

VM_AGENT_URL

http://YOUR_VM_IP:8080

VM agent URL (for workflow tools)

VM_AGENT_API_KEY

(empty)

VM agent API key

DbgEng Binaries

The dbgeng_bin/ directory is gitignored. Copy these DLLs from your WinDbg Preview installation:

C:\Program Files\WindowsApps\Microsoft.WinDbg_*\amd64\
  ├── dbgeng.dll
  ├── dbghelp.dll
  ├── dbgmodel.dll
  ├── dbgcore.dll
  ├── symsrv.dll
  └── srcsrv.dll

VM Agent

The vm_agent/ directory contains a lightweight Flask server that runs inside the target VM. It exposes process execution, file I/O, and driver service management over HTTP. Aragorn's workflow tools (breakpoint_and_run, vm_exec, etc.) use it to coordinate kernel debugging with VM-side actions.

# On the VM:
cd vm_agent
pip install -r requirements.txt
cp .env.example .env
# Edit .env: set VM_AGENT_API_KEY
python server.py

The VM agent is optional — all pure debugger tools work without it. You only need it for the coordinated workflow tools.

Tools

Session & Connection (12)

Tool

Description

connect

Connect to kernel debugger (in-process AttachKernel by default)

disconnect

Cleanly disconnect

status

Get connection state and config

target_info

Get debug target info (class, processors, page size)

ensure_ready

Atomic: break in, verify thread context, reload symbols (retries 5x)

health_check

Lightweight probe without breaking into target

restart_worker

Kill the worker subprocess and spawn a fresh one (use after wedge)

reset_engine

Soft reset of the in-process engine state

reconnect_debugger

Force full reconnect

test_kd_connection

Diagnostic kd.exe connection test

get_debugger_state

Full tracked state for cross-agent coordination

resolve_vm_target

Resolve a Hyper-V VM name to its current IPv4 + update KD_CONNECTION

Multi-Session (6)

Run multiple isolated debugger sessions in one Aragorn process — one per VM. Each gets its own kd.exe / COM thread / state. Tools take an optional session_id; the active session is used if omitted.

Tool

Description

session_create

Create an isolated debugger session for a VM

session_connect

Connect a session's debugger

session_disconnect

Disconnect without destroying

session_destroy

Destroy and clean up a session

session_list

List all sessions with status

session_set_active

Set the active session for tool routing

Command Execution (3)

Tool

Description

execute

Execute raw debugger command (e.g., lm, !process 0 0)

execute_batch

Execute multiple commands sequentially

evaluate

Evaluate an expression, return numeric value

Memory (7)

Tool

Description

read_memory

Read virtual memory (hex / qwords / dwords / ascii)

write_memory

Write bytes to virtual memory

search_memory

Search for byte pattern

read_physical

Read physical memory

write_physical

Write to physical memory

virtual_to_physical

Translate virtual to physical address

read_msr

Read Model-Specific Register

Registers (2)

Tool

Description

read_registers

Read all general-purpose registers

write_register

Write a register value

Stack (1)

Tool

Description

get_stack

Structured stack trace with symbols

Breakpoints (4)

Tool

Description

set_breakpoint

Set code, data, or hardware breakpoint (with optional MASM .if condition)

remove_breakpoint

Remove breakpoint by ID

list_breakpoints

List all breakpoints with status

set_exception_filter

Configure exception handling (break / ignore / output)

Execution Control (4)

Tool

Description

continue_exec

Resume execution (robust — drains spurious kdnet breaks, retries up to 10x)

step_into

Single-step into calls

step_over

Single-step over calls

break_in

Interrupt running target

Inspection (4)

Tool

Description

list_modules

List loaded modules with base / size / name

list_threads

List threads with engine / system IDs

list_processes

List processes with engine / system IDs

switch_process

Switch to process context (.process /i)

Symbols (4)

Tool

Description

resolve_symbol

Bidirectional symbol / address resolution

get_field_offset

Struct field byte offset

get_type_size

Type size in bytes

disassemble

Disassemble instructions at address

Events (3)

Tool

Description

wait_for_event

Block until next debug event

poll_events

Return queued events without blocking

clear_events

Discard all queued events

Kernel Objects (8)

Tool

Description

read_struct

Read typed structure (dt equivalent)

get_pte

Page table entry info

pool_info

Pool allocation metadata

get_driver_object

Driver object + dispatch table

get_device_objects

Device object info

get_object_info

Kernel object from object directory

dump_ssdt

System Service Descriptor Table

get_idt

Interrupt Descriptor Table

Structured Context (6)

One-shot context dumps via direct COM (no Execute() text parsing). Safe to call any time the target is broken in.

Tool

Description

get_cpu_state

All GPRs + control regs + execution status in one call

disasm_at

Disassemble at address with structured output

read_qwords

Read N qwords with symbol resolution per slot

get_current_process

Current _EPROCESS summary (image name, PID, etc.)

get_current_thread

Current _ETHREAD summary

get_full_context

Combined CPU + process + thread + module snapshot

Workflow (8)

Coordinated debugger + VM operations. Require a running VM agent.

Tool

Description

breakpoint_and_run

Atomic: set BP, resume, run VM command, wait for hit, capture state

run_and_trace

Set logging BPs at multiple addresses, run command, capture trace

inspect_at_breakpoint

Batch post-breakpoint inspection commands

vm_exec

Execute command on VM

vm_read_file

Read file from VM

vm_write_file

Write file to VM

vm_upload_file

Upload file from host to VM

vm_status

Check VM reachability

Conditional breakpoints

Aragorn passes MASM .if conditions through to dbgeng natively:

set_breakpoint(
    expression="<module>!<function>",
    condition=".if (poi(@rcx+0x10) == 0x1234) {} .else {gc}",
)

Two non-obvious gotchas (each one looks like a "spurious break" until you find it):

  • Use bitwise & and |, not logical && / ||. .if (1 && 0) returns HRESULT 0x80040205; the engine falls back to its default action (break). Bitwise & / | work correctly on the 0/1 booleans that == produces.

  • Inline all reads. Don't try to cache subexpressions with r @$tN=expr. The pseudo-register assignment also triggers fallback-to-break.

See Claude-Docs/SKILL.md for the full breakpoint playbook (rate-budget reasoning, JS predicates via bp /w, validation workflow, common patterns).

Layout

Aragorn/
├── server.py             # FastMCP entry point, registers all tool modules
├── supervisor.py         # Owns the worker subprocess; survives crashes
├── worker.py             # Child process that owns dbgeng + COM state
├── debugger.py           # High-level Debugger class (lifecycle, commands, reconnect)
├── dbgeng.py             # Pure ctypes COM interface definitions (6 interfaces)
├── callbacks.py          # IDebugOutputCallbacks + IDebugEventCallbacks
├── sessions.py           # Multi-session registry (parallel VM debugging)
├── vm_client.py          # Async HTTP client to VM agent
├── config.py             # Environment-variable configuration
├── bp_helpers.js         # JS predicates for `bp /w` conditional breakpoints
├── start_engine.bat      # Launch HTTP-mode server (must be admin)
├── dbgeng_bin/           # DbgEng DLLs (gitignored, ~15MB)
├── vm_agent/             # REST agent for the target VM (Flask + psutil)
│   ├── server.py
│   └── requirements.txt
├── Claude-Docs/
│   └── SKILL.md          # Skill for kernel debug-assisted tracing
├── tests/
│   └── test_supervisor_methods_present.py
└── tools/
    ├── _state.py         # State-snapshot wrapper applied to every tool
    ├── core.py           # execute, execute_batch, evaluate
    ├── session.py        # connect, disconnect, status, ensure_ready, restart_worker, ...
    ├── multi_session.py  # session_create / connect / destroy / list
    ├── memory.py         # read/write virtual + physical memory, MSR
    ├── registers.py      # read/write registers
    ├── stack.py          # get_stack
    ├── breakpoints.py    # set/remove/list breakpoints, exception filters
    ├── execution.py      # continue, step_into, step_over, break_in
    ├── inspection.py     # list modules/threads/processes, switch context
    ├── symbols.py        # resolve symbols, field offsets, disassemble
    ├── events.py         # wait/poll/clear debug events
    ├── kernel.py         # read_struct, PTE, pool, driver/device objects, SSDT, IDT
    ├── context.py        # one-shot structured context dumps via direct COM
    └── workflow.py       # breakpoint_and_run, run_and_trace, VM proxy tools

COM Interface Stack

Aragorn wraps six DbgEng COM interfaces via ctypes (no C++ extension needed):

  • IDebugClient — Session lifecycle, callback registration

  • IDebugControl — Command execution, breakpoints, execution status

  • IDebugDataSpaces2 — Virtual / physical memory, address translation

  • IDebugRegisters — Register read / write

  • IDebugSymbols2 — Symbol resolution, type info, disassembly

  • IDebugSystemObjects — Process / thread / module enumeration

License

WTFPL

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for controlling a Windows guest VM over WinRM, enabling PowerShell/CMD execution, file transfer, reboot, and KDNET debug configuration, typically paired with kd-mcp.
    12
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server for Windows process memory inspection/editing and crash dump analysis, enabling live memory scanning, patching, pointer resolution, disassembly, and offline dump examination via structured tool calls.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for reverse engineering Windows executables and related binary formats, offering static analysis, Ghidra-assisted function recovery, plugin-driven tooling, and optional isolated Windows runtime execution.
    3 npm
    242
    MIT