MCP Server for Pokemon × Claude

LAPRAS(ラプラス)

自ら学び、自ら進む。
Claude Code が Pokemon Red を自律プレイする MCP Server。

Featured Pokemon

Architecture

graph LR
    CC["Claude Code
画面認識 + 判断"] -->|"stdio"| MCP["MCP Server
gameboy_mcp_server.py"] MCP -->|"TCP :9876"| EMU["emulator.py
TCP Client"] EMU -->|"TCP"| PB["pyboy_server.py
PyBoy 60fps + SDL2"] PB -->|"JSON"| EMU PB -->|"mmap
/tmp/pyboy_screen.shm"| API["game_state_api.py
SSE 配信"] EMU -->|"応答"| MCP MCP -->|"stdio"| CC style CC fill:#1a0a0a,stroke:#f8d030,color:#f8d030 style MCP fill:#3a1010,stroke:#e03030,color:#f0e8e0 style EMU fill:#3a1010,stroke:#e03030,color:#f0e8e0 style PB fill:#3a1010,stroke:#e03030,color:#f0e8e0 style API fill:#3a1010,stroke:#e03030,color:#f0e8e0

↺ Claude が自律的にループ — 配信は共有メモリ (mmap) で画面を直接読み取り

Boot Sequence

Claude Code 起動からゲームプレイまでの起動シーケンス。PyBoy サーバーは別プロセスで動作し、TCP 経由で接続する。

1

PyBoy サーバー起動(別プロセス)

pyboy_server.py を別ターミナルで起動。SDL2 ウィンドウが表示され、TCP :9876 で待受開始。

2

Claude Code 起動

このディレクトリで Claude Code を開くと .mcp.json を自動検出。MCP サーバーが子プロセスとして起動。

3

load_rom → TCP 接続

Claude Code が load_rom を呼ぶと、emulator.py が TCP 経由で pyboy_server.py に接続。ROM ヘッダから JP/EN を自動判定。

4

ゲームプレイ開始

以降、Claude Code → MCP (stdio) → TCP → PyBoy サーバーに対して操作が続く。SDL2 ウィンドウでリアルタイム表示。

5

配信オーバーレイ(オプション)

game_state_api.py が共有メモリ (mmap) から画面を直接読み取り、SSE でブラウザに配信。16:9 ポケモン赤テーマ。

graph TD
    subgraph parent["Claude Code(親プロセス)"]
        CC[Claude Code]
    end

    CC -->|"stdio (JSON-RPC)"| MCP
    MCP -->|"stdio 応答"| CC

    subgraph child["子プロセス: gameboy_mcp_server.py"]
        MCP["FastMCP
gameboy_mcp_server.py"] MCP -->|"関数呼び出し"| EMU["emulator.py
(TCP クライアント)"] EMU -->|"応答 (JSON)"| MCP end EMU -->|"TCP :9876 コマンド送信"| SRV SRV -->|"TCP 応答 (JSON)"| EMU subgraph server["別プロセス: pyboy_server.py"] SRV["PyBoy TCP サーバー
PNG 生成 → mmap"] SRV --- PB["PyBoy エミュレータ
60fps + SDL2 表示"] end SRV -->|"mmap
/tmp/pyboy_screen.shm"| API subgraph optional["オプション: game_state_api.py"] API["FastAPI + SSE
配信オーバーレイ"] end API -->|"emulator.py を import
TCP :9876 経由で状態取得"| EMU2["emulator.py
(共有 TCP 接続)"] EMU2 -->|"TCP :9876"| SRV CC -->|"移動経験を自動蓄積"| NAV["nav_memory.py
自己学習ナビ"] CC -->|"プレイ経験を記録"| MEM["CLAUDE.md / Memory
自己改善ルール"] style parent fill:#1a0a0a,stroke:#e03030,stroke-width:2px,color:#f0e8e0 style child fill:#2a1010,stroke:#e03030,stroke-width:2px,color:#f0e8e0 style server fill:#2a1010,stroke:#f8d030,stroke-width:2px,color:#f0e8e0 style optional fill:#1a0a0a,stroke:#8a7a70,stroke-width:1px,stroke-dasharray:5,color:#f0e8e0 style CC fill:#3a1010,stroke:#f8d030,color:#f8d030 style MCP fill:#3a1010,stroke:#e03030,color:#f0e8e0 style EMU fill:#3a1010,stroke:#e03030,color:#f0e8e0 style SRV fill:#4a1515,stroke:#f8d030,color:#f8d030 style PB fill:#4a1515,stroke:#f8d030,color:#f8d030 style API fill:#2a1515,stroke:#8a7a70,color:#8a7a70 style EMU2 fill:#2a1515,stroke:#8a7a70,color:#8a7a70 style NAV fill:#1a2010,stroke:#48d848,color:#48d848 style MEM fill:#1a2010,stroke:#48d848,color:#48d848

※ 双方向矢印は要求/応答フロー / 緑ノードは自己改善(マップ学習 + ルール蓄積)

How it Works

TCP Client/Server

PyBoy を別プロセスで SDL2 ウィンドウ付き起動。MCP サーバーが TCP 経由でリモート操作。

JP/EN Auto-Detect

ROM ヘッダから日本語版/英語版を自動判定。文字テーブルを自動切替。

Auto Screen Return

ボタン操作後に wait_frames 分待って画面を自動返却。ツール呼び出し回数を半減。

Separate Process

PyBoy は別プロセスで常時 60fps + SDL2 表示。MCP サーバーとは TCP で疎結合。

Self-Improvement

移動経験を nav_memory.py が自動学習。操作ノウハウを CLAUDE.md / Memory に記録し、次回プレイに活用。

Director Direct

LLMアドバイザー不要。battle_calc + nav_memory + objective の計算モジュールを Director が直接使い、全判断を実行。

Play Flow

1

ROM をロード

load_rom("/path/to/pokemon_red.gb") でエミュレータ起動

2

状態確認

get_game_state で構造化 JSON を取得。シーン・座標・手持ちを把握

3

操作実行

press_button で1ステップ操作、do_action で移動/テキスト送り。バトルは press_button で1手ずつ進める

4

判断 & 繰り返し

返ってきた画面/JSON を見て次のアクションを決定。2-4 を自律的にループ

5

自己改善

移動の成功・失敗を nav_memory.py が自動記録。壁・行き止まり・マップ遷移を学習し、次回は最短ルートで移動

MCP Tools

ToolArgsDescription
press_buttonbutton, wait_frames, include_imageボタンを押す。デフォルトJSON、include_image=trueで画面付き
press_buttonsbuttons, interval_ms, wait_framesボタン連続入力、最後に画面を返す
hold_buttonbutton, frames, wait_framesボタン長押し後に画面を返す
waitseconds指定秒数待って画面を返す
get_game_state-構造化 JSON(scene / プレイヤー / 手持ち / バトル)
get_collision_map-衝突マップ(9x10) + プレイヤー方向 + NPC + ドア位置
get_wide_map-マップ全体の歩行可否(三状態: 2=確認済歩行可, 0=壁, -1=未探索) + 草むらグリッド
press_button_fastbutton, wait_framesボタン押下 + JSON 状態を返す(画像なし)
press_buttons_fastbuttons, interval_ms連続入力 + JSON 状態を返す(画像なし)
do_actionaction, count, direction歩行・テキスト送りをまとめて実行。エンカウント/マップ遷移で中断
navigate_totarget_x, target_y, target_map_id自己学習型ナビで目的地まで自動移動
navigate_smarttarget_type, direction, target_map_id意図ベース移動(exit/explore/transition/grass)
load_romrom_path, headlessROM をロードしてエミュレータ起動
quit_emulator-エミュレータ停止(セーブ付き)
saytextClaude の実況コメントをオーバーレイに表示
get_emulator_info-エミュレータの状態確認

Director Direct Architecture

LLMアドバイザーを廃止し、Director が計算モジュールを直接使って全判断を行うシンプル構成。

graph TD
    DIR["Director
Claude Code Opus
MCP 操作 + 全判断"] -->|"MCP stdio"| MCP["gameboy_mcp_server.py"] BC["battle_calc.py
タイプ相性 + ダメージ推定"] -->|"計算済みデータ"| DIR NM["nav_memory.py
自己学習マップ知識"] -->|"歩行実績 + 草タイル"| DIR NA["nav_analyst.py
リアルタイム分析"] -->|"毎歩自動実行"| DIR OBJ["objective.py
目標管理"] -->|"進捗追跡"| DIR style DIR fill:#3a1010,stroke:#f8d030,color:#f8d030 style MCP fill:#3a1010,stroke:#e03030,color:#f0e8e0 style BC fill:#1a2010,stroke:#48d848,color:#48d848 style NM fill:#1a2010,stroke:#48d848,color:#48d848 style NA fill:#1a2010,stroke:#48d848,color:#48d848 style OBJ fill:#1a2010,stroke:#48d848,color:#48d848

LLMアドバイザー不要。battle_calc + nav_memory + objective の計算結果を Director が直接読んで判断。

🎮 Director

Claude Code セッションが MCP 経由でゲームを操作。battle_calc・nav_memory・objective を直接使い、全ての判断を自ら行う。

📊 battle_calc.py

Gen1 タイプ相性表(15x15)、全165技、151種族のタイプデータ。STAB・ダメージ%を事前計算し、Director の技選択を支援。

🗺️ nav_memory.py

歩行中に壁・遷移・草タイルを自動蓄積。wide_map のキャッシュデータと草むら判定(エンカウント実績ベース)を提供。

📡 nav_analyst.py

do_action 毎にリアルタイム分析を自動実行。フロンティア検出・出口情報・ループ検出を Director に返す。

🎯 objective.py

目標設定・進捗追跡・再評価トリガー。grind/gym/heal/explore/story の目標タイプを管理。

🔧 collision_map.py

衝突マップ生成、A* パスファインダー、wide_map 全体マップ構築。三状態システム(確認済/壁/未探索)でA*が未探索エリアも通過可能。

Buttons

A
B
Start
Select
Up
Down
Left
Right

wait_frames Guide

Scenewait_framesTime
Menu select10 (default)~0.17s
Text advance20~0.33s
Character move15~0.25s
Screen transition30-60~0.5-1s
Battle animation60-180~1-3s

Setup

# Python 環境 python3 -m venv .venv .venv/bin/pip install -r requirements.txt # Claude Code をこのディレクトリで起動 # .mcp.json により gameboy MCP サーバーが自動接続 # Claude に指示する # 例: 「ポケモン赤をロードしてプレイして」

Tech Stack

Python 3.10+Runtime
PyBoy 2.7.0GB/GBC Emulator
MCP SDK 1.26+Claude Code Protocol
Pillow 10+Image Processing

MCP Server Implementation

MCP Configuration

.mcp.json

Claude Code がこのディレクトリで起動すると、以下の設定で MCP サーバーが自動接続される。

{ "mcpServers": { "gameboy": { "command": ".venv/bin/python3", "args": ["src/gameboy_mcp_server.py"], "env": { "PYTHONPATH": "src" } } } }

gameboy_mcp_server.py

src/gameboy_mcp_server.py

FastMCP で構築された MCP サーバー本体。全 16 ツールを公開し、stdio トランスポートで通信する。

Button Tools (4)

  • press_button — ボタン押下(デフォルトJSON、画像オプション)
  • press_buttons — 連続入力、最後に画面を返す
  • hold_button — 長押し + リリース後の画面を返却
  • wait — 指定秒数待機 + 画面を返却

State Tools (4)

  • get_game_state — 構造化 JSON(scene/手持ち/バトル)
  • get_collision_map — 衝突マップ + NPC位置
  • press_button_fast — ボタン押下 + JSON 状態を返す
  • press_buttons_fast — 連続入力 + JSON 状態を返す

Composite Tools (2)

  • do_action — 歩行・テキスト送りをまとめて実行
  • navigate_to — 自己学習型ナビで自動移動

Lifecycle & Utility (4)

  • load_rom — ROM ロード + エミュレータ起動
  • quit_emulator — セーブ付きで停止
  • get_emulator_info — 実行状態とカートリッジ情報
  • say — Claude の実況コメントをオーバーレイに表示

collision_map.py

src/collision_map.py

画面内衝突マップ(9x10)生成 + マップ全体の wide_map 構築 + A* パスファインダーで経路探索する。

  • 画面内: 18x20 タイルマップ → 9x10 グリッドにダウンサンプリング
  • wide_map: 三状態(2=walkable, 0=wall, -1=unknown)、A*はunknownをコスト3で通過
  • collision_cache: nav_memory.jsonに永続化、サーバー再起動後も維持
  • 草むらグリッド: nav_memory のエンカウント実績から生成
  • A* アルゴリズムで壁・NPC を避けた最短経路探索
  • タイルペア衝突テーブルでレッジ(段差)の一方通行を考慮
  • NPC を障害物として扱う動的衝突更新
  • ASCII マップ表示(█=壁, ·=通路, S=NPC, ↓=プレイヤー)

battle_calc.py

src/battle_calc.py

Gen1 バトル計算エンジン。タイプ相性・技データ・ダメージ推定を提供し、Battle Advisor に計算済みデータを渡す。

  • Gen1 タイプ相性表(15×15)— 等倍/半減/無効/4倍を正確に計算
  • 全165技のデータベース(タイプ・威力・命中率・物理/特殊/変化)
  • 全151種族のタイプデータ(単タイプ・複合タイプ)
  • enrich_battle_context() — 相性ラベル・ダメージ%・STAB判定・交代候補の防御相性を一括計算
  • 固定ダメージ技(ソニックブーム、りゅうのいかり等)や一撃必殺技の特別処理

agent_log.py

src/agent_log.py

Director の状態追跡。稼働状態をオーバーレイにリアルタイム表示する。

  • Director のライフサイクル管理(IDLE → THINKING → DONE → IDLE)
  • タイムアウト: THINKING 60秒 / DONE 10秒 で自動 IDLE 復帰
  • SSE agents イベントで変化時のみ配信

emulator.py

src/emulator.py

PyBoy TCP クライアント。pyboy_server.py に接続してエミュレータを操作する。

  • シングルトン PyBoy インスタンスを threading.Lock で排他制御
  • バックグラウンドスレッドで _tick_loop が 60fps でフレーム進行
  • get_screen_bytes — PIL Image → JPEG bytes 変換(MCP用)。配信は mmap 経由で PNG を直接読み取り
  • press_button — ボタン押下 → wait_frames/60 秒スリープ → 画面返却
  • press_button_hold — 押下 → ホールド → リリース → 画面返却
  • ROM パス検証: .gb / .gbc のみ許可、os.path.realpath で解決
  • ウィンドウモード: SDL2(GUI)/ null(headless)を選択可能

Target Game

Pokemon Red / Blue (Gen1)

赤・青の両バージョンに対応。ターン制バトル + マップ移動で MCP 操作との相性が良い。

History

v1 - 2026/03/29

screencapture + Anthropic API ループ方式で初期実装

v2 - 2026/03/31

PyBoy + MCP サーバー方式に全面書き換え。wait_frames による画面自動返却

v2.1 - 2026/04/04

ダッシュボード削除、get_screen 削除、プロジェクト紹介 HTML 追加

v3 - 2026/04/04

scene 検出(8シーン)、複合ツール(do_action)、技名テーブル165件、配信オーバーレイ(ポケモン赤テーマ、anime.js)、アクションログ、PokeAPI スプライト連携

v3.1 - 2026/04/04

TCP クライアント/サーバー分離(SDL2 ウィンドウ表示対応)、日本語版 ROM 自動判定、ひらがな文字テーブル追加、シーン検出のゲーム開始直後誤判定修正

v3.2 - 2026/04/05

ボタン入力修正(button_press/release 方式)、_INTERNAL_TO_DEX 全面修正、マップナビゲーションデータ(map_data.py)、配信オーバーレイ JSON 表示、シーン検出バトル優先判定、do_action エンカウント中断検出、ビューワー UI リデザイン(ポケモン赤テーマ)、初テストプレイ完了(マサラ → トキワ → 図鑑入手)

v3.3 - 2026/04/06

衝突マップ & A* パスファインダー実装(壁自動迂回)、navigate_to に A* 迂回統合(_walk_toward が壁検出時に自動で迂回路を探索)、Route 1 通過 → トキワシティ到着、ヒトカゲ Lv.9(ひのこ習得)

v3.4 - 2026/04/07

配信オーバーレイ高速化 — 画面転送を TCP から共有メモリ (mmap) に置き換え、レイテンシ約60倍改善。RGBA→RGB 変換修正、PNG 形式採用でアーティファクト解消。スキャンライン CSS 無効化(H.264 モアレ対策)、プレイヤー名表示追加。音声安定性も確認済み

v3.5 - 2026/04/07

トークン効率 & TCP 最適化 — bulk read で TCP 40-60回→1-2回、collision_map 分離(毎回300-400 tokens 節約)、do_action(walk) 毎歩チェック廃止(scene バイトのみ)、press_button 画像オプショナル化、ステートキャッシュ層追加。20歩ウォークで約95%トークン削減

v3.6 - 2026/04/07

自己学習ナビゲーション(nav_memory.py)、マップ遷移検出追加(do_action/navigate_to で建物出入り時に自動wait)、ポケモンセンター出口座標修正

v3.7 - 2026/04/07

プロジェクト整理 — CLAUDE.md 65%削減(MCPツール一覧の重複除去)、ルールファイル10→4に統合(69%削減)、メモリファイル整理、map_data.py 削除(nav_memory.py に完全移行)、デッドコード検出、README.md 更新

v4.0 - 2026/04/07

マルチエージェント ゲームプレイ — Director+Advisor 型構成を実装。battle_calc.py(Gen1 タイプ相性表 15×15、全165技、151種族タイプ、ダメージ推定)、4 アドバイザー(Battle/Nav/Strategist/Map Analyst)、エージェント状態可視化(agent_log.py → オーバーレイ AGENTS パネル)、Claude 実況 MCP ツール(say)、collision_map の AI LOG 表示、セッションイベントログ、137テスト全通過

v4.1 - 2026/04/07

ワイドマップ&オーバーレイ改善 — get_wide_map MCP ツール追加(マップ全体の衝突データ取得)、オーバーレイ右パネルのコンパクト化(フォント・スプライト・パディング縮小)、Bookmark 機能完全削除、Director 状態のイミュータブル合成に修正、マルチエージェント動作検証(Navigation/Strategist/Map Analyst の並列起動確認)

v4.2 - 2026/04/07

Map Analyst 廃止 & DESIGN.md 導入 — Map Analyst エージェントを nav_memory.get_exploration_stats() に置換(Haiku 1回分のコスト削減)、exploration_stats を Navigation Advisor と Strategist に直接提供、DESIGN.md でデザイントークン統一、英語版 index_en.html 追加

v4.3 - 2026/04/08

草むら検出修正 & 自律ループ — 洞窟上部タイルの草むら誤認識を修正、JP/EN 判定ロジック分離、ドア表示(衝突マップ D 表示)、自律ゲームループ(objective.py で目標管理・Strategist自動トリガー)、セマンティックナビ(smart_nav.py で意図ベース移動)、CLAUDE.md 52%圧縮

v1.0.0 - 2026/04/09 🎉

初の正式リリース — Director 直結アーキテクチャ(LLMアドバイザー廃止、battle_calc + nav_memory + objective で全判断をDirectorが直接実行)。nav_analyst.py(do_action毎にリアルタイムマップ分析)、press_button からcaptureパラメータ完全除去。トキワの森→ニビシティ到達・ポケモンセンター回復・野生ポケモン戦自動処理を実証。

v1.0.1 - 2026/04/13

マップデータ構造修正 & コード整理 — JP/EN のマップデータ構造を修正。wide_map に2層フォールバック導入(collision_cache + ボーダーブロック比較)。草むらグリッドを nav_memory エンカウント実績ベースに変更。不要コード削除。

v2.0.0 - 2026/04/14 — ラプラス 🌊

ナビゲーション全面改善 (P0-P6) & プロジェクト名「ラプラス」 — wide_map 三状態化(unknown≠wall、A*が未探索エリアをコスト3で通過)。衝突判定の精度を100%まで改善。collision_cache を nav_memory.json に永続化(サーバー再起動後も維持)。no_progress 閾値 4→12(迷路で粘る)。フロンティア上限撤廃+多様性スコアリング。HP安全チェック(全滅防止)。ワープ事前記録(マップ遷移時に全ドア自動記録)。PyBoy ヘッドレスモード追加(並列テスト基盤)。Claude Code Agent() による8エージェント並列調査で改善点を発見・実装。JP/EN判定の共通化、不要TCP呼び出し削除などリファクタ実施。

v2.0.1 - 2026/04/16

ナビゲーション座標修正 & ドア回避 — warp座標とplayer座標の系統統一、A*ターゲットのgrid変換に//2追加(navigate_toが短距離で正確到達)。find_pathにドア回避機能追加(navigate_to中に建物に吸い込まれる問題を解消)。stuck時のcollision_cache大量削除を廃止(高精度キャッシュを保護)。壁ヒット時の適応的ウェイポイント選択(no_progress増加に応じてwide_mapの先のウェイポイントを参照し、建物を大きく迂回)。タイルセット情報の動的取得で衝突判定をさらに正確化。pyboy_serverにmark_wall/set_speedコマンド追加。

v2.0.2 - 2026/04/17

レッジ方向判定 & ドア回避統一 — レッジ(段差)の一方通行判定に移動方向チェックを追加(南方向ジャンプは許可、北への登りはブロック)。navigate_toのA*全呼び出しでドア回避ゴール除外を統一(ウェイポイント・画面端ゴールがドア位置と一致しても到達可能に)。_DIR_BLKをモジュール定数に統一しリファクタ。ニビシティジム(タケシ)をHP2で撃破、グレーバッジ獲得。