はじめに
ポケモンチャンピオンズの選出画面、制限時間ありますよね。
相手のパーティを見て、タイプ相性を頭の中で計算して、「こおり一貫してるな…」「でもこっちを出すとじめんが重い…」と考えているうちに時間が過ぎていく。結局なんとなくで3体を選んで、試合後に「あの選出は間違いだった」と気づく。これを何度も繰り返していました。
育成にしても同じです。種族値を調べて、タイプ相性を確認して、努力値配分を考えて、性格を決めて…。ポケモン1体の育成方針を決めるだけで、複数のサイトを行き来する作業が発生します。
「この作業、全部AIに聞けたら楽なのに」
そう思って作ったのが、ポケモンのデータ検索・育成提案・パーティ分析ができる MCP サーバーです。GitHub Copilot に「このパーティの弱点を分析して」と聞くだけで、18タイプの相性を全部計算して改善提案まで返してくれます。
この記事では、MCP サーバーの設計・実装から、実際に GitHub Copilot と連携して使うところまでを解説します。
MCP とは
MCP(Model Context Protocol)は、AI アシスタントに外部ツールを追加するためのプロトコルです。Anthropic が策定したオープン標準で、VS Code の GitHub Copilot や Claude Desktop などが対応しています。
簡単に言うと「AIに新しいスキルを教える仕組み」です。今回はポケモンの知識を教えます。
作ったもの
PokeAPI と連携して、以下の 5 つのツールを提供する MCP サーバーです。
| ツール | できること |
|---|---|
search_pokemon |
ポケモンの種族値・タイプ・特性を検索 |
recommend_build |
役割に応じた性格・努力値配分を提案 |
analyze_team |
パーティのタイプバランスを分析・改善提案 |
check_type_matchup |
タイプ相性の倍率を計算 |
suggest_selection |
相手パーティに対する選出を提案 |
技術スタック
- Python 3.11+
- FastMCP(MCP の Python SDK)
- httpx(非同期 HTTP クライアント、HTTP/2 対応)
- PokeAPI(ポケモンデータの公開 API)
- uv(パッケージマネージャー)
プロジェクト構成
mcp/
├── server.py # MCPサーバー本体(ツール定義)
├── pokeapi.py # PokeAPI クライアント(キャッシュ付き)
├── pokemon_data.py # タイプ相性・性格などの静的データ
└── pyproject.toml # プロジェクト設定
各ツールの実装解説
各ツールを「何ができるか → コード → 実行例」の3点セットで紹介します。
search_pokemon — ポケモン検索
何ができるか: ポケモンの名前(英語名・日本語名・図鑑番号)から種族値・タイプ・特性・弱点を一発表示します。
コード(server.py より抜粋):
@mcp.tool()
async def search_pokemon(name: str) -> str:
"""ポケモンの種族値・タイプ・特性を検索します。
Args:
name: ポケモンの名前(例: pikachu, ピカチュウ, 25)
"""
pokemon, species, ja_name = await _fetch_pokemon_full(name)
# 種族値を取得
stats = {s["stat"]["name"]: s["base_stat"] for s in pokemon["stats"]}
# タイプから弱点・耐性を自動計算
types = [t["type"]["name"] for t in pokemon["types"]]
weakness_map = get_type_weaknesses(types)
# ...(整形して返す)
ポイントは docstring がそのまま AI への説明になること。Args の説明が具体的だと、AI が適切に引数を渡してくれます。
実行例:
👤 ピカチュウの種族値を教えて
🤖 ## ピカチュウ (#25)
タイプ: でんき
特性: せいでんき, ひらいしん(夢特性)
### 種族値
HP 35 ██░░░░░░░░░░░░░░░░░░
こうげき 55 ████░░░░░░░░░░░░░░░░
ぼうぎょ 40 ███░░░░░░░░░░░░░░░░░
とくこう 50 ███░░░░░░░░░░░░░░░░░
とくぼう 50 ███░░░░░░░░░░░░░░░░░
すばやさ 90 ███████░░░░░░░░░░░░░
合計 320
弱点: じめん(x2.0)
耐性: でんき(x0.5), ひこう(x0.5), はがね(x0.5)
recommend_build — 育成提案
何ができるか: 種族値から役割(物理アタッカー・特殊受けなど)を自動判定し、性格・努力値配分を提案します。
コード(役割自動判定ロジック):
def _detect_role(stats: dict[str, int]) -> str:
"""種族値から最適な役割を自動判定"""
atk = stats.get("attack", 0)
spa = stats.get("special-attack", 0)
spd_stat = stats.get("speed", 0)
bulk = stats.get("hp", 0) + stats.get("defense", 0) + stats.get("special-defense", 0)
offense = max(atk, spa)
if offense >= 100 and spd_stat >= 90:
return "physical_attacker" if atk >= spa else "special_attacker"
if bulk >= 280 and offense < 90:
return "physical_tank" if df >= spd else "special_tank"
# ...
攻撃種族値 100 以上 × すばやさ 90 以上 → アタッカー、耐久合計 280 以上 × 火力 90 未満 → 受け、のようにルールベースで判定しています。role パラメータで手動指定も可能です。
実行例:
👤 ガブリアスの育成提案をして
🤖 ## ガブリアス の育成提案
判定された役割: 物理アタッカー
### 性格
おすすめ: ようき(jolly)
↑ すばやさ / ↓ とくこう
### 努力値配分
こうげき: 252
すばやさ: 252
HP: 4
### 育成のポイント
- すばやさが高いため、上から殴れるアタッカーとして運用できます
- ⚠️ 4倍弱点: こおり(要注意)
analyze_team — パーティ分析
何ができるか: パーティ(最大6体)の攻撃面タイプカバー、防御面の弱点集中、ステータスバランスを分析し、改善提案を出します。18タイプ全ての相性を自動計算します。
コード(弱点集中の検出ロジック):
# チーム全体で各タイプへの弱点数を集計
type_weakness_count: dict[str, int] = {t: 0 for t in ALL_TYPES}
for p in team_data:
wmap = get_type_weaknesses(p["types"]) # 18タイプ全ての倍率を計算
for t in ALL_TYPES:
mult = wmap.get(t, 1.0)
if mult > 1.0:
type_weakness_count[t] += 1
# 2体以上が弱点を持つタイプを警告
danger_types = [(t, c) for t, c in type_weakness_count.items() if c >= 2]
get_type_weaknesses() が 18×18 の相性マトリクスから複合タイプの倍率を掛け算で計算します(足し算ではなく掛け算がポイント。例: リザードンにいわ技 = 2.0 × 2.0 = 4倍)。
実行例:
👤 ガブリアス、カイリュー、ナットレイのパーティを分析して
🤖 ## パーティ分析 (3体)
### メンバー
- ガブリアス (ドラゴン / じめん) 合計種族値: 600
- カイリュー (ドラゴン / ひこう) 合計種族値: 600
- ナットレイ (くさ / はがね) 合計種族値: 489
### 攻撃面タイプカバー
抜群を取れるタイプ (13/18): ...
⚠️ カバーできていないタイプ: ノーマル, ひこう, エスパー, ゴースト, あく
### チーム弱点分析
以下のタイプに複数メンバーが弱点を持っています:
⚠️ こおり: 2体が弱点
⚠️ ドラゴン: 2体が弱点
⚠️ フェアリー: 2体が弱点
### 改善提案
- 全員が物理寄りです。特殊アタッカーの追加を検討してください。
check_type_matchup — タイプ相性チェック
何ができるか: 攻撃タイプと防御タイプ(複合対応)の倍率を即座に計算します。
コード:
@mcp.tool()
async def check_type_matchup(
attacking_type: str,
defending_types: list[str],
) -> str:
"""タイプ相性の倍率を計算します。"""
# 複合タイプは各タイプの倍率を掛け算
multiplier = 1.0
for d in resolved_defs:
multiplier *= TYPE_CHART.get(atk, {}).get(d, 1.0)
日本語タイプ名(「ほのお」「みず」)にも対応しています。
実行例:
👤 いわタイプの技でリザードン(ほのお/ひこう)に攻撃したら?
🤖 いわ → ほのお / ひこう: x4.0 (4倍弱点!)
suggest_selection — 選出提案
何ができるか: 自分と相手のパーティを入力すると、タイプ相性ベースで選出3体(ダブルなら4体)と注意すべき相手ポケモンを提案します。選出画面の制限時間内に使う想定の高速ツールです。
コード(スコアリングロジック):
for i, me in enumerate(my_data):
# 攻撃面: 相手全員に対するタイプ相性スコア
atk_score = sum(_matchup_score(me["types"], opp["types"]) for opp in opp_data)
# 防御面: 相手から受けるダメージリスク
def_penalty = sum(_defensive_score(me["types"], opp["types"]) for opp in opp_data)
# 総合スコア = 攻撃貢献 - 被ダメリスク(防御の重みは0.5)
total = atk_score - def_penalty * 0.5
上位からタイプ被りを考慮しつつ3体を選び、相手の脅威度ランキングと対処法も合わせて出力します。
実行例:
👤 自分: ガブリアス, ロトム, ナットレイ, ウルガモス, カイリュー, ドヒドイデ
相手: ミミッキュ, ドラパルト, ドリュウズ, ガブリアス, モロバレル, ハッサム
を選出提案して
🤖 ## 選出提案 (シングル)
### 選出 (3体)
1. ウルガモス (むし/ほのお) → 有利: ドリュウズ, モロバレル, ハッサム
2. カイリュー (ドラゴン/ひこう) → 有利: ドラパルト, ガブリアス, モロバレル
3. ガブリアス (ドラゴン/じめん) → 有利: ドラパルト, ドリュウズ, ガブリアス
### 相手の注意ポケモン
⚠️ ガブリアス (ドラゴン/じめん) ← 対処: カイリュー, ガブリアス
⚠️ ドラパルト (ドラゴン/ゴースト) ← 対処: カイリュー, ガブリアス
### 初手: ウルガモス
共通の技術ポイント
ツール横断で使っている工夫を紹介します。
PokeAPI への非同期アクセスとキャッシュ
_cache: dict[str, dict] = {}
_client: httpx.AsyncClient | None = None
async def _get(path: str) -> dict:
"""PokeAPI への GET リクエスト(インメモリキャッシュ付き)"""
if path in _cache:
return _cache[path]
client = _get_client()
resp = await client.get(f"{POKEAPI_BASE}/{path}")
resp.raise_for_status()
data = resp.json()
_cache[path] = data
return data
- インメモリキャッシュ: 同じリクエストは 2 回目以降即座に返る
-
コネクションプール: httpx の
AsyncClientを共有して接続オーバーヘッドを削減 - HTTP/2: PokeAPI が対応しているので有効化
並列データ取得
パーティ分析(6体)や選出提案(最大12体)では asyncio.gather で並列化。6体直列だと数秒かかるところが体感 1 秒以下になります。
async def _fetch_pokemon_full_batch(queries: list[str]):
ids = await asyncio.gather(*(pokeapi.resolve_pokemon_id(q) for q in queries))
pairs = await asyncio.gather(*(pokeapi.get_pokemon_and_species(str(pid)) for pid in ids))
日本語名検索
PokeAPI は英語名ベースですが、日本語名→図鑑番号のマッピングを初回に構築してキャッシュしています。
セットアップ方法
インストール
cd mcp
uv sync
VS Code(GitHub Copilot)で使う
.vscode/mcp.json に以下を追加します。
{
"servers": {
"pokemon-champions": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/path/to/mcp", "python", "server.py"]
}
}
}
あとは Copilot Chat で「ガブリアスの種族値を教えて」「このパーティのバランスを分析して」と聞くだけです。
使ってみた例
種族値検索:
「ピカチュウの種族値を教えて」→ 種族値バーつきで表示
育成提案:
「ガブリアスの育成提案をして」→ 物理アタッカーと自動判定、ようき AS252 を提案
パーティ分析:
「ガブリアス、カイリュー、ナットレイのパーティを分析して」→ タイプカバー・弱点集中・改善提案を表示
選出提案:
「相手のパーティは〜なので選出を提案して」→ 3体の選出と注意ポケモンを提示
ハマったポイント
PokeAPI の日本語名検索が遅い
初回は全ポケモンの種族データを取得して日本語名マッピングを構築するため、初回起動時にかなり時間がかかります。将来的にはローカルにキャッシュファイルを持たせる改善を検討中です。
タイプ相性の複合計算
2 タイプのポケモンへの相性計算は、各タイプへの倍率を掛け算する必要があります。例えばリザードン(ほのお/ひこう)にいわタイプの技は 2.0 × 2.0 = 4.0 倍です。最初うっかり足し算にしていました。
まとめ
- MCP サーバーは意外と簡単に作れる(FastMCP + デコレータだけ)
- PokeAPI + 非同期処理 + キャッシュで実用的な速度を実現
- GitHub Copilot と連携すると、自然言語でポケモンのデータ検索・育成相談ができる
MCPはAIに「自分専用のスキル」を追加できる仕組みなので、ポケモンに限らず色々なドメインで活用できると思います。