はじめに
MCP(Model Context Protocol)サーバーを使うことで、AIモデルとアプリケーションの連携が簡単に実現できます。動画を開いてみると、左側にゲーム画面が、右側にClaudeが開かれています。ゲームをClaudeがMCPを活用して操作している様子がわかると思います。この資料では、ゲーム操作を例に、MCPサーバーの実装方法について詳しく解説します。
MPCのゲームへの活用
As AI models become more complex and more capable, is it possible that they’ll have experiences of their own?
— Anthropic (@AnthropicAI) April 24, 2025
It’s an open question. We recently started a research program to investigate it. pic.twitter.com/tVrWzsJQKP
作ったもの
プレイヤーのコントロール(上下左右、ミサイル発射)
プレイヤーから見た視界の情報を渡す仕組み
MCP サーバーの基本構造
MCPサーバーは、AIモデルからの要求を受け取り、特定の機能(ツール)を提供するサーバーです。以下に基本的な実装手順を示します。
1. 必要なパッケージのインポート
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod"; // バリデーション用
2. サーバーの初期化
const server = new McpServer({
name: "game-charactor", // サーバー名
version: "1.0.0", // バージョン
capabilities: {
resources: {}, // リソース定義
tools: {}, // ツール定義
},
});
3. ツールの定義
MCPの強みは、AIモデルが利用できる「ツール」を定義できる点です。以下の例では、ゲームキャラクターを操作するためのツールを定義しています:
// キャラクター移動ツール
server.tool(
"game-charactor-move-operation", // ツールID
"ゲームキャラクターを操作する", // 説明
{
x: z.number().describe("キャラクターが移動させるX座標"), // パラメータ定義
z: z.number().describe("キャラクターが移動させるY座標")
},
async ({ x, z }) => { // 実行関数
try {
// APIエンドポイントにリクエスト
const response = await fetch(`http://localhost:3000/api/move`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ x, z })
});
const data = await response.json();
// 結果を返す
return {
content: [
{
type: "text",
text: `Character moved successfully: x=${x}, z=${z}`
}
]
};
} catch (error) {
// エラー処理
return {
content: [
{
type: "text",
text: `Failed to move: ${error instanceof Error ? error.message : String(error)}`
}
]
};
}
}
);
4. 他のツール例:ミサイル発射
// ミサイル発射ツール
server.tool(
"fire-missile", // ツールID
"ゲームキャラクターからミサイルを発射する", // 説明
{
r: z.number().describe("ミサイルを発射する方向。値は度数法(0°~360°)で表現 0°は北向き(Z軸正方向) 90°は東向き(X軸正方向) 180°は南向き(Z軸負方向) 270°は西向き(X軸負方向)")
},
async ({ r }) => { // 実行関数
try {
// APIエンドポイントにリクエスト
const response = await fetch(`http://localhost:3000/api/fire-missile`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ r })
});
const data = await response.json();
// 結果を返す
return {
content: [
{
type: "text",
text: `Missile fired successfully in direction ${r} degrees`
}
]
};
} catch (error) {
// エラー処理
return {
content: [
{
type: "text",
text: `Failed to fire missile: ${error instanceof Error ? error.message : String(error)}`
}
]
};
}
}
);
5. 情報取得ツール:視界情報
// 視界情報取得ツール
server.tool(
"vision", // ツールID
"ゲームキャラクターの視界情報。どの方向に敵がいるかなどを知る", // 説明
{}, // パラメータなし
async () => { // 実行関数
try {
// APIエンドポイントにリクエスト
const response = await fetch(`http://localhost:3000/api/vision`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
// 結果を返す(JSON文字列として)
return {
content: [
{
type: "text",
text: JSON.stringify(data.visionInfo)
}
]
};
} catch (error) {
// エラー処理
return {
content: [
{
type: "text",
text: `Failed to get vision info: ${error instanceof Error ? error.message : String(error)}`
}
]
};
}
}
);
6. サーバー起動処理
async function main() {
// 標準入出力を使ったトランスポートを作成
const transport = new StdioServerTransport();
// サーバーを起動
await server.connect(transport);
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
MCPサーバー実装のポイント
-
ツール定義の明確化:
- ツールIDは一意であること
- 説明は分かりやすく、AIが理解しやすい表現を使う
- パラメータにはzodを使い、型と説明を明確に定義する
-
エラーハンドリング:
- すべてのAPIリクエストはtry-catchで囲み、エラーを適切に処理する
- エラーメッセージは具体的で、デバッグしやすいものにする
-
レスポンス形式:
- 返却値は必ず
{ content: [{ type: "text", text: "..." }] }
の形式にする - テキスト以外にも、JSON、画像などの返却も可能
- 返却値は必ず
-
非同期処理:
- ツール実行関数は必ずasync関数として定義し、非同期処理を適切に扱う
バックエンドAPIとの連携
MCPサーバーは、通常バックエンドAPIと連携して動作します。上記の例では、以下のAPIエンドポイントを使用しています:
-
/api/move
- キャラクターを移動させる -
/api/fire-missile
- ミサイルを発射する -
/api/vision
- 視界情報を取得する
これらのAPIは、実際のゲームロジックを実装するバックエンドサーバーで提供されます。
実際の活用例
このMCPサーバーを使用すると、AIは以下のような指示を理解し実行できるようになります:
- 「敵の位置を確認して、最も近い敵に向かって移動し、ミサイルを発射してください」
- 「視界情報から敵の位置を特定し、X座標10、Z座標15の位置に移動してください」
- 「北東方向にミサイルを発射してください」
AIは提供されたツールを使用して、これらの指示を適切なAPIリクエストに変換して実行します。
まとめ
MCPサーバーの実装によって、AIモデルとゲームなどのアプリケーションを簡単に連携させることができます。ツールを適切に定義し、エラー処理を適切に行うことで、安定した動作を実現できます。
ゲーム操作のお手伝いをします。敵の位置を確認してから、キャラクターを移動させミサイルを発射しましょう。
まず、敵の位置を確認するために視界情報を取得します。
視界情報を確認しました。現在、3体の敵が以下の位置にいます:
1. 1体目:X座標10、Z座標10の位置(北東方向、距離約14.1)
2. 2体目:X座標-5、Z座標15の位置(北北西方向、距離約15.8)
3. 3体目:X座標8、Z座標-12の位置(南東方向、距離約14.4)
まず、1体目の敵に接近するために移動します。
キャラクターを座標(8, 8)に移動しました。これで1体目の敵に近づきました。
次に、1体目の敵に向かってミサイルを発射します。敵は座標(10, 10)にいるので、北東方向(45度)に発射します。
ミサイルを北東方向(45度)に発射しました!
次に、2体目の敵(座標-5, 15)に向かって移動します。
キャラクターを座標(-3, 12)に移動しました。これで2体目の敵に近づきました。
2体目の敵は座標(-5, 15)にいるので、北西方向(約342度)にミサイルを発射します。
ミサイルを北西方向(342度)に発射しました!
最後に、3体目の敵(座標8, -12)に向かって移動します。
キャラクターを座標(6, -10)に移動しました。これで3体目の敵に近づきました。
3体目の敵は座標(8, -12)にいるので、南東方向(約146度)にミサイルを発射します。
ミサイルを南東方向(146度)に発射しました!
すべての敵に対して移動とミサイル発射を完了しました:
1. 1体目(座標10,10):座標(8,8)から45度方向にミサイル発射
2. 2体目(座標-5,15):座標(-3,12)から342度方向にミサイル発射
3. 3体目(座標8,-12):座標(6,-10)から146度方向にミサイル発射
すべての敵にミサイルを発射することができました。お役に立てて嬉しいです!