mcp-mgba
mcp-mgba
An MCP server that exposes the mGBA Game Boy Advance emulator to any MCP-compatible client (Claude Desktop, Claude Code, etc.).
Lets your model read and write GBA memory, inject button presses, take screenshots, and step the emulator — all through a clean tool interface.

Claude driving an in-development homebrew side-scroller through mgba_press_buttons — Start to begin, A to confirm New Game, then Right to walk and A to jump. Each frame is captured via mgba_screenshot.
How it works
+------------------+ stdio +------------------+ TCP :8765 +------------------+
| MCP client | JSON-RPC | mcp-mgba | newline JSON | mGBA emulator |
| (Claude / etc.) | ===========> | (Node.js) | ============> | bridge.lua |
+------------------+ +------------------+ +------------------+Two pieces:
lua/bridge.lua— runs inside mGBA's scripting engine, opens a loopback TCP server on port 8765dist/index.js— Node.js MCP server, talks to the Lua bridge over TCP, exposes tools over stdio
Requirements
mGBA 0.10 or newer (with Lua scripting)
Node.js 18+ (for the MCP server)
Install
Option A — install from npm (recommended)
npm install -g mcp-mgbaPuts mcp-mgba on your PATH. Verify with mcp-mgba --help (it'll print a startup line and wait for stdio — Ctrl+C to exit).
Option B — npx (no install)
npx -y mcp-mgbaRun on demand. Good for trying it out without committing to a global install.
Option C — clone and develop
git clone https://github.com/dmang-dev/mcp-mgba
cd mcp-mgba
npm install # also runs the build via the `prepare` hookThen reference the absolute path to dist/index.js when registering, or npm install -g . to symlink the bin globally.
Set up the mGBA bridge
Launch mGBA and load any GBA ROM.
Open Tools > Scripting…
Click File > Load script and select
lua/bridge.luafrom this repo.
You should see in the scripting console:
[mcp-mgba] bridge listening on 127.0.0.1:8765
[mcp-mgba] frame callback registered — bridge is activeIf you see a bind failed error, the previous instance's socket is still held — quit and relaunch mGBA.
Register with your MCP client
Claude Code (CLI)
claude mcp add mgba --scope user mcp-mgba(if you used Option B without global install, replace mcp-mgba with node /absolute/path/to/dist/index.js)
Verify:
claude mcp list
# mgba: mcp-mgba - ✓ ConnectedClaude Desktop
Edit claude_desktop_config.json:
Platform | Path |
macOS |
|
Windows |
|
Linux |
|
Add (assuming Option A — globally installed):
{
"mcpServers": {
"mgba": {
"command": "mcp-mgba"
}
}
}Or with explicit Node + path (Option B):
{
"mcpServers": {
"mgba": {
"command": "node",
"args": ["/absolute/path/to/mcp-mgba/dist/index.js"]
}
}
}Restart Claude Desktop after editing.
Other MCP clients
The server speaks standard MCP over stdio. Run mcp-mgba (or node dist/index.js) and connect any MCP client to its stdio.
Configuration
Env var | Default | Purpose |
|
| Bridge host to dial |
|
| Bridge port to dial |
Tools
Tool | Description |
| Verify bridge connectivity (returns |
| Game title, code, frame count |
| Read memory at an address |
| Write to RAM |
| Read up to 4096 bytes as a byte array |
| Write up to 4096 bytes from a byte array |
| Queue a button press (FIFO; consecutive calls produce distinct events) |
| Step the emulator N frames |
| Pause / resume emulation |
| Reset the loaded ROM |
| Save a PNG of the current display |
| Save/load emulator state to a slot or path |
See docs/RECIPES.md for end-to-end examples (RAM hunting, snapshot-experiment-restore, side-scroller automation, etc.).
GBA button names
A, B, Select, Start, Right, Left, Up, Down, R, L
GBA address space (cheat sheet)
Range | Region |
| EWRAM (256 KiB, general) |
| IWRAM (32 KiB, fast) |
| I/O registers |
| Palette RAM |
| VRAM |
| OAM |
| ROM (read-only) |
Troubleshooting
Symptom | Cause / Fix |
| mGBA isn't running, or |
| A previous mGBA instance still holds the socket; quit and relaunch mGBA |
Tool calls hang | The bridge script may have errored out silently after a hot-reload — check the mGBA scripting console |
Tools missing in Claude after install | Restart your MCP client; Claude only enumerates servers on startup |
Tool calls return data shaped like an old version after editing | mGBA doesn't fully tear down a previous script when you reload. The new script's |
| mGBA's |
| This particular build of mGBA doesn't expose that method. The bridge feature-detects on the first frame; check |
| Known mGBA Lua quirk — the typed read methods are flaky via pcall from the frame callback. The bridge already routes |
Multiple | Older |
Development
npm install
npm run dev # tsc --watch — autobuilds on src/ changesThe Lua side (lua/bridge.lua and lua/json.lua) needs no build step. Edit and reload via mGBA's File > Load script.
License
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dmang-dev/mcp-mgba'
If you have feedback or need assistance with the MCP directory API, please join our Discord server