mcp-retroarch
The mcp-retroarch server bridges MCP clients (like Claude) to RetroArch's Network Control Interface (NCI) over UDP, enabling programmatic control of emulated games across many systems (NES, SNES, Genesis, GBA, PSX, N64, etc.).
Connectivity & Status
retroarch_ping— Verify connectivity and retrieve the RetroArch version stringretroarch_get_status— Check if emulation is playing or paused, and get loaded game info (system, name, CRC32)retroarch_get_config— Read RetroArch configuration parameters (e.g. save directories, settings)
Memory Access
retroarch_read_memory/retroarch_write_memory— Read/write emulated memory via the libretro core's system memory map (preferred; up to 4 KiB per call)retroarch_read_ram/retroarch_write_ram— Read/write memory via the CHEEVOS address space (fallback when no memory map is available)
Emulation Control
retroarch_pause_toggle— Toggle between paused and running statesretroarch_frame_advance— Step emulation forward by exactly one frame (while paused)retroarch_reset— Soft-reset the running game
Save States
retroarch_save_state_current— Save emulator state to the currently-selected slotretroarch_load_state_current/retroarch_load_state_slot— Restore state from the current or a specific slot (0–9)retroarch_state_slot_plus/retroarch_state_slot_minus— Increment or decrement the current save slot pointer
Visual & Display
retroarch_screenshot— Capture a PNG screenshot saved to RetroArch's screenshot directoryretroarch_show_message— Display a custom on-screen notification overlay
Notable Limitations
No gamepad/button input — RetroArch's NCI does not expose controller input
Saving to a specific slot requires walking the pointer with slot_plus/slot_minus
Most control commands are fire-and-forget UDP datagrams with no acknowledgment; use status/memory reads to verify effects
Memory map availability varies by core
Provides tools for interacting with RetroArch's Network Control Interface, enabling memory read/write, save/load states, screenshots, pause/frame advance, reset, and on-screen messages for emulated games.
mcp-retroarch
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.
What it can do
Capability | Available? | Notes |
Memory read / write | ✅ | Two paths: |
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 | ✅ |
|
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.
Related MCP server: mcp-mgba
How it works
+----------------+ stdio +-----------------+ UDP :55355 +-----------------+
| MCP client | JSON-RPC | mcp-retroarch | text proto | RetroArch |
| (Claude etc) | -----------> | (Node.js) | ------------> | (NCI enabled) |
+----------------+ +-----------------+ +-----------------+Requirements
RetroArch (any recent version) with Network Commands enabled
Node.js 22+
Install
Option A — install from npm (recommended)
npm install -g mcp-retroarchOption B — npx (no install)
npx -y mcp-retroarchOption C — clone and develop
git clone https://github.com/dmang-dev/mcp-retroarch
cd mcp-retroarch
npm installEnable RetroArch's Network Control Interface
Either:
GUI: Settings → Network → Network Commands → ON, then confirm
Network Cmd Portis55355(the default)Or via
retroarch.cfg:network_cmd_enable = "true" network_cmd_port = "55355"
Then launch any libretro core + game. The NCI is always-on once enabled — no script to load.
Register with your MCP client
Claude Code
claude mcp add retroarch --scope user mcp-retroarchVerify:
claude mcp list
# retroarch: mcp-retroarch - ✓ ConnectedClaude Desktop
Edit claude_desktop_config.json:
Platform | Path |
macOS |
|
Windows |
|
Linux |
|
{
"mcpServers": {
"retroarch": {
"command": "mcp-retroarch"
}
}
}Restart Claude Desktop after editing.
Configuration
Env var | Default | Purpose |
|
| UDP destination host |
|
| UDP port (must match |
Tools
Tool | Description |
| Verify reachability — returns RetroArch version |
| State (playing/paused), system, game, CRC32 |
| Read named RetroArch config values (e.g. |
| Memory r/w via system memory map |
| Memory r/w via CHEEVOS address space (fallback when no memory map) |
| Toggle pause state |
| Step one frame (only effective while paused) |
| Hardware-reset the running game |
| Save a screenshot to RetroArch's screenshot directory |
| Display a notification on the RetroArch window |
| Save to currently-selected slot |
| Load from currently-selected slot |
| Load from explicit slot number |
| Change current slot pointer (NCI has no "set slot to N") |
See docs/RECIPES.md for end-to-end examples.
Tested cores
Verified end-to-end against mcp-retroarch:
System | Core |
|
| Notes |
Game Boy Advance |
| ✅ | ✅ | GBA interrupt vector table visible at |
NES |
| ✅ (only NES core tested that does) | ✅ | Full 16-bit NES address space exposed. WRAM at |
NES |
| ❌ no memory map | ✅ | CHEEVOS only. 64 KB bound. For NES + memory map, prefer Mesen. |
SNES |
| ❌ no memory map | ✅ | CHEEVOS bounded to ~128 KB (matches SNES WRAM size). 65C816 RTS opcodes ( |
Sega Mega Drive / Genesis |
| ❌ 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 |
| ✅ | ✅ | Full N64 RAM exposed. KSEG0 mirror is faithful — |
PlayStation 1 |
| ❌ no memory map | ✅ | CHEEVOS only. PSX main RAM begins around CHEEVOS offset |
Patterns observed
Most libretro cores don't advertise a system memory map to NCI — they implement only the CHEEVOS read API. Of those tested, only Mesen (NES) and Mupen64Plus-Next (N64) expose a system memory map. Both also expose CHEEVOS, so they're strictly better.
System memory maps are faithful to real hardware — Mupen64Plus-Next preserves the N64's KSEG0 mirror (
0x80000000reads as0x0); Mesen preserves the NES's WRAM mirroring (0x1000reads as0x0). This is great for anyone using the bridge alongside disassembly.CHEEVOS bounds match the system's main RAM size — NES exposes 64 KB, SNES 128 KB, etc. Reads past the bound fail with "no error message".
When choosing a core for memory work, prefer the one with a system memory map if available.
If you've tested another core, please open a PR adding it to this table.
Troubleshooting
Symptom | Cause / Fix |
| Network Commands aren't enabled in RetroArch, or the port doesn't match |
| The loaded libretro core doesn't advertise a system memory map. Try |
| 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 |
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 |
Development
npm install
npm run dev # tsc --watchSmoke test against a running RetroArch:
node .scratch/smoke.cjsDebugging with the MCP Inspector
Browse and call this server's tools interactively with the MCP Inspector:
npm run inspectorBuild first if you've edited src/ since your last npm install (npm run build, or keep npm run dev running). Override the target with RETROARCH_HOST / RETROARCH_PORT (default 127.0.0.1:55355). tools/list works even without RetroArch connected; calling a tool needs RetroArch running with Network Commands enabled.
License
Related
Available Tools
17 toolsretroarch_frame_advanceA
PURPOSE: Step emulation forward by exactly one frame. USAGE: Use for frame-precise input automation, animation inspection, or letting the system initialize after a reset. ONLY effective while emulation is paused — RetroArch's FRAMEADVANCE is a no-op when running, so call retroarch_pause_toggle first (after checking retroarch_get_status to confirm you'll end up paused, not unpaused). For long jumps (thousands of frames) prefer retroarch_save_state_current / retroarch_load_state_current of a pre-prepared state — frame-by-frame stepping costs ~1 UDP round-trip per frame. BEHAVIOR: When paused, advances the emulator by exactly one frame and remains paused. When NOT paused, the command is silently ignored by RetroArch. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. The new frame count is not reported — to verify progress, take screenshots before/after with retroarch_screenshot or read a known-changing memory value. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Advanced one frame' (UDP-send confirmation only — does NOT confirm that RetroArch was paused or that the frame actually advanced).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Describes behavior when paused vs unpaused, fire-and-forget nature, no confirmation, UDP silent drops, and need for verification. No annotations so description carries full burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with labeled sections, front-loaded purpose. Slightly verbose but every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, usage, prerequisites, failure modes, transport, return value, and verification steps. Complete for a no-param tool with no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters; schema coverage 100%. Description adds no param info but baseline for 0 params is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Step emulation forward by exactly one frame' with specific verb and resource, distinguishing it from sibling tools like pause toggle and reset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use (frame-precise tasks) and when not (long jumps prefer save/load), with prerequisite to ensure paused state and reference to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_get_configA
PURPOSE: Read a single RetroArch configuration parameter by name via the NCI's GET_CONFIG_PARAM command. USAGE: Use to 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 values. NOTE: RetroArch whitelists which params are exposed via NCI; unknown / non-whitelisted names return an error from RetroArch even though they may exist in retroarch.cfg. The screenshot output 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). Returns an error if the named param isn't in RetroArch's NCI whitelist, the value contains characters that break the line-based reply parser, or the UDP query times out. RETURNS: Single line 'NAME = VALUE'.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Config parameter name (case-sensitive). Commonly-supported values: `savefile_directory`, `savestate_directory`, `system_directory`, `cache_directory`, `log_dir`, `runtime_log_directory`, `netplay_nickname`, `video_fullscreen`. RetroArch's exact whitelist varies by version; if a name returns an error, it isn't exposed via the NCI on this build. `screenshot_directory` is NOT exposed by RetroArch — there is no NCI way to query the screenshot output path. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It states the tool is a pure read with no side effects, describes the transport (NCI over UDP, with network_cmd_enable required), and lists potential errors (non-whitelisted param, parser breakage, timeout). This is very good, though missing details on empty values or error format.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headings (PURPOSE, USAGE, NOTE, BEHAVIOR, RETURNS) and is front-loaded with the purpose. Every sentence adds value, and it is not overly verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter) and lack of output schema, the description covers purpose, usage, behavior, and return format. It mentions error conditions and transport requirements. Minor omission: does not specify error return format, but overall very complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with detailed description of the 'name' parameter, including common values and caveats. The description adds little beyond what the schema provides, only repeating some info and adding the note about screenshot_directory not being exposed. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads a single RetroArch config parameter via NCI's GET_CONFIG_PARAM command. It distinguishes from siblings like retroarch_get_status and retroarch_screenshot, specifying different use cases.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool (to discover paths/settings without parsing retroarch.cfg) and when not to (for run-state, use retroarch_get_status). It also notes the screenshot directory is not exposed, pointing to retroarch_screenshot.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_get_statusA
PURPOSE: 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'.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description fully discloses no side effects (pure read), error on timeout, contentless state message, and exact return format. Exceeds typical transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with PURPOSE, USAGE, BEHAVIOR, RETURNS sections. Every sentence is necessary and concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description thoroughly explains return values, error states, and integration with sibling tools. Complete for reliable agent use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters, so schema provides no parameter info. Description adds value by detailing output format, compensating for absence of parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool reports playing/paused state, loaded system, game basename, and CRC32. It uses a specific verb and resource, and distinguishes from retroarch_get_config.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use scenarios (after ping, before pause_toggle, before frame_advance, to confirm commands) and when not to use (use retroarch_get_config for settings).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_load_state_currentA
PURPOSE: Restore the emulator from RetroArch's currently-selected save slot (one of slots 0-9). USAGE: Counterpart to retroarch_save_state_current. Use to undo a sequence of writes/inputs (the snapshot/experiment/restore workflow) or to start each tool-call sequence from a known baseline. Loads from whichever slot is currently selected (the same slot save_state_current would target). To load from a specific slot WITHOUT changing the current-slot pointer, use retroarch_load_state_slot instead — that's important if you're alternating between bookmarks. To start fresh from boot, use retroarch_reset. BEHAVIOR: DESTRUCTIVE TO LIVE STATE: replaces ALL current emulator state (RAM, registers, mapper, audio, framecount) with the slot file's contents. Anything not previously snapshotted is lost. The state file MUST come from the same ROM and same core version that produced it — loading mismatched files typically fails or destabilizes the core. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. If the currently-selected slot has no saved state, RetroArch silently ignores the command — no error is raised. To verify the load happened, follow up with a memory-read or screenshot. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Loaded from current slot' (UDP-send confirmation only — does NOT verify the slot existed or the load succeeded).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Fully details destructive behavior (replaces all state), fire-and-forget nature, silent failures, and transport requirements. No annotations provided, so description carries full burden and excels.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with headings, front-loaded purpose, and every sentence adds value. Length is justified given complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all aspects: purpose, usage, behavior, verification, transport. No output schema, but description compensates fully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, but description clearly communicates that behavior relies on the currently-selected slot. Schema has 100% coverage, and description adds necessary context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool restores emulator state from the currently-selected save slot. It uses specific verbs and resources, and distinguishes from siblings like 'retroarch_load_state_slot' and 'retroarch_reset'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides when to use (undo sequence, start from baseline) and when not to use (specific slot without pointer change), along with alternative tools and verification methods.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_load_state_slotA
PURPOSE: Load state from an explicitly-named save slot number, without modifying RetroArch's currently-selected slot pointer. USAGE: Use to load from a specific slot when you don't want to disturb the current-slot pointer (e.g. you're alternating between two bookmarks while keeping the 'live' slot for ongoing saves). For loading from the currently-selected slot, use retroarch_load_state_current — semantically distinct: this tool ignores the current-slot pointer entirely and addresses by number. Slots are numbered 0-9 by RetroArch convention. There is no retroarch_save_state_slot counterpart in the NCI — saving to a specific slot still requires walking the pointer with state_slot_plus/minus and then calling save_state_current. BEHAVIOR: DESTRUCTIVE TO LIVE STATE: replaces ALL current emulator state with the named slot's contents. Anything not previously snapshotted is lost. The state file MUST come from the same ROM and core version that produced it. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). UNLIKE most NCI control commands, LOAD_STATE_SLOT does send a reply (this client awaits it), so a UDP timeout will surface as an error here even though sibling load/save calls are fire-and-forget. If the named slot has no saved state, RetroArch's reply still indicates the command was processed — verify with a memory-read or screenshot. The current-slot pointer is unchanged after this call. RETURNS: Single line 'Loaded from slot N' echoing the requested slot number.
| Name | Required | Description | Default |
|---|---|---|---|
| slot | Yes | Save state slot number to load from. RetroArch's standard slot range is 0-9 (ten slots), but the NCI does not enforce a hard upper bound — slot numbers outside the configured range will simply find no file and silently no-op. This call does NOT change the currently-selected slot pointer (use retroarch_state_slot_plus / retroarch_state_slot_minus for that). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavioral traits: 'DESTRUCTIVE TO LIVE STATE: replaces ALL current emulator state... Anything not previously snapshotted is lost.' It also covers transport requirements, reply behavior vs. siblings, error handling (UDP timeout), and constraints on state file compatibility.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear labeled sections (PURPOSE, USAGE, BEHAVIOR, RETURNS). It is front-loaded with purpose and usage, every sentence adds distinct value, and there is no redundancy despite comprehensive coverage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of the tool (emulator state manipulation, no output schema), the description is remarkably complete. It explains return value format, error conditions (UDP timeout, missing state file), transport details, and dependencies (same ROM/core). No obvious gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single parameter 'slot'. The description adds meaning beyond the schema by noting standard range (0-9), that the NCI doesn't enforce upper bound, that out-of-range slots silently no-op, and that the call does not change the current-slot pointer.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'PURPOSE: Load state from an explicitly-named save slot number, without modifying RetroArch's currently-selected slot pointer.' This clearly identifies the verb (load), resource (save slot), and behavior (no pointer change), differentiating it from sibling retroarch_load_state_current.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'USAGE' guidance: 'Use to load from a specific slot when you don't want to disturb the current-slot pointer... For loading from the currently-selected slot, use retroarch_load_state_current — semantically distinct.' It clearly states when to use this tool and when to use an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_pause_toggleA
PURPOSE: Toggle RetroArch's pause state — pause if running, unpause if paused. USAGE: RetroArch's NCI exposes ONLY a toggle, not separate pause/unpause commands. To reach a known state, call retroarch_get_status first to check state: playing|paused, then toggle if and only if you need to flip it. Use before a sequence of memory-inspect / write / screenshot calls when you need a stable game state across calls; pair with retroarch_frame_advance to step single frames without leaving pause. BEHAVIOR: Modifies emulator run state by flipping it. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. Calling toggle when you don't know the current state will flip it to whichever state it ISN'T — confirm with retroarch_get_status before and after if it matters. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Pause toggled' (this is a confirmation that the UDP datagram was sent, NOT that RetroArch received or acted on it).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, description fully discloses behavior: it is fire-and-forget with no UDP acknowledgment, packets can be silently dropped, and it requires network_cmd_enable in config. It also explains that the return line only confirms the UDP datagram was sent, not that RetroArch acted on it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is well-organized with labeled sections (PURPOSE, USAGE, BEHAVIOR, RETURNS) and is front-loaded with the core purpose. While it is lengthy, every sentence serves a purpose; minor verbosity is acceptable given the need to explain fire-and-forget semantics and usage patterns.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless tool with no output schema, the description covers all necessary context: purpose, correct usage sequence, behavioral limitations, transport requirements, and return value meaning. It is fully self-contained and leaves no ambiguity for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so description adds no parameter-specific info. Baseline for 0 parameters is 4, and description fulfills that without needing to elaborate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Toggle RetroArch's pause state — pause if running, unpause if paused.', which is a specific verb-resource combination. It distinguishes from siblings like retroarch_get_status and retroarch_frame_advance by explaining when to use them in conjunction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to use retroarch_get_status first to check current state before toggling, and explains that calling toggle when state is unknown will flip it to the opposite state. Also recommends pairing with retroarch_frame_advance and defines fire-and-forget nature.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_pingA
PURPOSE: 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'.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses no side effects, transport details (UDP, config requirement), timeout, and error conditions. No ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with labeled sections. Every sentence serves a purpose; no redundancy. Front-loaded with purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, the description compensates fully by explaining return value, error scenarios, and configuration dependency. Complete for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so description naturally has high coverage. Adds value by detailing the return format and version string example, beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool verifies connectivity and returns the RetroArch version string. Distinguishes from siblings by noting that retroarch_get_status should be used later to confirm game loaded.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to call at start-of-session before other tools, and suggests retroarch_get_status for game confirmation. Provides clear when-to-use and when-not-to-rely guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_read_memoryA
PURPOSE: 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.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Starting address in the libretro core's system memory map (NOT the CHEEVOS address space — that's read_ram). Address layout depends on the loaded core: e.g. SNES WRAM is typically at 0x7E0000-0x7FFFFF, GBA EWRAM at 0x02000000-0x0203FFFF, Genesis 68K RAM at 0xFF0000-0xFFFFFF. Reads `length` consecutive bytes starting here. | |
| length | Yes | Number of consecutive bytes to read (1-4096). Hard cap is RetroArch's NCI single-datagram size; chunk larger reads yourself. RetroArch may return fewer bytes if the read crosses a memory-region boundary in the core's descriptor list. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, description discloses side effects (pure read), transport (NCI over UDP), error conditions (no memory map, invalid address/length, timeout), and behavior of returning fewer bytes across region boundaries. Explains two distinct memory APIs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with labeled sections (PURPOSE, USAGE, BEHAVIOR) and front-loaded. Slightly verbose but all information is relevant and necessary for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but description explains return format, transport, errors, and relationship to siblings. Complete for a read tool with complex constraints. Leaves no major gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but description adds core-specific address examples and distinguishes address spaces from read_ram. For length, reiterates cap and chunking. Provides context beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it reads up to 4096 bytes from emulated memory via the libretro core's system memory map and returns a hex dump. Differentiates from sibling retroarch_read_ram which uses CHEEVOS address space.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes when to use this tool (preferred when core has memory map) versus fallback to retroarch_read_ram. Provides pairing instructions with retroarch_write_memory and workflow for memory hunting. Advises chunking for larger reads.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_read_ramA
PURPOSE: 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.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Starting address in the CHEEVOS (achievements) address space — distinct from the libretro system memory map used by retroarch_read_memory. CHEEVOS addresses follow per-system conventions used by RetroAchievements (e.g. SNES CHEEVOS addresses for WRAM start at 0x000000, not the SNES system bus 0x7E0000). If unsure, retroarch_read_memory is usually the right starting point. | |
| length | Yes | Number of consecutive bytes to read (1-4096). Hard cap is RetroArch's NCI single-datagram size. May return fewer bytes at region boundaries. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses: no side effects (pure read), transport details (NCI over UDP), configuration requirement (network_cmd_enable = true), behavior during pause/run, error conditions, and potential to return fewer bytes at region boundaries. This is comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-structured with clear sections (PURPOSE, USAGE, BEHAVIOR, RETURNS). Every sentence adds value, though some sentences could be merged for brevity without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description includes return format. It covers purpose, usage, behavior, parameter nuances, and compares with sibling tool. No important context is missing, making it fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Though schema coverage is 100%, the description adds significant context: explains CHEEVOS addresses vs. system memory map, provides examples (SNES WRAM), and clarifies the length cap rationale. This enriches the schema's minimal descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads up to 4096 bytes from emulated memory via the CHEEVOS address space and returns a hex dump. It distinguishes from sibling retroarch_read_memory by explaining the two distinct memory APIs, making the purpose precise and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states this is a fallback when retroarch_read_memory returns 'no memory map defined' and that it pairs with retroarch_write_ram. Also advises that read_memory is preferred when the core advertises a memory map, providing clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_resetA
PURPOSE: Soft-reset the running game — equivalent to pressing the console's reset button (NOT a power cycle). USAGE: Use to start fresh from the game's reset vector. To return to a specific known-good point instead of boot, use retroarch_load_state_current or retroarch_load_state_slot with a previously saved state. Note this is a SOFT reset (button reset): RAM contents and any cart-internal state may persist depending on the system, unlike a true power cycle. BEHAVIOR: DESTRUCTIVE: triggers the loaded core's reset routine, which on most systems clears registers, resets the PC to the reset vector, and starts the boot sequence over. Unsaved game progress is lost. The loaded ROM stays loaded — only volatile state is affected. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. To confirm the reset took, follow up with retroarch_get_status (state should still be 'playing') and/or a screenshot. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Game reset' (UDP-send confirmation only — does NOT verify the reset executed).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are absent, so description bears full burden. It details destructiveness, fire-and-forget nature, silent UDP drops, persistence of cart-internal state, and lack of acknowledgment. Completely transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with labeled sections (PURPOSE, USAGE, BEHAVIOR, RETURNS) and front-loaded with key information. However, it is somewhat verbose with some redundant elaboration, earning a 4 rather than 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and no annotations, the description covers purpose, usage guidelines, behavioral details, transport requirements, follow-up verification, and return confirmation. It is fully complete for a fire-and-forget tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so baseline is 4. The description does not need to add parameter meaning, and the schema coverage is 100%. No additional info required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'soft-reset the running game — equivalent to pressing the console's reset button', uses a specific verb-resource combination, and distinguishes from power cycle and load state tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides when to use ('start fresh from the game's reset vector') and when not ('to return to a specific known-good point... use retroarch_load_state_current or retroarch_load_state_slot'), and recommends follow-up verification tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_save_state_currentA
PURPOSE: Save the entire emulator state to RetroArch's currently-selected save slot (one of slots 0-9). USAGE: Use as a rollback point before risky writes, to bookmark interesting game states, or to share repro states. RetroArch's NCI has NO 'save to slot N' command — to target a specific slot, you must first walk the slot pointer there with retroarch_state_slot_plus / retroarch_state_slot_minus, then call this. The current slot is RetroArch's internal state and is NOT reported back by the NCI, so if you don't track it yourself, observe the on-screen slot indicator after each plus/minus or use retroarch_show_message as a confirmation echo. The companion retroarch_load_state_current restores from the same slot. For path-based savestate I/O (no slots), there is no NCI equivalent — use the BizHawk or mGBA MCP servers instead. BEHAVIOR: DESTRUCTIVE TO TARGET SLOT FILE: overwrites whatever was previously in the currently-selected slot with no prompt or backup. The state file lands in RetroArch's configured savestate_directory (queryable via retroarch_get_config). State files are bound to the EXACT ROM and core version that produced them — loading on a different ROM or core typically fails. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. To verify the save happened, retroarch_load_state_current it back and observe via memory-read or screenshot. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Saved to current slot' (UDP-send confirmation only — does NOT verify the file was written, nor report which slot number it landed in).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses destructive behavior (overwrites slot file), fire-and-forget nature (no confirmation), UDP silent drops, and state file ROM/core binding. It also explains transport and return value limitations. This is exceptionally transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-structured with labeled sections (PURPOSE, USAGE, BEHAVIOR, TRANSPORT, RETURNS). Every sentence adds value, though some redundancy could be trimmed. Still, it is effectively organized and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and no output schema, the description covers all necessary context: purpose, usage context, behavioral caveats, transport details, and return value. It references sibling tools and explains limitations, making it fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters (100% coverage). The description explains why no parameters are needed (saves to current slot), adding context beyond the schema. A score of 4 is appropriate as the baseline is 4 for zero-parameter tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Save the entire emulator state'), the target resource ('RetroArch's currently-selected save slot'), and distinguishes from siblings like retroarch_load_state_current and slot navigation tools. The scope is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes when to use (rollback, bookmarking, repro states) and when not to use, with clear alternatives: path-based I/O requires BizHawk/mGBA, targeting a specific slot requires prior slot pointer manipulation. The guidance is comprehensive and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_screenshotA
PURPOSE: Capture a PNG screenshot of the current emulator display and save it to RetroArch's configured screenshot directory. USAGE: Use to capture visible game state for inspection, sequence documentation, or to verify that a fire-and-forget control command (pause / reset / load_state / write) had a visible effect. To capture a specific game state, pause / advance frames / load state first to get the frame you want, then call this. IMPORTANT: unlike most screenshot tools, this one DOES NOT take a path argument — RetroArch saves to its own configured screenshot_directory, which the NCI does not expose (it is NOT readable via retroarch_get_config). To find the file, check RetroArch's settings UI (Settings → Directory → Screenshots) or look at where screenshots normally land for your install. BEHAVIOR: Writes a new timestamped PNG to RetroArch's screenshot directory — no existing files are overwritten (RetroArch generates a fresh filename per shot). FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. The returned message confirms only that the SCREENSHOT command was sent, not that the file was actually written (disk full, permission denied, etc. would fail silently from the tool's perspective). Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Screenshot saved to RetroArch's configured screenshot directory' (UDP-send confirmation only).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly explains behavioral traits: writes a new timestamped PNG without overwriting, fire-and-forget without acknowledgment, silent packet drops if RetroArch is not listening, and silent failures. It also covers transport and configuration requirements, compensating for the lack of annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with labeled sections (PURPOSE, USAGE, IMPORTANT, etc.) and front-loaded with the purpose. However, it is somewhat verbose with some repetition (e.g., fire-and-forget explained twice), which slightly reduces conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations, no output schema, and zero parameters, the description is highly complete. It covers purpose, usage, behavior, return value, transport details, and configuration requirements, leaving no critical gaps for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, and the description clarifies that no path argument is needed because RetroArch manages its own directory. This explains the absence of parameters and adds value beyond the schema, which is fully covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool captures a PNG screenshot of the current emulator display and saves it to RetroArch's configured directory. It specifies the action, resource, and destination, and distinguishes itself from typical screenshot tools by noting it does not accept a path argument.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage contexts: capturing game state for inspection, sequence documentation, or verifying fire-and-forget commands. It advises pausing/advancing frames or loading a state first. It does not explicitly list when not to use it, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_show_messageA
PURPOSE: Display a single-line notification message overlaid on the RetroArch window (OSD overlay). USAGE: Use for in-emulator debug output, progress markers during long-running scripts, or to communicate with a human watching the RetroArch window. The overlay appears in RetroArch's standard notification area and fades out after RetroArch's configured notification timeout. This is purely cosmetic — it has no effect on game state. There is no sibling tool: this is the ONLY way to push text from the agent onto the RetroArch display. BEHAVIOR: Renders the supplied message string in RetroArch's on-screen notification area. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. Messages are not queued — calling rapidly will replace the previous message before users can read it. Line breaks in the message are stripped (NCI is line-based). Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Showed: MESSAGE' echoing what was sent (UDP-send confirmation only — does NOT verify that the overlay was actually rendered).
| Name | Required | Description | Default |
|---|---|---|---|
| message | Yes | Message text to display. Spaces inside the string are preserved; line breaks (\n / \r) are NOT — the NCI protocol is line-terminated, so newlines truncate the message. Keep messages short (one line, ~80 chars) to fit RetroArch's notification overlay without clipping. Consecutive calls replace the previous message rather than queueing. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description fully bears the burden. It thoroughly details behavior: renders the message, fire-and-forget (no acknowledgment), UDP silent drops, messages not queued, line breaks stripped, and transport requirements. This exceeds typical transparency expectations for a simple notification tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with labeled sections (PURPOSE, USAGE, BEHAVIOR, etc.), making it easy to scan. It is front-loaded with the purpose. Although it is lengthy, every sentence adds value and does not contain fluff. It could be slightly more concise, but overall it is effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (1 parameter, no annotations, no output schema), the description is exceptionally complete. It covers purpose, usage, behavior, limitations, transport requirements, return format, and even mentions the lack of sibling tools. An agent can fully understand how and when to use this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'message' has 100% schema description coverage. The description adds some context beyond the schema (e.g., fire-and-forget), but the schema already covers line breaks, consecutive calls, and length. Per guidelines, baseline is 3 when coverage is high, and while the description adds value, it does not significantly elevate parameter understanding beyond what is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Display a single-line notification message overlaid on the RetroArch window (OSD overlay).' It specifies the verb (display), resource (notification message), and location. It also distinguishes from siblings by stating 'this is the ONLY way to push text from the agent onto the RetroArch display.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit use cases: 'debug output, progress markers during long-running scripts, or to communicate with a human.' It explains when to use (cosmetic communication) and gives guidance on the fire-and-forget nature and verification steps. However, it doesn't explicitly state when NOT to use; this is implied by the context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_state_slot_minusA
PURPOSE: Decrement RetroArch's currently-selected save slot pointer by 1 (e.g. slot 3 → slot 2). USAGE: Counterpart to retroarch_state_slot_plus. Combine with retroarch_save_state_current or retroarch_load_state_current to target a lower-numbered slot — these tools always operate on the current slot. RetroArch's NCI exposes NO way to set the slot directly to N or to query the current slot number, so track it client-side or walk from a known position. For loading a specific slot WITHOUT changing the pointer, use retroarch_load_state_slot. BEHAVIOR: Mutates RetroArch's internal current-slot pointer (-1). Wraps or clamps per RetroArch's slot-cycling configuration (typically wraps at 0 → 9). FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. The new slot number is NOT reported back — track it client-side or watch the on-screen slot indicator. No effect on emulator memory / run state — only the slot pointer used by future save_state_current / load_state_current calls changes. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Decremented current slot' (UDP-send confirmation only — does NOT report the new slot number).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully covers behavioral traits: mutates pointer, wraps/clamps, fire-and-forget UDP with no acknowledgment, silent drop, no effect on emulator memory, and transport configuration. This exceeds the disclosure requirement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear sections (PURPOSE, USAGE, BEHAVIOR, TRANSPORT, RETURNS), front-loads key information, and every sentence provides essential detail without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (fire-and-forget UDP, no confirmation, client-side tracking needed), the description covers all necessary context including transport requirements, failure modes, and verification steps. No output schema exists, but return value is explained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters (coverage 100%). The description adds extensive behavioral context beyond the empty schema, explaining the tool's operation, return value, and side effects, compensating fully for the lack of parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb (decrement) and resource (RetroArch's current save slot pointer), and distinguishes from the sibling tool retroarch_state_slot_plus. It also mentions related tools for context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly identifies as counterpart to retroarch_state_slot_plus, explains when to combine with save/load current slot tools, and directs to retroarch_load_state_slot for loading without changing the pointer. Provides clear guidance on client-side tracking and verification steps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_state_slot_plusA
PURPOSE: Increment RetroArch's currently-selected save slot pointer by 1 (e.g. slot 3 → slot 4). USAGE: Combine with retroarch_save_state_current or retroarch_load_state_current to target a specific slot — these tools always operate on the current slot, so to save TO slot 5 you must walk the pointer there first. Pair with retroarch_state_slot_minus to walk backwards. RetroArch's NCI exposes NO way to set the slot directly to N or to query the current slot number, so if you don't track it yourself you must walk from a known position (e.g. slot 0) or observe the on-screen indicator. For loading a specific slot WITHOUT changing the pointer, use retroarch_load_state_slot instead. BEHAVIOR: Mutates RetroArch's internal current-slot pointer (+1). Wraps or clamps per RetroArch's slot-cycling configuration (typically wraps at 9 → 0). FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. The new slot number is NOT reported back — track it client-side or watch the on-screen slot indicator. No effect on emulator memory / run state — only the slot pointer used by future save_state_current / load_state_current calls changes. Transport: RetroArch's Network Control Interface (NCI) over UDP (default 127.0.0.1:55355, requires network_cmd_enable = true in retroarch.cfg). RETURNS: Single line 'Incremented current slot' (UDP-send confirmation only — does NOT report the new slot number).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses mutation of internal pointer, wrap/clamp behavior, fire-and-forget nature with no confirmation, silent drops when RetroArch not listening, and need to track slot client-side. No annotations provided, so description fully covers behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is well-structured with labeled sections (PURPOSE, USAGE, BEHAVIOR, RETURNS) and front-loaded key info. Every sentence adds value, no redundancy. Length is appropriate for the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Highly complete given the tool's complexity: covers usage scenarios, behavioral caveats, transport details, return value, and workarounds for limitations. No output schema, but description adequately explains what the tool returns and its meaning.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has no parameters, so schema coverage is 100%. Description adds meaning by explaining that the tool takes no parameters and operates on the current slot pointer statefully. While schema already conveys no params, description clarifies the lack of parameters is intentional and explains the operation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool increments RetroArch's current save slot pointer by 1. Uses specific verb 'increment' and resource 'save slot pointer'. Distinguishes from sibling retroarch_state_slot_minus by mentioning it walks backwards.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly explains when to use (combine with save/load current for targeting specific slot), when not to use (use retroarch_load_state_slot for loading without pointer change), and alternatives (pair with minus, walk from known position). Also mentions limitations like no direct set or query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_write_memoryA
PURPOSE: 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.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Starting address in the libretro core's system memory map (NOT CHEEVOS space). Bytes are written sequentially address, address+1, ..., address+N-1. | |
| bytes | Yes | Byte values to write, one per element (each 0-255). Length 1-4096 (hard cap from RetroArch's NCI single-datagram size). Written sequentially from `address`. If a read-only descriptor is encountered mid-array, the write stops at that boundary and the response reports how many bytes actually landed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses destructive overwrite, hardcore mode disable, return count with possible partial writes, and transport details. This is comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is well-structured with clear sections and front-loaded purpose. While lengthy, each part serves a purpose; could be slightly condensed but still effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of two memory APIs, destructive behavior, size limits, and transport protocol, the description is thorough. It explains return format, fallback, rollback necessity, and error conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 100% coverage; both parameters are described. Description adds context about sequential writing, NCI line limit, address space differences, and behavior on read-only boundaries, which is valuable beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it writes a byte sequence to emulated memory via the libretro core's system memory map, distinguishing it from retroarch_write_ram and specifying use cases like cheats and debug pokes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises when to use this tool (preferred when core has memory map) and when to fall back to retroarch_write_ram. Also mentions maximum byte limit and rollback via retroarch_save_state_current.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retroarch_write_ramA
PURPOSE: Write a byte sequence to emulated memory via the achievement (CHEEVOS) address space (WRITE_CORE_RAM). USAGE: Fallback memory-write tool — use when retroarch_write_memory returns 'no memory map defined' or the core only supports the older CHEEVOS write API. Maximum 4096 bytes per call (NCI line-length limit). To verify the write landed (this command does NOT acknowledge — see BEHAVIOR), follow up with retroarch_read_ram at the same address. To establish a rollback point first, use retroarch_save_state_current. BEHAVIOR: DESTRUCTIVE: overwrites 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. FIRE-AND-FORGET: the NCI does NOT acknowledge this command — the call returns as soon as the UDP datagram is sent, with no confirmation that RetroArch received or applied it. To verify the effect, follow up with an observable tool (retroarch_get_status for run state, retroarch_read_memory / retroarch_read_ram for memory mutations, retroarch_screenshot for visual state). UDP packets to a not-listening RetroArch are silently dropped. This is the key behavioral difference vs retroarch_write_memory, which DOES return a count: write_ram has no way to report a partial write or a rejected address — the only way to verify is a follow-up retroarch_read_ram. 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). Local input validation rejects empty arrays, > 4096 bytes, or values outside 0-255 before the UDP send.
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 (CHEEVOS, no ack)' where N is the array length you sent. The 'no ack' in the message is a reminder that RetroArch did not confirm the write.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Starting address in the CHEEVOS (achievements) address space — distinct from the libretro system memory map used by retroarch_write_memory. See retroarch_read_ram for address-space caveats. Bytes are written sequentially address, address+1, ... | |
| bytes | Yes | Byte values to write, one per element (each 0-255). Length 1-4096 (hard cap from RetroArch's NCI single-datagram size). Written sequentially from `address`. Because RetroArch does not acknowledge this command, partial / rejected writes cannot be distinguished from successful ones at the protocol level. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses destructive behavior, fire-and-forget nature (no acknowledgment), disabling of hardcore mode, UDP silent drops, and the need for verification. This is comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-organized with clear sections (PURPOSE, USAGE, BEHAVIOR, RETURNS) and front-loaded critical info. It could be slightly more concise, but the detail is necessary for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool complexity, 100% schema coverage, and no output schema, the description covers all necessary aspects: address space distinction, size limits, verification steps, sibling tool relationships, and transport details. It is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with good descriptions, but the description adds important context: address space caveats for 'address' and the lack of acknowledgment for 'bytes'. This extra value justifies a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it writes a byte sequence to emulated memory via the CHEEVOS address space, distinguishing it from retroarch_write_memory which uses the core memory map. The purpose is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use this tool as a fallback when retroarch_write_memory returns 'no memory map defined', and lists prerequisites and follow-up actions (e.g., verify with retroarch_read_ram, create rollback point).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
7 tool updates
v0.1.2- Changed
retroarch_get_config2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / name / descriptionPrevious value: -"Config parameter name (see description for supported values)"New value: +"Config parameter name (case-sensitive). Commonly-supported values: `savefile_directory`, `savestate_directory`, `system_directory`, `cache_directory`, `log_dir`, `runtime_log_directory`, `netplay_nickname`, `video_fullscreen`. RetroArch's exact whitelist varies by version; if a name returns an error, it isn't exposed via the NCI on this build. `screenshot_directory` is NOT exposed by RetroArch — there is no NCI way to query the screenshot output path."
- Changed
retroarch_load_state_slot2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / slot / descriptionPrevious value: -"Save state slot number"New value: +"Save state slot number to load from. RetroArch's standard slot range is 0-9 (ten slots), but the NCI does not enforce a hard upper bound — slot numbers outside the configured range will simply find no file and silently no-op. This call does NOT change the currently-selected slot pointer (use retroarch_state_slot_plus / retroarch_state_slot_minus for that)."
- Changed
retroarch_read_memory4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / address / descriptionPrevious value: -"Memory address (in the core's address space)"New value: +"Starting address in the libretro core's system memory map (NOT the CHEEVOS address space — that's read_ram). Address layout depends on the loaded core: e.g. SNES WRAM is typically at 0x7E0000-0x7FFFFF, GBA EWRAM at 0x02000000-0x0203FFFF, Genesis 68K RAM at 0xFF0000-0xFFFFFF. Reads `length` consecutive bytes starting here." - added
Input schema / properties / address / minimumAdded value: +0 - added
Input schema / properties / length / descriptionAdded value: +"Number of consecutive bytes to read (1-4096). Hard cap is RetroArch's NCI single-datagram size; chunk larger reads yourself. RetroArch may return fewer bytes if the read crosses a memory-region boundary in the core's descriptor list."
- Changed
retroarch_read_ram4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / address / descriptionAdded value: +"Starting address in the CHEEVOS (achievements) address space — distinct from the libretro system memory map used by retroarch_read_memory. CHEEVOS addresses follow per-system conventions used by RetroAchievements (e.g. SNES CHEEVOS addresses for WRAM start at 0x000000, not the SNES system bus 0x7E0000). If unsure, retroarch_read_memory is usually the right starting point." - added
Input schema / properties / address / minimumAdded value: +0 - added
Input schema / properties / length / descriptionAdded value: +"Number of consecutive bytes to read (1-4096). Hard cap is RetroArch's NCI single-datagram size. May return fewer bytes at region boundaries."
- Changed
retroarch_show_message2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / message / descriptionPrevious value: -"Message text. Spaces are kept; line breaks are not."New value: +"Message text to display. Spaces inside the string are preserved; line breaks (\\n / \\r) are NOT — the NCI protocol is line-terminated, so newlines truncate the message. Keep messages short (one line, ~80 chars) to fit RetroArch's notification overlay without clipping. Consecutive calls replace the previous message rather than queueing."
- Changed
retroarch_write_memory4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / address / descriptionPrevious value: -"Memory address"New value: +"Starting address in the libretro core's system memory map (NOT CHEEVOS space). Bytes are written sequentially address, address+1, ..., address+N-1." - added
Input schema / properties / address / minimumAdded value: +0 - added
Input schema / properties / bytes / descriptionAdded value: +"Byte values to write, one per element (each 0-255). Length 1-4096 (hard cap from RetroArch's NCI single-datagram size). Written sequentially from `address`. If a read-only descriptor is encountered mid-array, the write stops at that boundary and the response reports how many bytes actually landed."
- Changed
retroarch_write_ram4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / address / descriptionAdded value: +"Starting address in the CHEEVOS (achievements) address space — distinct from the libretro system memory map used by retroarch_write_memory. See retroarch_read_ram for address-space caveats. Bytes are written sequentially address, address+1, ..." - added
Input schema / properties / address / minimumAdded value: +0 - added
Input schema / properties / bytes / descriptionAdded value: +"Byte values to write, one per element (each 0-255). Length 1-4096 (hard cap from RetroArch's NCI single-datagram size). Written sequentially from `address`. Because RetroArch does not acknowledge this command, partial / rejected writes cannot be distinguished from successful ones at the protocol level."
17 tool updates
v0.1.1- First observed
retroarch_frame_advance - First observed
retroarch_get_config - First observed
retroarch_get_status - First observed
retroarch_load_state_current - First observed
retroarch_load_state_slot - First observed
retroarch_pause_toggle - First observed
retroarch_ping - First observed
retroarch_read_memory - First observed
retroarch_read_ram - First observed
retroarch_reset - First observed
retroarch_save_state_current - First observed
retroarch_screenshot - First observed
retroarch_show_message - First observed
retroarch_state_slot_minus - First observed
retroarch_state_slot_plus - First observed
retroarch_write_memory - First observed
retroarch_write_ram
TDQS
Every tool has a clearly distinct purpose. Memory read/write tools are explicitly differentiated by API (core memory map vs. CHEEVOS), save/load state tools distinguish between current slot and specific slot, and control tools (pause, reset, frame advance) have non-overlapping functions. The descriptions thoroughly clarify boundaries.
All tool names follow a consistent 'retroarch_verb_noun' pattern in snake_case (e.g., retroarch_read_memory, retroarch_pause_toggle, retroarch_state_slot_plus). Verbs are imperative and nouns are specific, making the naming predictable and self-explanatory.
17 tools cover the necessary operations for emulator control via RetroArch's NCI: connectivity, status, config, controls, state management, memory access, screenshot, and messaging. The count is well-scoped for the domain, with no superfluous tools and no critical gaps.
The tool set covers all major NCI capabilities: connectivity check, status, config, pause/reset/frame advance, save/load state with slot management, memory read/write via two APIs, screenshot, and OSD messaging. Within the scope of runtime emulator control, it is fully complete.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Official remote MCP server for Archivist AI TTRPG campaign memory: characters, sessions, and more.
The official MCP Server for the Mux API
- ArcjetOAuthcom.arcjet
An MCP server for Arcjet - the runtime security platform that ships with your AI code.
Cloud-hosted MCP server for durable AI memory
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP 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.14262MIT
- AlicenseAqualityBmaintenanceMCP server for the mGBA Game Boy Advance emulator. Read and write GBA memory, inject button presses, take screenshots, save/load state, and step the emulator through a Lua bridge.18362MIT
- AlicenseAqualityCmaintenanceMCP server for BizHawk, the multi-system emulator. Drive NES, SNES, GB/GBC/GBA, Genesis, N64, PSX, Saturn and more through one Lua bridge — memory r/w across named domains, joypad input, frame-advance, screenshot, save/load state.20264MIT
- AlicenseAqualityCmaintenanceAn MCP server that exposes PPSSPP — the PlayStation Portable emulator — to any MCP-compatible client (Claude Desktop, Claude Code, etc.) via PPSSPP's built-in WebSocket debugger interface. Read and write PSP memory, drive games with button input, capture screenshots, set CPU breakpoints, inspect MIPS Allegrex registers — all through a clean tool interface. No bridge plugin needed; PPSSPP's debugg23256MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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-retroarch'
If you have feedback or need assistance with the MCP directory API, please join our Discord server