← ブログへ

Godot向けリアルタイムMCPサーバーを構築した方法

VberAIのGodot MCPアーキテクチャ:リアルタイムModel Context ProtocolサーバーがシーンツリーをフリーズさせずにGodotエディターとAIクライアントを橋渡しする仕組み

公開日
  • vberai
  • godot
  • mcp
  • architecture
  • realtime

GodotのMCPサーバーにおいて「リアルタイム」が重要な理由

ほとんどのMCPデモはREST的な世界で動作します。モデルが質問し、ツールがJSONを返し、往復に2秒かかっても誰も気にしません。Godotは違います。エディターはライブなシーンツリー、リソースインポート、プレイモードループを所有しています。MCPサーバーがメインスレッドをブロックしたり、プロジェクトの古いダンプしか見られなかったりすると、AIクライアントはコパイロットというより、余計な手間がかかるリモートファイルエディターのように感じられます。

VberAI向けにGodot MCPを設計したとき、要件は明確でした。

  • AIアシスタント(Cursor、Claude、WindsurfなどのMCPクライアント)は、ディスク上の.gdファイルを読むだけでなく、エディターを操作できなければならない
  • ノード作成、名前変更、スクリプトアタッチ、選択クエリなどのアクションは、エディターの応答性を保ったまま完了する必要がある
  • プレイモードと編集モードのコンテキストは正直でなければならない。プレイ中に安全でない操作はツールが明確に失敗するべきである

この記事はエンジニアリングストーリーです。プロジェクトを静的なリポジトリと見なすのではなく、Godotの隣に存在するリアルタイムMCPサーバーをどのように構築したかを説明します。

エンジンにおける「ファイルのみ」のMCPの問題点

単純なアプローチは魅力的です。

  1. MCPサーバーをプロジェクトフォルダーに向ける
  2. read_file / write_file / list_dir を公開する
  3. モデルにGDScriptを生成させ、エディターがうまくリロードされることを期待する

これはドキュメンテーションサイトでは機能します。しかし、エンジンワークでは失敗します。なぜなら:

  • シーンの所有権はメモリ上にある — 未保存の.tscn差分、開いているシーン、エディターの選択状態はディスクからは見えない
  • インポートパイプラインはステートフル — PNGを書き込むことは「正しいインポート設定でリソースが準備完了」と同じではない
  • シグナルとノードパスはグラフデータ — 文字列の編集は配線を静かに壊す
  • レイテンシが累積する — 「ノードが出現したか?」の確認ごとにファイルシステム全体のスキャンが必要になる

私たちは、人間がGodotドックで見るもの(階層、インスペクターのようなプロパティ、リソースハンドル)を反映するMCPサーフェスが必要でした。パス文字列だけではありません。

アーキテクチャ概要

高レベルでは、Godot MCPは3つの協調レイヤーで構成されています。

MCPクライアント(Cursor / Claude / …)
        │  JSON-RPC over stdio またはローカル転送

MCPサーバー(VberAI Godotブリッジプロセス)
        │  コマンドキュー + 結果エンベロープ

Godotエディタープラグイン(GDExtension / エディタープラグイン)
        │  メインスレッドでの遅延呼び出し

エディターシーンツリー / ResourceDB / スクリプトエディター

レイヤー1 — MCPツールサーフェス

ツールは意図的に小さく、動詞の形をしています。

  • godot_get_scene_tree — 編集中のシーンのスナップショット(ノードタイプとパスを含む)
  • godot_create_node / godot_set_property
  • godot_attach_script / godot_run_script_snippet(ガード付き)
  • godot_list_resources / godot_get_selection

巨大なdo_anythingツールは避けています。小さなツールは検証しやすく、ログを取りやすく、モデルが無制限のパッチに悪用するのが難しくなります。

レイヤー2 — リアルタイムブリッジ

ブリッジこそが「リアルタイム」の本質です。

  • MCPプロセスとエディタープラグイン間の双方向チャネル(開発時はローカルソケットまたは名前付きパイプ;製品ビルドではVberAIデスクトップヘルパーの背後にラップされる可能性あり)
  • 2つの重複するツール呼び出しがシーンツリーを競合しないように変異を直列化するコマンドキュー
  • MCPクライアントがファイルシステムをポーリングせずに「適用済み」を待機できるリクエストID + 確認応答
  • ハートビート / エディター生存確認により、クライアントはGodotがセッション中に終了したことを認識できる

レイヤー3 — Godotにおけるメインスレッドの安全性

GodotのUIとシーンAPIはスレッドセーフではありません。プラグインはMCP I/Oスレッド上でノードを決して変更しません。代わりに:

  1. MCPコマンドがブリッジスレッドに到着
  2. ペイロードがキューに入れられる
  3. エディターの遅延コールバックがメインスレッドで実行される(call_deferred / アイドルフレームフック)
  4. 結果エンベロープが成功、構造化エラー、または「プレイモード終了後に再試行」を返す

このパターンは意図的に退屈です。退屈であることが、「リアルタイム」を「ランダムなエディターフリーズ」にしないための鍵です。

リアルタイム感を実現する(レイテンシについて嘘をつかずに)

ここでの「リアルタイム」は魔法のようなゼロレイテンシを意味しません。フィードバックループが人間がエディター内で作業する方法と一致することを意味します。

