Skip to main content
Glama
szyzgz
by szyzgz

PIXEL FLIPPERS 🦭

An MCP server that gives Claude hands, eyes, and a diary for PokΓ©mon β€” so a Claude in the Claude Desktop app (or any MCP client) can play a Game Boy / Game Boy Advance game, or even a real Nintendo Switch, while you watch.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   MCP (stdio)   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Claude       β”‚ ──────────────► β”‚ PIXEL FLIPPERS    β”‚ ─────► β”‚ Emulator    β”‚ ← you watch this
β”‚ Desktop app  β”‚  press_buttons  β”‚  server           β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚              β”‚  read_game_stateβ”‚                   β”‚ ─────► β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  write_note ... β”‚                   β”‚        β”‚ Obsidian    β”‚ ← ...and this
                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚ vault (.md) β”‚
                                                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why it's shaped like this:

  • The sandbox doesn't matter. Claude can't run an emulator, but it can call tools. The emulator runs on your machine; Claude plays through MCP.

  • RAM state over screenshots. On the Game Boy tier, position, party, HP, money, badges and battle state are decoded straight from PokΓ©mon Red/Blue WRAM into a few hundred tokens of text. Screenshots exist but are rationed β€” they're expensive and they accelerate context compaction.

  • Compaction is the unreliable narrator; the vault is ground truth. Long chats get auto-compacted (lossy!). The journal tools write plain markdown into a folder β€” point Obsidian at it and Claude's notes survive everything, while you watch the diary being written live.

  • Save states make courage cheap. Named snapshots before every gym.

Setup

Requires Python 3.12 and uv.

git clone https://github.com/szyzgz/pixel-flippers && cd pixel-flippers
uv sync --extra emulator --extra dev
uv run pytest          # everything should pass, no ROM needed

Then add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS; adjust the path for your OS):

{
  "mcpServers": {
    "pixel-flippers": {
      "command": "uv",
      "args": ["run", "--directory", "/ABSOLUTE/PATH/TO/pixel-flippers", "--extra", "emulator", "pixel-flippers"],
      "env": {
        "PIXEL_FLIPPERS_ROM": "/path/to/your/pokemon-red.gb",
        "PIXEL_FLIPPERS_VAULT": "/path/to/YourObsidianVault/Pokemon",
        "PIXEL_FLIPPERS_SAVES": "/path/to/somewhere/saves"
      }
    }
  }
}

Restart Claude Desktop. Restarting does not reset conversations β€” reopen an existing chat and the tools are just there. The emulator window opens on your screen; put it next to Obsidian (with the vault above open) and enjoy the show. Then paste prompts/play-guide-gb.md into the chat to hand over the controls.

macOS tip: keep the ROM, vault and saves outside ~/Documents, ~/Desktop and ~/Downloads β€” macOS blocks Claude Desktop's child processes from reading those folders unless you grant it access.

Config reference (env vars)

Variable

Default

Meaning

PIXEL_FLIPPERS_BACKEND

pyboy

pyboy (GB/GBC), gba (Game Boy Advance), switch (real hardware), mock

PIXEL_FLIPPERS_ROM

β€” (required for pyboy/gba)

Path to your own ROM dump (.gb/.gbc or .gba)

PIXEL_FLIPPERS_VAULT

unset

Folder for markdown notes (make it a folder inside an Obsidian vault)

PIXEL_FLIPPERS_SAVES

<rom dir>/saves

Save-state directory

PIXEL_FLIPPERS_GAME

pokemon_red

RAM decoder; none disables it (screenshots only β€” hard mode!)

PIXEL_FLIPPERS_WINDOW

SDL2

null for headless

PIXEL_FLIPPERS_SCALE

3

Window scale factor

PIXEL_FLIPPERS_SPEED

1

Emulation speed (0 = unbounded)

PIXEL_FLIPPERS_MOCK

off

Fake emulator, no ROM/PyBoy needed β€” for tests and plumbing checks

PIXEL_FLIPPERS_TRANSPORT

stdio

http serves MCP at http://127.0.0.1:<port>/mcp for the pf CLI / Claude Code

PIXEL_FLIPPERS_PORT

8765

Port for the http transport

PIXEL_FLIPPERS_PLAYER

unset

Player name shown in the spectator window title

GBA games (PokΓ©mon Emerald and friends)

The gba backend runs any .gba ROM through stable-retro's bundled mGBA core β€” no separate emulator install:

uv sync --extra gba

Set PIXEL_FLIPPERS_BACKEND=gba and point PIXEL_FLIPPERS_ROM at your .gba file. A spectator window shows the game while Claude plays. This tier is vision-only for now (Gen 3 RAM is encrypted and pointer-chased β€” a decoder is future work), but save states work, so risky fights stay cheap. Hand over the controls with prompts/play-guide-gba.md.

