dosbox-mcp

dosbox-mcp is an MCP server that connects any MCP-capable agent runtime to a running dosbox-automation instance — typing into DOS programs, reading the screen, capturing frames and video, running sandboxed Lua, inspecting memory, driving a full headless debugger. This page is a developer-facing map of every tool this bridge actually registers right now, generated straight from the tool definitions in dosbox_mcp/tools/*.py — not a pitch.

This repo is VorticonCmdr's fork of upstream dosbox-automation/dosbox-mcp, adding the debugger, Ghidra address-mapping, symbols, batch, and wait_for tool groups documented below; it drops upstream's mixer tools. It's built against VorticonCmdr's dosbox-automation fork, not upstream's dosbox-automation — most of the tools here need REST routes upstream doesn't have. For this fork's code, the repo; for the wire contract, PROTOCOL.md.

Quick start

Point an MCP client at a running (or spawnable) emulator.

# 1. enable the API on a running dosbox-automation instance
dosbox --set webserver_enabled=true

# 2. add the bridge to your MCP client (Claude Code)
claude mcp add dosbox -- uvx --from vorticoncmdr-dosbox-mcp dosbox-mcp

# or a JSON MCP config:
# { "mcpServers": { "dosbox": { "command": "uvx", "args": ["--from", "vorticoncmdr-dosbox-mcp", "dosbox-mcp"] } } }
# pipx install vorticoncmdr-dosbox-mcp / pip install vorticoncmdr-dosbox-mcp work too
# (published under this name to avoid colliding with upstream's own "dosbox-mcp" package)

# 3. that's it - the bridge finds the running emulator, checks what it
#    can do, and registers the matching tools
#    ask your agent for bridge_status, or bridge_start to spawn one itself

Configuration

Optional. dosbox-mcp setup --init writes a commented config file; dosbox-mcp setup (no flags) prints the effective config as JSON; dosbox-mcp probe validates it end-to-end.

SettingDefaultPurpose
binaryunsetPath to the dosbox binary bridge_start spawns. Human-edited only.
port8386Webserver port on 127.0.0.1, used both to connect and to configure a spawned instance.
headlessfalseSpawn without a window (SDL dummy video driver).
protocolnegotiates highestPin the bridge to a lower protocol version, e.g. "1.0".
modefullCapability mode: observe (read-only), interact (+ input, video capture, scripts, lifecycle), full (+ memory writes, port I/O, register writes, debugger). Human-edited only.
token_fileengine defaultToken file of an already-running instance to attach to.
mount_allowed_basesemptyUp to 5 absolute host directories a spawned instance may let drive_mount mount. Human-edited only.
mount_allowed_image_rootsemptySame mechanism for drive_swap's disk-image source roots.

Environment variable overrides

VariablePurpose
DOSBOX_API_URLTarget base URL (loopback only: 127.0.0.1, ::1, or localhost).
DOSBOX_API_TOKENBearer token by value (a token file is preferred).
DOSBOX_TOKEN_FILEOverride where the bridge reads the token from.
DOSBOX_MCP_CONFIGOverride the config file path.
DOSBOX_MCP_GHIDRA_MAPOverride where Ghidra address-mapping state persists.

The bridge talks to loopback addresses only; it will not reach out to a remote machine.

Tools

All 85 tools this bridge can register, extracted from every add_tool(...) call in dosbox_mcp/tools/*.py — how many an agent actually sees depends on mode and what the attached engine build supports. Read-only tools are safe to auto-approve.

ToolR/WCategoryFeatureDescriptionExample

Pairs with Ghidra for reverse engineering

The Debugger tools (execution control: pause/step/continue and breakpoints) plus Ghidra address mapping and Symbols let an agent combine this bridge with a separate Ghidra MCP server: analyze a program statically in Ghidra, then set breakpoints and interpret a paused CPU state against the exact same addresses live in DOSBox.

Address mapping is pure arithmetic

debug_map_set_base and friends never talk to Ghidra or the engine — they translate addresses once anchored at one known correspondence point (usually the entry point). Exact for .COM programs and single-segment .EXE programs.

The .COM 0x100 offset

Ghidra's real-mode loader can't rebase a .COM import to a segment:0x0100 layout, so it typically lands at 0000:0000 — a constant 0x100 below every live address. Anchoring absorbs that automatically.

Symbols follow you everywhere

Once loaded via debug_symbols_load, a symbol field appears on disassembly, debugger stop records, backtrace frames, and the DOS memory map.