スナップショット vs ストリーム

初期のプロトタイプは、呼び出しごとにシーンツリー全体を返していました。大きなオープンワールド設定では崩壊しました。そこで以下に切り替えました。

  • デフォルトでは浅いスナップショット(ルート+1レベル、または選択フォーカス)
  • モデルがすでにサブツリーを知っている場合はパススコープの読み取り
  • オプションの変更トークンにより、後続の呼び出しですべてを再シリアライズせずに「X以降何が変わったか?」を問い合わせ可能

差分に適した結果

ツール結果には以下が含まれます。

  • 正規化されたNodePath文字列
  • タイプ名(CharacterBody2DControl、…)
  • インスペクターフィールドにきれいにマッピングされるプロパティキー
  • 書き込みが適用されたがシーンがまだダーティ/未保存である場合の明示的な警告

結果が自由形式のテキストブログ記事ではなくUI状態のように見えると、モデルはより速く反復できます。

制限付きのプレイモード動作

プレイモードは、「AIがプロジェクトを壊した」というチケットの半分の原因です。私たちのルールセットは以下の通りです。

モード許可ブロックまたはゲート
編集シーン変更、リソースクエリ確認なしの破壊的なプロジェクト削除
プレイ主に読み取り/ランタイムノードのクエリ編集中のシーンへの構造的編集
遷移待機/再試行のヒントサイレントなノーオペレーション

明確なエラーは賢さに勝ります。モデルがプレイ中に編集できない場合、MCPレスポンスは構造化された形式でそれを伝えます。これにより、クライアントはユーザーにプレイを停止してから再試行するよう指示できます。

直面した(そして維持した)難しい問題

1. エディターはデータベースではない

ノードの順序、オーナー関係、パックシーンは、GIFではシンプルに見え、.tscnでは厄介に見える方法で相互作用します。私たちは、並列のシーンモデルを発明してずれるのを防ぐのではなく、Godot自身のAPI(NodeEditorInterface、リソースローダー)に依存しました。

2. スクリプトとシーンという2つの真実の源泉

スクリプトをアタッチすることは、スクリプトがコンパイルされ、クラス名が解決されることを保証することと同じではありません。サーバーはコンパイル/アタッチの結果を別々に報告します。これにより、「ツールは成功と言ったのに、インスペクターには何も表示されない」という失敗を防ぎました。

3. マルチウィンドウ / マルチプロジェクトセッション

開発者は複数のGodotインスタンスを開きます。ブリッジは明示的なエディターセッションIDにバインドされるため、週末のスリープと再開後にツール呼び出しが間違ったプロジェクトに届くことはありません。

4. セキュリティ境界

シーンを書き換えられるMCPサーバーは強力です。ローカルファーストの転送、明示的なツール許可リスト、プロジェクトツリー全体のサイレントなクラウド流出防止は譲れません。「AIヘルパー」と「ゲーム上のリモートシェル」は別の製品カテゴリーであり続けなければなりません。

AI StudioおよびVberAIの他の部分との連携

Godot MCPはエンジンオペレーターです。補完的なピースは以下の通りです。

  • VberAI AI StudioAI Studio) — Figma/PSDからControl階層へのデザインtoエンジン構造;MCPはインポート後にボタンを配線し、ノードの名前を変更します
  • Unity MCP / Cocos MCP — 同じMCPのアイデア、異なるエディターホストと安全ルール
  • AI Super Matting — テクスチャがエンジンリソースになる前にアルファをクリーンアップし、後でMCPが割り当てます

共通のテーゼ:AIはライブなプロダクションサーフェス(エディター、アセット、シーン)に触れるべきであり、テキストとしてのリポジトリだけではありません。

独自のエンジンMCPを構築する場合の実践的なヒント

  1. エンジンのメインスレッドで変異をキューイングする — ゲームエンジンを共有なしサーバーと決して見なさないこと
  2. スキーマを持つ小さなツールを優先する — 検証はプロンプトの詩よりも優れている
  3. NodePathとタイプを返し、散文は返さない — モデルは操作可能なハンドルを必要とする
  4. すべてのレスポンスにプレイ/編集モードをエンコードする — ここでの曖昧さは信頼を破壊する
  5. 「ドックに表示されるまで」の往復時間を測定する — JSONエンコード時間だけではない

MCPプロセスだけを最適化し、エディターブリッジを無視すると、高速な幻覚ループを出荷することになります。

結論

Godot向けのリアルタイムMCPサーバーを構築するということは、エディターをライブな共同作業者として扱うことを意味しました。キューイングされ、メインスレッドセーフなブリッジ、エディターアクションのように形作られたツール、プレイモードの制限に対する正直さ。ファイルのみのMCPはより簡単ですが、シーンネイティブな作業には不完全です。

週末のプロトタイプではなく、出荷されたパスをお望みですか? VberAI Godot MCPから始めて、お好みのMCPクライアントを接続し、簡単な最初のツール呼び出しを試してください。現在のシーンツリーをリストし、選択下に1つのノードを作成する。この単一のループ — クエリ → 変異 → ドックで確認 — が製品です。それ以外はすべて、その周りの信頼性エンジニアリングです。

こちらの記事もおすすめです