64 tools · JSON-RPC 2.0 · cross-platform

An AI assistant that can
actually see your game.

FRED-80 has an MCP (Model Context Protocol) server built into the engine itself. Point Claude, Gemini, or any MCP-capable assistant at a running FRED-80 process and it can read your sprites, watch for Lua errors, press buttons in your live cart, and edit code — without you copy-pasting a single screenshot.

JSON-RPC / TCP Bearer-token auth Local only 9 tool categories

Why this matters.

Normally, getting an AI assistant to help with a game means describing what's on screen, pasting error messages by hand, and never being quite sure the assistant is looking at the same state you are. FRED-80's MCP server closes that loop: the assistant can query the engine directly and act on it — the same running process you're looking at, not a description of it.

Three things to wire up.

FRED-80 speaks MCP over a local TCP socket. Most AI hosts only know how to spawn a process over stdio -- --mcp-bridge is a mode built into fred-80 itself that relays between the two, so no separate script or Python interpreter is needed on any platform.

This needs a local/desktop AI host -- one that can spawn a process on the same machine FRED-80 is running on, e.g. Claude Desktop, Claude Code, Codex CLI, or Gemini CLI. A browser-based assistant (chat.openai.com, claude.ai in a tab, etc.) cannot reach 127.0.0.1 from your machine and will never be able to connect to this, no matter how the config is set up -- that's not a bug to work around, it's what "local only" above means.

01

Launch FRED-80 with a token

$ export FRED80_MCP_TOKEN=some-long-random-string
$ ./fred-80
> :: Windows (cmd)
> set FRED80_MCP_TOKEN=some-long-random-string
> fred-80.exe

The MCP server listens on 127.0.0.1:8090 and only accepts connections that present this token. macOS and Linux since the start; Windows support (Winsock2) landed in 0.8.200, verified compiling and linking clean through the real mingw-w64 cross-toolchain -- not yet confirmed on actual Windows hardware, so treat it as recently-added rather than battle-tested. Amiga/Apollo hardware transport is still a separate, later, opt-in phase and remains stubbed for now. On Windows specifically: the GUI build has no console, so the auto-generated token (if you didn't set one yourself) is written to fred80.log next to the exe instead of the terminal -- check there if you launched without setting FRED80_MCP_TOKEN first. Add --headless to run with no window at all (everything, including screenshot, already reads the internal framebuffer rather than the displayed window, so nothing else changes) -- useful for pure AI-automation with no one watching.

02

Point your AI host at fred-80 --mcp-bridge

{
  "mcpServers": {
    "fred80": {
      "command": "/path/to/fred-80",
      "args": ["--mcp-bridge"],
      "env": { "FRED80_MCP_TOKEN": "some-long-random-string" }
    }
  }
}

--mcp-bridge connects to an already-running fred-80 instance (the one you launched in step 1 -- it never starts a second engine of its own) and relays stdin/stdout to its MCP socket, exactly like a real MCP host expects. This is the same binary either way -- there's nothing extra to download or install, on any platform. Prefer a Python-based setup instead? tools/mcp_bridge.py in the repo still works identically, speaking the same wire protocol.

03

Just ask

Open a cart and describe what you want. The assistant reaches for screenshot, sprite_get, or get_error_log the same way it reaches for any other tool — no special prompting required.

What a session actually looks like.

A real tool-call sequence — no hand-waving. The assistant closes the loop itself: draw, run, look, fix.

you: "the player sprite looks wrong and it won't move when I press right"

sprite_get(n=0) → pixels: [...], hitbox: [...] (spots a stray pixel at 3,3)
sprite_set(n=0, x=3, y=3, color=0) → ok
get_error_log() → "main.lua:24: attempt to compare nil with number" (age_ms: 1200)
cart_read_sheet(name="main") → ... finds a typo: btn(RIGHT) instead of btn(right) ...
cart_write_sheet(name="main", content="...") → ok
reload_cart() → ok
inject_input(btn="right", hold_ms=300) → ok
screenshot() → [image] — player sprite fixed, now moving right

A different session — composing a soundtrack and shipping a finished cart, without ever opening the TOMMY tab by hand.

you: "give the title screen a simple 4-note bassline, then export the cart"

aud_pattern_set_channel(pattern=0, channel=0, wave=2, vol=80) → ok — channel 0's instrument for this pattern is now a triangle wave at vol 80
aud_pattern_draw(pattern=0, channel=0, notes=[13,13,17,20,13,13,17,20,...]) → ok — whole channel written in one call, not 16 separate ones
cart_search_symbol(query="_update") → main.lua:14 — confirms the game loop is already wired up before shipping
cart_export() → {"path": "fred80/dungeon.f80", "files_skipped": 0} — ready to copy to real A6000 hardware

64 tools, 9 categories.

Everything the engine already does for a human in the editor, exposed the same way to an assistant.

Diagnostics

8 tools
  • engine_ping
  • get_telemetry
  • get_error_log
  • get_palette
  • get_game_state
  • list_globals
  • docs_search
  • check_a6000_perf

Sprites

6 tools
  • sprite_get / sprite_set
  • sprite_draw
  • sprite_fill_rect
  • sprite_hitbox_set
  • sprite_export

Tilemaps & Iso

9 tools
  • map_load
  • map_get / map_set
  • map_draw
  • map_export
  • iso_set / iso_get
  • iso_fill_height
  • iso_info

Voxels

6 tools
  • voxel_get / voxel_set
  • voxel_fill_plane
  • voxel_fill_row
  • voxel_rebuild_hull
  • voxel_info

Audio

5 tools
  • sfx / music
  • note
  • snd_load / snd_play

TOMMY

7 tools
  • aud_pattern_get
  • aud_pattern_set_note
  • aud_pattern_draw
  • aud_pattern_set_channel
  • aud_pattern_set_steps
  • aud_song_get / aud_song_set

3D

13 tools
  • poly_build
  • mesh_load / tex_load
  • collider_mesh_add / _remove
  • collider_box_add / _remove
  • collider_clear
  • move_and_slide
  • raycast3d
  • world_place / world_list / world_remove

Cart & code

8 tools
  • cart_create / cart_open
  • cart_read_sheet / cart_write_sheet
  • cart_list_sheets
  • cart_search_symbol
  • cart_export
  • reload_cart

Play-testing

2 tools
  • inject_input
  • screenshot

What it can't do (on purpose).

Every tool is tagged by how much it can change, so a host can reason about — or ask you to confirm — anything beyond a read.

Diagnostic / Telemetry

Read-only. Screenshots, sprite/palette/error readback, fps and frame timing. Can't change anything.

Mutate

Changes cart state — sprite pixels, tilemap cells, voxels, a played sound, an injected button press. Reversible by re-editing or re-running.

Destructive

reload_cart restarts the cart from a fresh Lua state — all in-memory runtime state (score, position) is lost, same as pressing F5. cart_open discards whatever cart was previously open in the editor, same as the manual HOME flow.

The server only binds to 127.0.0.1 and requires a bearer token set by whoever launches FRED-80 — it's not reachable over the network, and there's nothing to configure beyond the token. execute_lua_eval (arbitrary Lua from the assistant) is deliberately not shipped yet — it needs real sandboxing first.

Try it yourself

Full tool schemas and parameters

Every tool listed here has a full parameter reference, defaults, and gotchas documented alongside the rest of the Lua API.