mcp-bizhawk
This server bridges MCP-compatible clients (like Claude) to the BizHawk multi-system emulator, enabling programmatic emulation control, memory inspection/manipulation, and input automation.
Connectivity & Info
bizhawk_ping— Verify bridge connectivitybizhawk_get_info— Retrieve ROM name/hash, framecount, memory domains, and capability flagsbizhawk_list_memory_domains— List available memory domains for the loaded core
Memory Reading
bizhawk_read8/16/32— Read unsigned 8-bit, 16-bit, or 32-bit (little-endian) valuesbizhawk_read_range— Read up to 4096 contiguous bytes as a hex dump
Memory Writing
bizhawk_write8/16/32— Write unsigned 8-bit, 16-bit, or 32-bit (little-endian) valuesbizhawk_write_range— Write up to 4096 bytes to a contiguous memory range
Emulation Control
bizhawk_pause/bizhawk_unpause— Freeze or resume emulationbizhawk_frame_advance— Step emulation by N framesbizhawk_reset— Hard reset the loaded core
Input & State
bizhawk_press_buttons— Set joypad button states for a player for the next framebizhawk_screenshot— Save a PNG of the current displaybizhawk_save_state/bizhawk_load_state— Save and restore full emulator state to/from files
Supported systems include NES, SNES, Game Boy/GBC/GBA, Sega Master System/Genesis/32X/Saturn, N64, PlayStation 1, Atari, Lynx, ColecoVision, and more. Requires BizHawk 2.6.2+ and Node.js 18+.
Provides tools for interacting with Atari 2600/5200/7800 emulators via BizHawk, enabling memory read/write, button input, frame advancing, and save/load state operations.
Provides tools for interacting with PlayStation 1 emulators via BizHawk, enabling memory read/write, button input, frame advancing, and save/load state operations.
Provides tools for interacting with Sega Saturn emulators via BizHawk, enabling memory read/write, button input, frame advancing, and save/load state operations.
Provides tools for interacting with Sega Master System, Genesis, and 32X emulators via BizHawk, enabling memory read/write, button input, frame advancing, and save/load state operations.
mcp-bizhawk
An MCP server that exposes BizHawk — the multi-system emulator the TAS community lives in — to any MCP-compatible client (Claude Desktop, Claude Code, etc.).
One bridge, many systems: NES, SNES, Game Boy / GBC / GBA, Sega Master System / Genesis / 32X / Saturn, N64, PlayStation 1, Atari 2600/5200/7800, Lynx, ColecoVision, Intellivision, and more — all through the same MCP tools, with per-system memory domains exposed cleanly.
How it works
+------------------+ stdio +------------------+ TCP :8766 +------------------+
| MCP client | JSON-RPC | mcp-bizhawk | newline JSON | BizHawk |
| (Claude / etc.) | ===========> | (Node.js) | <============ | bridge.lua |
+------------------+ +------------------+ +------------------+The transport is inverted compared to most other emulator-MCP bridges: BizHawk's Lua doesn't have native server sockets, only an outbound comm.socketServer* client. So mcp-bizhawk runs the TCP listener, and BizHawk's Lua bridge dials in once per frame to ferry commands and replies.
Two pieces:
lua/bridge.lua— runs inside BizHawk's Lua Console, polls our TCP server once per framedist/index.js— the Node.js MCP server, listens on127.0.0.1:8766by default, exposes tools over stdio
Trade-off: this design adds ~one frame of latency per call (≈16ms at 60Hz). Fine for interactive memory hunting, save-state experimentation, and frame-by-frame inspection. Less ideal for high-rate-of-fire scripting.
Related MCP server: mcp-retroarch
Requirements
BizHawk 2.6.2 or newer (earlier builds use an older socket-server wire format)
Node.js 18+ (for the MCP server)
Tested on BizHawk 2.11.1 across SNES (Super Metroid). Should work on any system BizHawk supports.
Install
Option A — install from npm (recommended)
npm install -g mcp-bizhawkOption B — npx (no install)
npx -y mcp-bizhawkOption C — clone and develop
git clone https://github.com/dmang-dev/mcp-bizhawk
cd mcp-bizhawk
npm install # also runs the build via the `prepare` hookSet up the BizHawk bridge
There are two pieces to configure: telling BizHawk where to connect, and loading the bridge script.
1. Point BizHawk at the MCP server
Easiest: launch BizHawk with the socket flags directly.
EmuHawk.exe --socket_ip=127.0.0.1 --socket_port=8766 <path/to/rom>(Adjust port if you're overriding BIZHAWK_PORT.)
Alternative: configure persistently via Settings → Customize → External Tools in BizHawk's UI.
2. Load the bridge script
In BizHawk: Tools → Lua Console → Open Script → select lua/bridge.lua from this repo.
You should see in the Lua Console:
[mcp-bizhawk] bridge starting
[mcp-bizhawk] socket server target: 127.0.0.1:8766
[mcp-bizhawk] socket receive timeout set to 50ms
[mcp-bizhawk] frame loop active — bridge is polling once per frameAnd in the mcp-bizhawk process's stderr:
[mcp-bizhawk] BizHawk client connected (waiting for bridge.lua to start polling)
[mcp-bizhawk] bridge.lua is polling — bridge readyRegister with your MCP client
Claude Code (CLI)
claude mcp add bizhawk --scope user mcp-bizhawkVerify:
claude mcp list
# bizhawk: mcp-bizhawk - ✓ ConnectedClaude Desktop
Edit claude_desktop_config.json:
Platform | Path |
macOS |
|
Windows |
|
Linux |
|
{
"mcpServers": {
"bizhawk": {
"command": "mcp-bizhawk"
}
}
}Restart Claude Desktop after editing.
Other MCP clients
The server speaks standard MCP over stdio. Run mcp-bizhawk and connect any MCP client to its stdio.
Configuration
Env var | Default | Purpose |
|
| TCP host to listen on for BizHawk |
|
| TCP port to listen on for BizHawk |
Tools
Tool | Description |
| Verify bridge connectivity (returns |
| ROM name, ROM hash, framecount, memory domains, capabilities |
| List available memory domains for the loaded core |
| Read u8 / u16-LE / u32-LE from memory |
| Write to memory |
| Read up to 4096 bytes as a byte array |
| Write up to 4096 bytes from a byte array |
| Set joypad state for one player; keys are button names, values booleans |
| Step the emulator by N frames |
| Pause / resume emulation |
| Reset the loaded core |
| Save a PNG of the current display to a path |
| Save / load emulator state to a file path |
All memory r/w tools take an optional domain parameter — if omitted, the active "current" memory domain is used. Use bizhawk_list_memory_domains to discover the names available on the loaded core.
See docs/RECIPES.md for end-to-end examples (RAM hunting on SNES/NES/N64, frame-precise input, snapshot-experiment-restore, cross-system regression testing) and CHANGELOG.md for release history.
Memory domains by system (cheat sheet)
Names come straight from BizHawk's core implementation. Use bizhawk_list_memory_domains to see the exact set for the loaded ROM.
System | Main RAM domain | Other common domains |
NES |
|
|
SNES |
|
|
GB/GBC |
|
|
GBA |
|
|
Genesis |
|
|
N64 |
|
|
PSX |
|
|
Buttons by system
BizHawk's joypad.set takes a {ButtonName=true, ...} table where button names depend on the core. Common ones:
System | Names |
NES |
|
SNES |
|
GB/GBC |
|
GBA |
|
N64 |
|
Genesis |
|
If you're unsure, run a probe: bizhawk_press_buttons {"A": true} and watch the active core's input display in BizHawk.
Troubleshooting
Symptom | Cause / Fix |
MCP tool calls hang for 10 seconds, then time out with "is the bridge.lua script still polling?" | bridge.lua isn't loaded. In BizHawk: Tools → Lua Console → Open Script → bridge.lua. Check the console for |
BizHawk connects to the server but tool calls still time out | You're on BizHawk older than 2.6.2 — the socket wire format changed then. Upgrade BizHawk. |
| BizHawk wasn't launched with |
Tools missing in Claude after install | Restart your MCP client; Claude only enumerates servers on startup. |
Memory reads return zeros for the first few seconds after boot | The emulator hasn't initialized RAM yet. Either advance some frames ( |
| The domain name didn't match anything for the loaded core. Call |
| Some BizHawk cores expose a slightly different surface. Check |
Development
npm install
npm run dev # tsc --watch — autobuilds on src/ changesEnd-to-end smoke test (launches BizHawk, loads ROM + bridge, runs ping/get_info/list_memory_domains/read_range):
node .scratch/test-all.cjs "I:\path\to\your\rom.smc"Set DEBUG=1 to dump every RX/TX line.
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-bizhawk'
If you have feedback or need assistance with the MCP directory API, please join our Discord server