Skip to main content
Glama
dmang-dev

mcp-retroarch

by dmang-dev

mcp-retroarch

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

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: READ_CORE_MEMORY (system memory map, preferred) and READ_CORE_RAM (CHEEVOS, fallback)

Save / load state

Current slot or explicit slot for load; save is current-slot-only (NCI limitation)

Screenshot

Saved to RetroArch's configured screenshot directory

Pause / frame advance

PAUSE_TOGGLE flips state; FRAMEADVANCE steps one frame

Reset

Hard-reset the running game

On-screen message

Useful for "look here" cues during scripted runs

Game info

Title, system, CRC32

Game-pad input

NCI doesn't expose this. RetroArch has a separate "Remote RetroPad" core on UDP port 55400 that does, but it requires loading that specific core (you can't drive an existing emulation core through it). Not in scope for v0.1.0.

If you need game-pad input on Game Boy Advance specifically, see mcp-mgba. For PCSX2 (memory + savestate only, no input/screenshot), see mcp-pine.

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

npm install -g mcp-retroarch

Option B — npx (no install)

npx -y mcp-retroarch

Option C — clone and develop

git clone https://github.com/dmang-dev/mcp-retroarch
cd mcp-retroarch
npm install

Enable RetroArch's Network Control Interface

Either:

  • GUI: Settings → Network → Network Commands → ON, then confirm Network Cmd Port is 55355 (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-retroarch

Verify:

claude mcp list
# retroarch: mcp-retroarch - ✓ Connected

Claude Desktop

Edit claude_desktop_config.json:

Platform

Path

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "retroarch": {
      "command": "mcp-retroarch"
    }
  }
}

Restart Claude Desktop after editing.

Configuration

Env var

Default

Purpose

RETROARCH_HOST

127.0.0.1

UDP destination host

RETROARCH_PORT

55355

UDP port (must match network_cmd_port in retroarch.cfg)

Tools

Tool

Description

retroarch_ping

Verify reachability — returns RetroArch version

retroarch_get_status

State (playing/paused), system, game, CRC32

retroarch_get_config

Read named RetroArch config values (e.g. savestate_directory)

retroarch_read_memory / retroarch_write_memory

Memory r/w via system memory map

retroarch_read_ram / retroarch_write_ram

Memory r/w via CHEEVOS address space (fallback when no memory map)

retroarch_pause_toggle

Toggle pause state

retroarch_frame_advance

Step one frame (only effective while paused)

retroarch_reset

Hardware-reset the running game

retroarch_screenshot

Save a screenshot to RetroArch's screenshot directory

retroarch_show_message

Display a notification on the RetroArch window

retroarch_save_state_current

Save to currently-selected slot

retroarch_load_state_current

Load from currently-selected slot

retroarch_load_state_slot

Load from explicit slot number

retroarch_state_slot_plus / retroarch_state_slot_minus

Change current slot pointer (NCI has no "set slot to N")

See docs/RECIPES.md for end-to-end examples.

Tested cores

Verified end-to-end against mcp-retroarch:

System

Core

read_memory

read_ram

Notes

Game Boy Advance

mgba_libretro

GBA interrupt vector table visible at 0x0000 (d3 00 00 ea ...)

NES

mesen_libretro

(only NES core tested that does)

Full 16-bit NES address space exposed. WRAM at 0x0000-0x07FF, mirrored to 0x1FFF. CHEEVOS bounded to first 64 KB.

NES

nestopia_libretro

❌ no memory map

CHEEVOS only. 64 KB bound. For NES + memory map, prefer Mesen.

SNES

snes9x_libretro

❌ no memory map

CHEEVOS bounded to ~128 KB (matches SNES WRAM size). 65C816 RTS opcodes (60) visible in code regions.

Sega Mega Drive / Genesis

genesis_plus_gx_libretro

❌ no memory map

⚠️ sparse

CHEEVOS exposes some 68K WRAM addresses but fails at others ("no error message"). Usable if you know specific addresses; blanket sweep doesn't work.

Nintendo 64

mupen64plus_next_libretro

Full N64 RAM exposed. KSEG0 mirror is faithful — read_memory(0x80000000) returns the same bytes as read_memory(0x0). Bound is the connected RAM size (4 MB without Expansion Pak, 8 MB with).

PlayStation 1

swanstation_libretro

❌ no memory map

CHEEVOS only. PSX main RAM begins around CHEEVOS offset 0x010000 (lower addresses are typically zero).

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 (0x80000000 reads as 0x0); Mesen preserves the NES's WRAM mirroring (0x1000 reads as 0x0). This is great for anyone using the bridge alongside disassembly.

  • 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

