mcdosbox-x/README.md
Ryan Malloy 79c646cf87 Add comprehensive documentation for MCP server
- 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
2026-01-27 15:26:22 -07:00

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-remotedebug build 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

License

MIT License