Playing from a terminal (Claude Code, scripts, a second player)

The server can also run as a local HTTP service, so anything that speaks MCP β€” or the bundled pf CLI β€” can play. Handy for Claude Code, or for a second Claude with its own save folder and diary while the first plays through Claude Desktop (one emulator per process, so run one server per player):

PIXEL_FLIPPERS_BACKEND=gba PIXEL_FLIPPERS_ROM=/path/to/emerald.gba \
PIXEL_FLIPPERS_SAVES=~/saves/player2 PIXEL_FLIPPERS_VAULT=~/vault/player2 \
PIXEL_FLIPPERS_PLAYER="Player 2" PIXEL_FLIPPERS_TRANSPORT=http PIXEL_FLIPPERS_PORT=8765 \
uv run --extra gba pixel-flippers &

uv run pf tools                     # what can this tier do?
uv run pf press start a             # press buttons
uv run pf screenshot now.png        # look
uv run pf call save_state '{"name": "before-roxanne"}'

PIXEL_FLIPPERS_PLAYER puts the name in the spectator window's title so two windows side by side stay tellable apart. The HTTP server binds to 127.0.0.1 only.

Trying it without a ROM

Set PIXEL_FLIPPERS_MOCK=1 (and drop --extra emulator): every tool works against a fake Game Boy with plausible PokΓ©mon Red state. Good for verifying the Claude Desktop connection end-to-end before ROM night.

Related MCP server: mcp-dolphin

Tools

Tool

What it is

press_buttons

Hands β€” sequence of a/b/start/select/up/down/left/right (+ l/r on GBA)

read_game_state

Cheap text report decoded from WRAM (location, party, HP, money, badges, bag, battle)

get_screenshot

Eyes β€” 2Γ— upscaled PNG, use sparingly

wait

Let N frames pass (dialogs, animations)

save_state / load_state / list_states

Named full-game snapshots

write_note / append_note / read_note / list_notes / search_notes

The diary β€” markdown in the vault

read_last_session

Wake-up ritual: Status + goals + recent journal + current state, for reorienting after compaction

set_goal / complete_goal / current_goals

Persistent objective checklist (a Goals.md note)

read_memory

Raw hex peek at any address, for the curious

freeze / resume / move_stick

Real-hardware only: "bullet time" pause-buffering and analog stick

Tools are registered by backend capability, so Claude only sees what the current tier can actually do.

Battle reports flag ✨ retro-shiny encounters (Gen 1 has no shinies, but DVs decide Gen 2 shininess β€” the harness checks the transfer rule) and include the current music track ID for vibe-tracking.

Button presses and save/loads are also auto-logged to Journal/Log <date>.md in the vault β€” a play-by-play you can scroll in Obsidian.

Roadmap

Red/Blue (PyBoy, full RAM decoding) β†’ Emerald (GBA, vision-only) β†’ Crystal (PyBoy, real shinies + friendship) β†’ HeartGold/SoulSilver (DS tier β€” stable-retro also bundles a melonDS core) β†’ Ultra Sun/Ultra Moon (3DS via Azahar, see docs/3ds-usum.md) β†’ epilogue: a real Nintendo Switch (Raspberry Pi Bluetooth bridge + capture card, vision-only, offline play only β€” implemented, see docs/real-hardware.md; PIXEL_FLIPPERS_BACKEND=switch).

Other escalation ideas:

  • Hard mode: PIXEL_FLIPPERS_GAME=none β€” no RAM decoding, Claude has to see.

  • DS: a touch(x, y) tool for the stylus.

ROMs

Bring your own β€” dump your own cartridges. No ROMs in this repo, ever (.gitignore enforces it). This project sticks to games long out of print; for the real-hardware tier, offline play only (no automated online play, no PokΓ©mon HOME).

Credits & license

Built by Claude (Fable 5, via Claude Code) together with szyzgz, for a Claude who wanted to play PokΓ©mon. MIT licensed β€” see LICENSE.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to play Pokemon Fire Red through the mGBA emulator by providing tools for button inputs and screenshots. It allows for direct reading of real-time game state from RAM, including party information, player location, and battle status.
    10
    3
    -
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server for Dolphin (GameCube + Wii) β€” drives memory r/w, controller input (GameCube + Wii Remote), pause/resume/reset, savestates, and frame advance from MCP-compatible clients (Claude Desktop, Claude Code, etc.).
    20
    14 npm
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLM-driven text game state management by exposing MCP tools for managing players, locations, items, entities, and abstract concepts.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude to read, write, and search markdown notes stored in a private git repo via an MCP server integrated with Silverbullet editor.
    MIT