mcp-mgba
mcp-mgba
A headless GBA debugger MCP server: it lets an LLM (or any MCP client) load
a Game Boy Advance ROM, step it instruction-by-instruction, read/write
memory, and manage breakpoints/watchpoints/registers — all with zero GUI
toolkit dependency (no X server, no Qt, no SDL window). Under the hood it's
built on mGBA's core emulation library (libmgba),
built headless.
Prerequisites
cmake, a C compiler (gcc/clang), andmake— for building the native shim.Node.js
>=18and npm.
Setup
git submodule update --init --recursive # first time only
native/build.sh # build the native shim
npm install
npm run build # tsc -> dist/Running
npm start # runs dist/index.js over stdio
# or, for local development without a build step:
npm run dev # runs src/index.ts directly via tsxPoint any MCP client at the built server to drive it interactively, e.g.:
npx @modelcontextprotocol/inspector node dist/index.jsBy default the server locates its native shim next to itself
(native/build/<platform>/ in a checkout, or prebuilt/<platform>/ in a
published install). Set MCBAMGBA_SHIM_PATH to point it at a shim built
elsewhere instead.
Tools
Tool | Description |
| Loads a GBA ROM from an absolute path, replacing any ROM already loaded, and resets to its entry point. Required before any other tool. |
| Resets the currently loaded ROM back to its entry point. |
| Executes a single CPU instruction. |
| Advances execution by |
| Reads |
| Writes a hex-encoded byte string into GBA-mapped memory starting at |
| Holds one or more of the GBA's 10 buttons ( |
| Captures the current 240x160 frame as a PNG image. |
| Snapshots the current point in execution as an opaque, base64-encoded blob (never interpreted by the server) that |
| Restores emulator state from a blob previously returned by |
| Sets a hardware breakpoint at |
| Removes the breakpoint with the given |
| Lists every breakpoint currently set. |
| Sets a watchpoint at |
| Removes the watchpoint with the given |
| Lists every watchpoint currently set. |
| Reads the full CPU register set ( |
| Writes a single register by name (e.g. |
| Runs forward (single-stepping internally, one blocking call) until a breakpoint or watchpoint fires, or a safety |
| Decodes |
Every tool other than load_rom fails with a structured [NO_ROM_LOADED]
error if called before a ROM is loaded. clear_breakpoint,
clear_watchpoint, and set_register fail with a structured [NOT_FOUND]
error if given an id/register name that doesn't exist.
The server is fully synchronous/pull-based — every tool call blocks and returns a definitive result — and supports a single loaded ROM/session at a time.
License
MPL-2.0 — see LICENSE. Built on mGBA's
libmgba (also MPL-2.0), vendored as a git submodule and statically
linked into the compiled native shim this package distributes. See
NOTICE for the exact vendored tag/commit.