- Update README.md with accurate lokkju fork info and troubleshooting - Add CLAUDE.md development guide for future sessions - Document GDB protocol details, architecture, and common issues
8.9 KiB
DOSBox-X MCP Server
AI-assisted debugging of DOS binaries via the Model Context Protocol (MCP).
This MCP server enables Claude to programmatically debug DOS programs running in DOSBox-X by providing tools for:
- Setting breakpoints and tracing execution
- Reading/writing CPU registers and memory
- Disassembling code at any address
- Step-by-step instruction execution
Primary Use Case
Reverse engineering classic DOS programs — specifically, tracing the unpublished Bezier curve algorithm in RIPTERM.EXE for the RIPscrip graphics protocol research project.
Quick Start
Prerequisites
- Python 3.11+
- uv package manager
- Docker and Docker Compose
- X11 display (for DOSBox GUI) or use headless mode
Installation
# Clone the repository
git clone https://github.com/ryanmalloy/dosbox-mcp.git
cd dosbox-mcp
# Install dependencies
uv sync
# Build Docker image (uses lokkju/dosbox-x-remotedebug fork)
docker compose build
# Create DOS directory for your binaries
mkdir -p dos
Running
# Allow X11 access for Docker (Linux)
xhost +local:docker
# Start DOSBox-X with GDB server
docker compose up -d
# Verify GDB port is listening
nc -zv localhost 1234
# View logs
docker compose logs -f
Register with Claude Code
# Add to Claude Code
claude mcp add dosbox-mcp -- uv run --directory /path/to/dosbox-mcp dosbox-mcp
# Verify registration
claude mcp list
Usage with Claude
Once registered, Claude can debug DOS binaries:
# Connect to the running DOSBox-X GDB server
attach("localhost", 1234)
# Read current CPU state
registers()
# Read memory at CS:IP
memory_read("CS:IP", 64)
# Set a breakpoint at the boot sector
breakpoint_set("0x7C00")
# Continue execution until breakpoint
continue_execution()
# Step through instructions
step(10)
# Disassemble at current location
disassemble("CS:IP", 20)
# Disconnect when done
quit()
Tools Reference
Execution Control (6 tools)
| Tool | Description |
|---|---|
launch |
Start DOSBox-X container with optional binary |
attach |
Connect to GDB stub at host:port |
continue_execution |
Run until breakpoint or signal |
step |
Step N instructions (default: 1) |
step_over |
Step over CALL instructions |
quit |
Disconnect and optionally stop DOSBox-X |
Breakpoints (3 tools)
| Tool | Description |
|---|---|
breakpoint_set |
Set software breakpoint at address |
breakpoint_list |
List all active breakpoints |
breakpoint_delete |
Remove breakpoint by ID or all |
Inspection (6 tools)
| Tool | Description |
|---|---|
registers |
Read all CPU registers (32-bit, 16-bit, segments, flags) |
memory_read |
Read memory in hex/ASCII/dump format |
memory_write |
Write hex or ASCII data to memory |
disassemble |
Disassemble instructions with opcode hints |
stack |
Dump stack contents from SS:SP |
status |
Get debugger connection status |
Peripheral (2 tools — stubs)
| Tool | Description |
|---|---|
screenshot |
Capture DOSBox-X display (not yet implemented) |
serial_send |
Send data to serial port (not yet implemented) |
Address Formats
The server supports multiple address formats:
| Format | Example | Description |
|---|---|---|
| Segment:offset | 1234:5678 |
Standard DOS format |
| Flat hex | 0x12345 or 12345 |
Physical address |
| Decimal | #65536 |
Decimal address |
| Register-based | CS:IP, DS:SI |
Uses current register values |
Architecture
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Claude Code │────▶│ DOSBox-X MCP │────▶│ DOSBox-X │
│ │ MCP │ Server │ GDB │ Container │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
FastMCP 2.x GDB Remote lokkju/dosbox-x-
(stdio) Protocol remotedebug fork
(TCP :1234) (--enable-remotedebug)
Why lokkju/dosbox-x-remotedebug?
Mainline DOSBox-X doesn't include a GDB server. The lokkju/dosbox-x-remotedebug fork adds:
--enable-remotedebugbuild flag- GDB server on port 1234 (configurable)
- QMP server on port 4444 for machine control
- Config options in
[dosbox]section:gdbserver=true,gdbserver port=1234
Project Structure
dosbox-mcp/
├── src/dosbox_mcp/
│ ├── server.py # FastMCP server entry point
│ ├── gdb_client.py # GDB Remote Serial Protocol client
│ ├── dosbox.py # DOSBox-X process/container management
│ ├── state.py # Shared global state (manager, client)
│ ├── types.py # Type definitions (Registers, Breakpoint, etc.)
│ ├── utils.py # Address parsing, format conversion
│ └── tools/ # MCP tool implementations
│ ├── execution.py # launch, attach, continue, step, quit
│ ├── breakpoints.py # breakpoint_set, list, delete
│ ├── inspection.py # registers, memory, disassemble, stack
│ └── peripheral.py # screenshot, serial (stubs)
├── tests/ # pytest test suite
├── config/
│ └── dosbox.conf # DOSBox-X configuration with GDB enabled
├── dos/ # Mount point for DOS binaries
├── Dockerfile # Multi-stage build for dosbox-x-remotedebug
├── docker-compose.yml # Container orchestration
└── pyproject.toml # Python package definition
Configuration
DOSBox-X Config (config/dosbox.conf)
[dosbox]
memsize=16
gdbserver=true
gdbserver port=1234
qmpserver=true
qmpserver port=4444
[autoexec]
MOUNT C /dos
C:
Environment Variables (.env)
GDB_PORT=1234 # Host port for GDB
QMP_PORT=4444 # Host port for QMP
DOS_DIR=./dos # DOS files mount point
CONFIG_FILE=./config/dosbox.conf
Development
# Run tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=dosbox_mcp
# Lint code
uv run ruff check src/
# Format code
uv run ruff format src/
# Type check (optional)
uv run mypy src/
Technical Details
GDB Remote Serial Protocol
The server implements a client for the GDB Remote Serial Protocol:
| Command | Description |
|---|---|
qSupported |
Capability negotiation (handshake) |
g / G |
Read/write all registers |
p / P |
Read/write single register |
m / M |
Read/write memory |
Z0 / z0 |
Set/clear software breakpoint |
c / s |
Continue / step |
? |
Query stop reason |
Packets use format: $<command>#<2-digit checksum>
Real Mode Addressing
DOS uses real mode with segment:offset addressing:
Physical Address = (Segment << 4) + Offset
This gives a 20-bit address space (1MB). The Registers class provides helpers like cs_ip and ss_sp for common address calculations.
Troubleshooting
GDB Connection Refused
# Check if container is running
docker ps | grep dosbox
# Check if GDB port is listening
docker exec dosbox-mcp nc -zv localhost 1234
# Check logs for GDB server startup
docker logs dosbox-mcp 2>&1 | grep -i gdb
Container Shows "unhealthy"
The healthcheck uses nc which may not be installed in the slim image. This is cosmetic — the GDB server still works. To fix, add netcat-openbsd to the Dockerfile runtime stage.
X11 Display Issues
# Allow Docker X11 access
xhost +local:docker
# Or use headless mode
docker compose --profile headless up -d dosbox-headless
Related Projects
- RIPscrip Research (rpmesh) — Parent project
- lokkju/dosbox-x-remotedebug — DOSBox-X fork with GDB
- FastMCP — MCP server framework
- GDB Remote Protocol
License
MIT License