MCP server to control RetroArch via its Network Control Interface for memory, state, screenshot, pause, reset, and messages.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent โ or use 1-click editor setup below.
๐ก Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Inspect callable tools, capabilities, and parameters exposed to AI agents by MCP Retroarch.
retroarch_pingPURPOSE: Verify connectivity to RetroArch's Network Control Interface and return the running RetroArch version string. USAGE: Call once at start-of-session before issuing other tool calls โ if it succeeds, the UDP transport is up and other tools should reach RetroArch. Use retroarch_get_status afterwards to confirm a game is loaded (ping succeeds even when RetroArch is sitting at the menu with no content). BEHAVIOR: No side effects โ pure liveness probe. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires `network_cmd_enable = true` in retroarch.cfg). Times out after ~5 seconds with a clear error if RetroArch isn't running, has Network Commands disabled, is bound to a different host/port, or a firewall is blocking UDP 55355. RETURNS: Single line 'OK โ RetroArch VERSION', e.g. 'OK โ RetroArch 1.20.0'.
retroarch_get_statusPURPOSE: Report whether RetroArch is currently playing or paused, plus the loaded system, game basename, and CRC32. USAGE: Call after retroarch_ping to learn what (if anything) is loaded; before retroarch_pause_toggle to decide whether the toggle will pause or unpause; before retroarch_frame_advance (which only steps when paused); whenever you need to confirm the previous fire-and-forget control command (pause/reset/load_state) actually took effect. For RetroArch settings (paths, flags) use retroarch_get_config instead โ this tool only reports run-state and the loaded ROM identity. BEHAVIOR: No side effects โ pure read of emulator status via the NCI's GET_STATUS command. Returns 'No content loaded' (state=contentless) when RetroArch is sitting at the menu with no ROM. Returns an error on UDP timeout (RetroArch not reachable). RETURNS: When content is loaded: four lines 'State: playing|paused', 'System: SYSTEM_ID', 'Game: BASENAME', 'CRC32: HEX or (none reported)'. When no content: literal 'No content loaded'.
retroarch_get_configPURPOSE: Read a single RetroArch configuration parameter by name via the NCI GET_CONFIG_PARAM command. USAGE: Discover RetroArch's filesystem paths and selected settings without parsing retroarch.cfg yourself. For run-state (playing/paused, loaded ROM) use retroarch_get_status instead โ this tool only reads static config. RetroArch whitelists which params are exposed; non-whitelisted names error even if they exist in retroarch.cfg. `screenshot_directory` is NOT exposed โ see retroarch_screenshot. BEHAVIOR: No side effects โ pure read. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires `network_cmd_enable = true` in retroarch.cfg). Errors if the param isn't in RetroArch's NCI whitelist, the value contains characters that break the line-based reply parser (rare โ embedded newlines or null bytes), or the UDP query times out. RETURNS: 'NAME = VALUE' where VALUE is the raw string as stored in retroarch.cfg (paths unquoted, booleans as 'true'/'false', integers as decimal).
retroarch_read_memoryPURPOSE: Read up to 4096 bytes from emulated memory via the libretro core's system memory map (READ_CORE_MEMORY) and return them as a hex dump. USAGE: Preferred memory-read tool when the loaded core advertises a memory map (most modern cores do). If it returns 'no memory map defined', fall back to retroarch_read_ram which uses the CHEEVOS address space. To poke a value back, pair with retroarch_write_memory at the same address. The classic two-snapshot RAM-hunt workflow uses this: snapshot before a known change, snapshot after, diff for matching deltas. Maximum 4096 bytes per call (NCI line-length limit); for larger reads, batch in 4 KiB chunks. BEHAVIOR: No side effects โ pure read. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires `network_cmd_enable = true` in retroarch.cfg). Reads work whether emulation is paused or running. Returns an error if the loaded core doesn't expose a memory map ('no memory map defined'), the address is outside any core descriptor, length < 1, length > 4096, or the UDP query times out. RetroArch may return FEWER bytes than requested if the read crosses a memory-region boundary โ the response reports the actual count. RetroArch exposes TWO distinct memory APIs with different address spaces: โข READ_CORE_MEMORY / WRITE_CORE_MEMORY (used by retroarch_read_memory / retroarch_write_memory): goes through the libretro core's system memory map. Preferred when the loaded core advertises a memory map (most modern cores do). Errors with 'no memory map defined' if the loaded core doesn't. โข READ_CORE_RAM / WRITE_CORE_RAM (used by retroarch_read_ram / retroarch_write_ram): uses the achievement (CHEEVOS) address space. Works even when no core memory map is defined, but addresses follow CHEEVOS conventions, not the system bus. Use as a fallback when read_memory returns 'no memory map defined'. Both APIs depend on the loaded core's exposed mapping โ addresses you used on a different core / system will NOT carry over. RETURNS: Header line 'ADDR_HEX [N bytes]:' followed by space-separated 2-digit uppercase hex bytes.
retroarch_read_ramPURPOSE: Read up to 4096 bytes from emulated memory via the achievement (CHEEVOS) address space (READ_CORE_RAM) and return them as a hex dump. USAGE: Fallback memory-read tool โ use when retroarch_read_memory returns 'no memory map defined' (older cores or those without an exposed system memory map can still respond to the older CHEEVOS read API). To poke back, pair with retroarch_write_ram at the same CHEEVOS address. Maximum 4096 bytes per call (NCI line-length limit). BEHAVIOR: No side effects โ pure read. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires `network_cmd_enable = true` in retroarch.cfg). Reads work whether emulation is paused or running. Returns an error if the address is invalid for the CHEEVOS space, length < 1, length > 4096, or the UDP query times out. Like read_memory, RetroArch may return fewer bytes than requested at memory-region boundaries. RetroArch exposes TWO distinct memory APIs with different address spaces: โข READ_CORE_MEMORY / WRITE_CORE_MEMORY (used by retroarch_read_memory / retroarch_write_memory): goes through the libretro core's system memory map. Preferred when the loaded core advertises a memory map (most modern cores do). Errors with 'no memory map defined' if the loaded core doesn't. โข READ_CORE_RAM / WRITE_CORE_RAM (used by retroarch_read_ram / retroarch_write_ram): uses the achievement (CHEEVOS) address space. Works even when no core memory map is defined, but addresses follow CHEEVOS conventions, not the system bus. Use as a fallback when read_memory returns 'no memory map defined'. Both APIs depend on the loaded core's exposed mapping โ addresses you used on a different core / system will NOT carry over. RETURNS: Header line 'ADDR_HEX [N bytes, CHEEVOS]:' followed by space-separated 2-digit uppercase hex bytes.
retroarch_write_memoryPURPOSE: Write a byte sequence to emulated memory via the libretro core's system memory map (WRITE_CORE_MEMORY). USAGE: Preferred memory-write tool when the loaded core advertises a memory map. Use for cheats, debug pokes, and game-state mutations (give a player N lives, unlock a flag, install a cheat table). If it returns 'no memory map defined', fall back to retroarch_write_ram. Maximum 4096 bytes per call (NCI line-length limit); for larger writes, batch in 4 KiB chunks. To establish a rollback point first, use retroarch_save_state_current. BEHAVIOR: DESTRUCTIVE: overwrites N bytes starting at `address` with no undo (snapshot via retroarch_save_state_current first if you need rollback). Disables RetroArch's hardcore mode for the rest of the session (RetroArch silently flips this flag when any memory-write NCI command is used). UNLIKE most NCI commands, this one DOES return a count โ RetroArch replies with the number of bytes actually written, which may be less than requested if a read-only descriptor is hit mid-write (writes still apply up to that boundary). Direct memory write โ bypasses MBC/mapper/DMA semantics. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires `network_cmd_enable = true` in retroarch.cfg). Returns an error if the loaded core doesn't expose a memory map, the address is invalid, the byte array is empty or > 4096, or the UDP query times out. RetroArch exposes TWO distinct memory APIs with different address spaces: โข READ_CORE_MEMORY / WRITE_CORE_MEMORY (used by retroarch_read_memory / retroarch_write_memory): goes through the libretro core's system memory map. Preferred when the loaded core advertises a memory map (most modern cores do). Errors with 'no memory map defined' if the loaded core doesn't. โข READ_CORE_RAM / WRITE_CORE_RAM (used by retroarch_read_ram / retroarch_write_ram): uses the achievement (CHEEVOS) address space. Works even when no core memory map is defined, but addresses follow CHEEVOS conventions, not the system bus. Use as a fallback when read_memory returns 'no memory map defined'. Both APIs depend on the loaded core's exposed mapping โ addresses you used on a different core / system will NOT carry over. RETURNS: Single line 'Wrote N bytes โ ADDR_HEX' where N is RetroArch's reported actual byte count.
An MCP server that bridges Claude (and any other MCP client) to RetroArch via its built-in Network Control Interface (UDP, port 55355).
Works against any libretro core (NES, SNES, Genesis, GB/GBC/GBA, PSX, N64, etc.) โ give the model memory r/w, save-state automation, screenshot, pause / frame-advance / reset, and on-screen messages.
| Capability | Available? | Notes |
|---|---|---|
| Memory read / write | โ | Two paths: READ_CORE_MEMORY (system memory map, preferred) and READ_CORE_RAM (CHEEVOS, fallback) |
| Save / load state | โ | Current slot or explicit slot for load; save is current-slot-only (NCI limitation) |
| Screenshot | โ | Saved to RetroArch's configured screenshot directory |
| Pause / frame advance | โ | PAUSE_TOGGLE flips state; FRAMEADVANCE steps one frame |
| Reset | โ | Hard-reset the running game |
| On-screen message | โ | Useful for "look here" cues during scripted runs |
| Game info | โ | Title, system, CRC32 |
| Game-pad input | โ | NCI doesn't expose this. RetroArch has a separate "Remote RetroPad" core on UDP port 55400 that does, but it requires loading that specific core (you can't drive an existing emulation core through it). Not in scope for v0.1.0. |
If you need game-pad input on Game Boy Advance specifically, see mcp-mgba. For PCSX2 (memory + savestate only, no input/screenshot), see mcp-pine.
npx (no install)Either:
Network Cmd Port is 55355 (the default)retroarch.cfg:
Then launch any libretro core + game. The NCI is always-on once enabled โ no script to load.
Verify:
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 |
Restart Claude Desktop after editing.
| Env var | Default | Purpose |
|---|---|---|
RETROARCH_HOST | 127.0.0.1 | UDP destination host |
RETROARCH_PORT | 55355 | UDP port (must match network_cmd_port in retroarch.cfg) |
| Tool | Description |
|---|---|
retroarch_ping | Verify reachability โ returns RetroArch version |
retroarch_get_status | State (playing/paused), system, game, CRC32 |
retroarch_get_config | Read named RetroArch config values (e.g. savestate_directory) |
retroarch_read_memory / retroarch_write_memory | Memory r/w via system memory map |
retroarch_read_ram / retroarch_write_ram | Memory r/w via CHEEVOS address space (fallback when no memory map) |
retroarch_pause_toggle | Toggle pause state |
retroarch_frame_advance | Step one frame (only effective while paused) |
retroarch_reset | Hardware-reset the running game |
retroarch_screenshot | Save a screenshot to RetroArch's screenshot directory |
retroarch_show_message | Display a notification on the RetroArch window |
retroarch_save_state_current | Save to currently-selected slot |
retroarch_load_state_current | Load from currently-selected slot |
retroarch_load_state_slot | Load from explicit slot number |
retroarch_state_slot_plus / retroarch_state_slot_minus | Change current slot pointer (NCI has no "set slot to N") |
See docs/RECIPES.md for end-to-end examples.
Verified end-to-end against mcp-retroarch:
| System | Core | read_memory | read_ram | Notes |
|---|---|---|---|---|
| Game Boy Advance | mgba_libretro | โ | โ | GBA interrupt vector table visible at 0x0000 (d3 00 00 ea ...) |
| NES | mesen_libretro | โ (only NES core tested that does) | โ | Full 16-bit NES address space exposed. WRAM at 0x0000-0x07FF, mirrored to 0x1FFF. CHEEVOS bounded to first 64 KB. |
| NES | nestopia_libretro | โ no memory map | โ | CHEEVOS only. 64 KB bound. For NES + memory map, prefer Mesen. |
| SNES | snes9x_libretro | โ no memory map | โ | CHEEVOS bounded to ~128 KB (matches SNES WRAM size). 65C816 RTS opcodes (60) visible in code regions. |
| Sega Mega Drive / Genesis | genesis_plus_gx_libretro | โ no memory map | โ ๏ธ sparse | CHEEVOS exposes some 68K WRAM addresses but fails at others ("no error message"). Usable if you know specific addresses; blanket sweep doesn't work. |
| Nintendo 64 | mupen64plus_next_libretro | โ | โ | Full N64 RAM exposed. KSEG0 mirror is faithful โ read_memory(0x80000000) returns the same bytes as read_memory(0x0). Bound is the connected RAM size (4 MB without Expansion Pak, 8 MB with). |
| PlayStation 1 | swanstation_libretro | โ no memory map | โ | CHEEVOS only. PSX main RAM begins around CHEEVOS offset 0x010000 (lower addresses are typically zero). |
0x80000000 reads as 0x0); Mesen preserves the NES's WRAM mirroring (0x1000 reads as 0x0). This is great for anyone using the bridge alongside disassembly.If you've tested another core, please open a PR adding it to this table.
| Symptom | Cause / Fix |
|---|---|
RetroArch query timed out | Network Commands aren't enabled in RetroArch, or the port doesn't match RETROARCH_PORT. Confirm network_cmd_enable = "true" in retroarch.cfg. Also: UDP datagrams can be dropped under load even on loopback โ if a single call times out but a retry succeeds, that's the cause. The bridge doesn't auto-retry; just call again. |
READ_CORE_MEMORY failed: no memory map defined | The loaded libretro core doesn't advertise a system memory map. Try retroarch_read_ram (CHEEVOS path) โ many cores expose CHEEVOS even without a memory map. Confirmed for SwanStation (PSX); use read_ram for that core. |
READ_CORE_MEMORY failed: no descriptor for address | The address isn't covered by the core's memory map. Either a different core would expose it, or the address you want is outside the system bus (e.g. video memory in some cores). |
| Screenshots don't appear where I expect | RetroArch saves to its configured screenshot directory. The NCI doesn't expose screenshot_directory via GET_CONFIG_PARAM, so check the value via RetroArch's GUI: Settings โ Directory โ Screenshot. |
| Can't save to a specific state slot directly | NCI limitation, not a bug. The protocol only exposes "save to current slot" โ you have to walk the slot pointer to your target with state_slot_plus/state_slot_minus, then save. |
Smoke test against a running RetroArch:
Browse and call this server's tools interactively with the MCP Inspector:
Factual signals from GitHub, npm, and our automated checks โ not a rating.
No reviews yet โ be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/dmang-dev-mcp-retroarch)<a href="https://allmcps.com/mcp/dmang-dev-mcp-retroarch"><img src="https://allmcps.com/api/badge/dmang-dev-mcp-retroarch?style=directory" alt="MCP Retroarch on AllMCPs" /></a>