Skip to main content
Glama

mcp-mgba

npm version npm downloads CI License: MIT Snyk Socket Bundlephobia npmgraph

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

Related MCP server: PokeMCP

Requirements

  • mGBA 0.10 or newer (with Lua scripting)

  • Node.js 22+ (for the MCP server)

Install

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:

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):

{
  "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

Install Server
A
license - permissive license
A
quality
A
maintenance

Maintenance

Maintainers
7dResponse time
2dRelease cycle
4Releases (12mo)
Commit activity
Issues opened vs closed

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    A
    quality
    F
    maintenance
    Enables AI assistants to play Pokemon Fire Red through the mGBA emulator by providing tools for button inputs and screenshots. It allows for direct reading of real-time game state from RAM, including party information, player location, and battle status.
    Last updated
    10
    3
  • A
    license
    A
    quality
    A
    maintenance
    MCP server for PCSX2 and other emulators that speak the PINE protocol. Read and write 8/16/32/64-bit emulator memory and control save states for PlayStation-family emulation.
    Last updated
    14
    15
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    MCP server for RetroArch via its Network Control Interface. Drive any libretro core — read/write memory, save/load state, screenshot, pause/frame-advance/reset — across NES, SNES, Genesis, N64, GBA, PS1 and more.
    Last updated
    17
    18
    2
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

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