カスタムツール
独自のGodot MCPツールをC#で書き、メインスレッドでGodot APIを呼び出し、実行中のGodotゲームからツール、プロンプト、リソースを公開できます。
Godot MCP には、プロジェクト内でプレーンな C# を使って独自の MCP ツールを追加できます。カスタムツールとは AI エージェントが呼び出せるメソッドのことで、その動作をモデルに伝える説明が付きます。このページではエディタツール、メインスレッドのルール、そしてエージェントが実行中のゲームとやり取りできるオプトインのランタイムについて説明します。
エディタツールを作成する
ツールファミリーは [AiToolType] でマークされた partial class です。各ツールは [AiTool("tool-name")] でマークされたメソッドで、モデルがいつ、どのように呼び出せばよいか分かるように、メソッドとすべてのパラメータに [Description] を付けます。
using System.ComponentModel;
using com.IvanMurzak.McpPlugin; // [AiToolType], [AiTool]
using com.IvanMurzak.ReflectorNet.Utils; // MainThread
[AiToolType]
public partial class Tool_MyFeature
{
[AiTool("my-custom-task", Title = "Do a custom task")]
[Description("Explain to the LLM what this does and when to call it.")]
public string CustomTask
(
[Description("Explain to the LLM what this parameter is.")]
string inputData
)
{
// Work that does not touch the Godot API can run here, on a background thread.
return MainThread.Instance.Run(() =>
{
// Touch EditorInterface, Node or Resource here, on the main thread.
return "[Success] Operation completed.";
});
}
}C# プロジェクトをビルドします(エディタの Build ボタン、godot-cli build、またはエージェントに script-build を実行させる)。Godot がアセンブリをリロードし、アドオンが再接続し、新しいツールがエージェントのツールリストとドックの Tools ウィンドウに表示されます。
ツールの信頼性を保つルール
- Godot オブジェクトはメインスレッドのみ。 ツールメソッドはメインスレッド外で呼ばれます。
Node、Resource、SceneTree、EditorInterfaceへの呼び出しはすべてMainThread.Instance.Run(...)を経由する必要があります。バックグラウンドスレッドからこれらに触れるとエディタがクラッシュする可能性があります。 - 整形済みテキストではなくデータを返す。 プロパティを持つクラスを返すか(モデル向けにシリアライズされます)、副作用のみのツールなら
voidを返します。エージェントが解析する必要があるものに手組みの文字列を使うのは避けてください。 - 任意パラメータを明示する。 デフォルト値付きの nullable 型を使います(例:
string? filter = null)。そうするとモデルはそのパラメータを任意として扱います。 - すべてを説明する。 モデルが読むのはこの説明です。ツールが何をするか、いつ使うか、各パラメータが何を意味するかを書いてください。
- エディタ専用コードは
#if TOOLSの内側に。 エディタ API を使うコードは、エクスポートされたゲームにコンパイルされてはいけません。
ヒントとターゲット
[AiTool] は ReadOnlyHint = true や IdempotentHint = true などの任意のヒントを受け取り、ツールが何も変更しないこと、または安全に繰り返せることをクライアントに伝えます。Target はツールを登録する場所を決めます:ToolTarget.Editor(エディタのみ)、ToolTarget.Runtime(ゲームのみ)、またはデフォルトの両方です。
エージェントにツールを書かせる
システムツール godot-skill-create は新しい C# ツールファイルをプロジェクトに書き込みます。ツールは次回のビルド後に呼び出し可能になります。新しいツールを書く前に、その仕事を RQL がすでにカバーしていないか確認してください。エディタのデータアクセスのほとんど(ノード、リソース、ファイル、プロジェクト設定)は 1 回の rql-query または rql-mutate で済みます。詳しくは Tools を参照してください。
実行中のゲームでのツール
Godot MCP は、実行中またはエクスポートされたゲーム(デバッグ版・リリース版を問わず)の内部でも動作できます。これにより、エージェントはライブのゲーム状態を読み取って操作できます。たとえば、ボットの指し手が LLM から来るチェスゲームなどです。次の 2 点は意図的な設計です:
- 自分から接続することはありません。
Connect()を呼ぶかどうか、いつ呼ぶかはあなたのコードが決めます。 - デフォルトでは何も公開しません。 ツール、プロンプト、リソースはすべて自分で登録します。アドオンのエディタツールはゲームビルドにはコンパイルされません。
SceneTree が存在するようになったら起動します。たとえば autoload の _Ready() から:
using System.Reflection;
using com.IvanMurzak.Godot.MCP.Connection;
using com.IvanMurzak.Godot.MCP.Runtime;
using McpServerConsts = com.IvanMurzak.McpPlugin.Common.Consts.MCP.Server;
using Godot;
public partial class GameMcp : Node
{
private GodotMcpRuntimeHandle? _mcp;
public override async void _Ready()
{
_mcp = GodotMcpRuntime.Initialize(builder =>
{
builder.WithConfig(config =>
{
config.ConnectionMode = GodotMcpConnectionMode.Custom;
config.Host = "http://localhost:8080";
config.AuthOption = McpServerConsts.AuthOption.token;
config.Token = "your-secret-token";
});
builder.WithToolsFromAssembly(Assembly.GetExecutingAssembly());
}).Build();
await _mcp.Connect();
}
public override async void _ExitTree()
{
if (_mcp is not null)
await _mcp.Disconnect();
}
}ゲーム専用のツールクラスには [AiToolType(Target = ToolTarget.Runtime)](com.IvanMurzak.McpPlugin.Common から)を付けます。これによりエディタはそれらを登録せず、エディタが接続中でもエージェントはゲームに到達できます。
ビルダーのオプション
| 呼び出し | 動作内容 |
|---|---|
WithConfig(...) | コード内で Host、Token、ConnectionMode、AuthOption を設定します。 |
WithToolsFromAssembly(...) / WithTools(...) | アセンブリから、または特定の型の [AiToolType] クラスを登録します。 |
WithPromptsFromAssembly(...) / WithPrompts(...) | [AiPromptType] プロンプトクラスを登録します。 |
WithResourcesFromAssembly(...) / WithResources(...) | [AiResourceType] リソースクラスを登録します。 |
WithRuntimeErrorCapture() | ゲーム内のエラーをキャプチャし、runtime-errors-get / runtime-errors-clear を登録します。デフォルトではオフです。 |
WithScriptExecute() | ゲーム内に script-execute を登録します。デフォルトではオフで、.csproj でのオプトインが必要です。 |
ConnectWhenRunFromEditor() | エディタから Play でゲームを起動したときにも接続します。デフォルトではオフです。 |
WithoutMainThreadDispatcher() | 自動のメインスレッドディスパッチャーをスキップします(自前のものを導入する場合のみ)。 |
ホストとトークンは GODOT_MCP_* 環境変数や .env ファイルからも取得でき、これらはコードより優先されます。ゲームがエディタの保存済み設定を読み取ることはありません。
プロンプトとリソース
ツールに加えて、ゲームは MCP プロンプト(名前付きの命令テンプレート、[AiPromptType] と [AiPrompt] メソッド)とリソース(URI で取得する読み取り専用コンテンツ、[AiResourceType] と [AiResource] メソッド)を公開できます。どちらの種類も任意で、ツールと同じ方法で登録します。
ゲーム内で C# を実行する
エージェントにゲーム内で C# を実行させるには、ゲームの .csproj でオプトインし、WithScriptExecute() を呼び出します:
<PropertyGroup>
<GodotMcpCodeExecInGame>true</GodotMcpCodeExecInGame>
<DefineConstants>$(DefineConstants);GODOT_MCP_CODE_EXEC_IN_GAME</DefineConstants>
</PropertyGroup>これはデスクトップの CoreCLR ビルドでのみ動作し、NativeAOT や iOS では動作しません。
ゲームビルドのためのセキュリティチェックリスト
localhostまたは127.0.0.1上で、AuthOption.tokenと実際のトークンを使う Custom モードを推奨します。- 必要なツールだけを登録してください。攻撃対象領域は、登録したツールそのものです。
- そのために設計・保護していない限り、リリースビルドでパブリックなネットワークインターフェースに接続を公開しないでください。