Featured

Deploy OpenClaw in 60 seconds β€” 20% off logoDeploy OpenClaw in 60 seconds β€” 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger β†’
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger β†’
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free β†’
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free β†’
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data β€” no proxies, no parsers, no maintenance.

Start building free β†’
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it β€” secured from day one.

Get it set up for you β†’
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free β†’
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here β†’

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

dmang-dev/mcp-mgba MCP server](https://glama.ai/mcp/servers/dmang-dev/mcp-mgba/badges/score.svg)](https://glama.ai/mcp/servers/dmang-dev/mcp-mgba) πŸ“‡ 🏠 🍎 πŸͺŸ 🐧 - Drive the mGBA Game Boy Advance emulator from any MCP client: read/write GBA memory, inject...

README.md

mcp-mgba

![npm version](https://www.npmjs.com/package/mcp-mgba) ![npm downloads](https://www.npmjs.com/package/mcp-mgba) ![CI](https://github.com/dmang-dev/mcp-mgba/actions/workflows/ci.yml) ![License: MIT](LICENSE) ![Snyk](https://snyk.io/test/npm/mcp-mgba) ![Socket](https://socket.dev/npm/package/mcp-mgba) ![Bundlephobia](https://bundlephobia.com/package/mcp-mgba) ![npmgraph](https://npmgraph.js.org/?q=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.

!demo

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 8765
  • dist/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 22+ (for the MCP server)

Install

Option A β€” install from npm (recommended)

npm install -g mcp-mgba

Puts 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-mgba

Run 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` hook

Then reference the absolute path to dist/index.js when registering, or npm install -g . to symlink the bin globally.

Set up the mGBA bridge

  1. Launch mGBA and load any GBA ROM.
  2. Open Tools > Scripting…
  3. Click File > Load script and select lua/bridge.lua from 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 active ``

If 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: ```bash claude mcp list

mgba: mcp-mgba - βœ“ Connected


### Claude Desktop

Edit `claude_desktop_config.json`:

| Platform | Path |
|---|---|
| macOS    | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows  | `%APPDATA%\Claude\claude_desktop_config.json` |
| Linux    | `~/.config/Claude/claude_desktop_config.json` |

Add (assuming Option A β€” globally installed):

{ "mcpServers": { "mgba": { "command": "mcp-mgba" } } } ```

Or with explicit Node + path (Option B): ``json { "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 | |-------------|---------------|------------------------| | MGBA_HOST | 127.0.0.1 | Bridge host to dial | | MGBA_PORT | 8765 | Bridge port to dial |

Tools

| Tool | Description | |------|-------------| | mgba_ping | Verify bridge connectivity (returns pong) | | mgba_get_info | Game title, code, frame count | | mgba_read8 / mgba_read16 / mgba_read32 | Read memory at an address | | mgba_write8 / mgba_write16 / mgba_write32 | Write to RAM | | mgba_read_range | Read up to 4096 bytes as a byte array | | mgba_write_range | Write up to 4096 bytes from a byte array | | mgba_press_buttons | Queue a button press (FIFO; consecutive calls produce distinct events) | | mgba_advance_frames | Step the emulator N frames | | mgba_pause / mgba_unpause | Pause / resume emulation | | mgba_reset | Reset the loaded ROM | | mgba_screenshot | Save a PNG of the current display | | mgba_save_state / mgba_load_state | 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 | |----------------|-------------------------------| | 0x02000000 | EWRAM (256 KiB, general) | | 0x03000000 | IWRAM (32 KiB, fast) | | 0x04000000 | I/O registers | | 0x05000000 | Palette RAM | | 0x06000000 | VRAM | | 0x07000000 | OAM | | 0x08000000 | ROM (read-only) |

Troubleshooting

| Symptom | Cause / Fix | |---|---| | Cannot reach mGBA bridge at 127.0.0.1:8765 | mGBA isn't running, or bridge.lua isn't loaded β€” open Tools > Scripting and load it | | bind failed β€” port 8765 may already be in use | 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 bridge.lua and choosing Load Script again | mGBA doesn't fully tear down a previous script when you reload. The new script's bind() may succeed but the old frame callback keeps serving requests. Fix: quit mGBA entirely, relaunch, load the ROM, then load bridge.lua once. Check the console for the frame callback registered line β€” there should be exactly one. | | attempt to index a nil value (global 'emu') at script load | mGBA's emu global only exists once a ROM is loaded. Load any ROM first, then load bridge.lua. (Or load the script first; capability detection will defer until a ROM is loaded.) | | emu:foo not available on this mGBA build for pause, unpause, frameAdvance, etc. | This particular build of mGBA doesn't expose that method. The bridge feature-detects on the first frame; check mgba_get_info for the full capabilities map. For frameAdvance, the bridge falls back to runFrame then step automatically. | | read8/16/32 returns "invoking failed" intermittently | Known mGBA Lua quirk β€” the typed read methods are flaky via pcall from the frame callback. The bridge already routes read8/16/32 through the more reliable readRange internally; if you still see this on a write, the retry loop usually clears it within a few attempts. | | Multiple press_buttons calls don't seem to register as distinct events | Older mgba_press_buttons (≀0.1.0) had this bug; v0.2.0+ uses a FIFO queue. Make sure you've upgraded with npm install -g mcp-mgba and restarted your MCP client. |

Development

npm install
npm run dev      # tsc --watch β€” autobuilds on src/ changes

The Lua side (lua/bridge.lua and lua/json.lua) needs no build step. Edit and reload via mGBA's File > Load script.

Debugging with the MCP Inspector

Browse and call this server's tools interactively with the MCP Inspector:

npm run inspector

Build first if you've edited src/ since your last npm install (npm run build, or keep npm run dev running). Override the bridge address with MGBA_HOST / MGBA_PORT (default 127.0.0.1:8765). tools/list works even without mGBA connected; calling a tool needs mGBA open with lua/bridge.lua loaded.

License

MIT

See related servers & alternatives β†’

Related MCP servers

Browse all β†’

Related guides

Hand-picked reading to help you choose and use Vector & Memory servers.