RetroArch query timed out

Network Commands aren't enabled in RetroArch, or the port doesn't match RETROARCH_PORT. Confirm network_cmd_enable = "true" in retroarch.cfg. Also: UDP datagrams can be dropped under load even on loopback — if a single call times out but a retry succeeds, that's the cause. The bridge doesn't auto-retry; just call again.

READ_CORE_MEMORY failed: no memory map defined

The loaded libretro core doesn't advertise a system memory map. Try retroarch_read_ram (CHEEVOS path) — many cores expose CHEEVOS even without a memory map. Confirmed for SwanStation (PSX); use read_ram for that core.

READ_CORE_MEMORY failed: no descriptor for address

The address isn't covered by the core's memory map. Either a different core would expose it, or the address you want is outside the system bus (e.g. video memory in some cores).

Screenshots don't appear where I expect

RetroArch saves to its configured screenshot directory. The NCI doesn't expose screenshot_directory via GET_CONFIG_PARAM, so check the value via RetroArch's GUI: Settings → Directory → Screenshot.

Can't save to a specific state slot directly

NCI limitation, not a bug. The protocol only exposes "save to current slot" — you have to walk the slot pointer to your target with state_slot_plus/state_slot_minus, then save.

Development

npm install
npm run dev      # tsc --watch

Smoke test against a running RetroArch:

node .scratch/smoke.cjs

Debugging with the MCP Inspector

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

npm run inspector

Build first if you've edited src/ since your last npm install (npm run build, or keep npm run dev running). Override the 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

MIT

Available Tools

17 tools
retroarch_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).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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'.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesConfig 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

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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'.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
slotYesSave 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

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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'.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesStarting 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.
lengthYesNumber 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

A4.9/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesStarting 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.
lengthYesNumber of consecutive bytes to read (1-4096). Hard cap is RetroArch's NCI single-datagram size. May return fewer bytes at region boundaries.

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesMessage 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

A4.4/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesStarting address in the libretro core's system memory map (NOT CHEEVOS space). Bytes are written sequentially address, address+1, ..., address+N-1.
bytesYesByte 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

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
addressYesStarting 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, ...
bytesYesByte 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

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

  1. 7 tool updatesv0.1.2
    • Changedretroarch_get_config2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / name / description
        Previous 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."
    • Changedretroarch_load_state_slot2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / slot / description
        Previous 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)."
    • Changedretroarch_read_memory4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / address / description
        Previous 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."
      • addedInput schema / properties / address / minimum
        Added value: +0
      • addedInput schema / properties / length / description
        Added 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."
    • Changedretroarch_read_ram4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / address / description
        Added 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."
      • addedInput schema / properties / address / minimum
        Added value: +0
      • addedInput schema / properties / length / description
        Added 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."
    • Changedretroarch_show_message2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / message / description
        Previous 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."
    • Changedretroarch_write_memory4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / address / description
        Previous 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."
      • addedInput schema / properties / address / minimum
        Added value: +0
      • addedInput schema / properties / bytes / description
        Added 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."
    • Changedretroarch_write_ram4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / address / description
        Added 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, ..."
      • addedInput schema / properties / address / minimum
        Added value: +0
      • addedInput schema / properties / bytes / description
        Added 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."
  2. 17 tool updatesv0.1.1
    • First observedretroarch_frame_advance
    • First observedretroarch_get_config
    • First observedretroarch_get_status
    • First observedretroarch_load_state_current
    • First observedretroarch_load_state_slot
    • First observedretroarch_pause_toggle
    • First observedretroarch_ping
    • First observedretroarch_read_memory
    • First observedretroarch_read_ram
    • First observedretroarch_reset
    • First observedretroarch_save_state_current
    • First observedretroarch_screenshot
    • First observedretroarch_show_message
    • First observedretroarch_state_slot_minus
    • First observedretroarch_state_slot_plus
    • First observedretroarch_write_memory
    • First observedretroarch_write_ram

TDQS

A4.7/5.0
Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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

ActivityActive
ResponsivenessWithin a week

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

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    MCP server for PCSX2 and other emulators that speak the PINE protocol. Read and write 8/16/32/64-bit emulator memory and control save states for PlayStation-family emulation.
    14
    26
    2
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP 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.
    18
    36
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP 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.
    20
    26
    4
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    An 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 debugg
    23
    25
    6
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dmang-dev/mcp-retroarch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server