Skip to main content
Glama
MCP_SERVER_ARCHITECTURE.md25.3 kB
# Unity MCP Server Architecture UnityにおけるMCP (Model Context Protocol) サーバーの構築ガイドと技術仕様。 --- ## 概要 Unity MCP Serverは、Claude CodeなどのAIツールからUnity Editorを操作するためのサーバーです。MCP (Model Context Protocol) に準拠し、JSON-RPC 2.0ベースの通信を行います。 ### アーキテクチャ図 ![MCP Architecture](diagrams/mcp_architecture.png) <details> <summary>テキスト版(ASCII図)</summary> ``` ┌─────────────────────────────────────────────────────────────────┐ │ Claude Code │ └─────────────────────────────────────────────────────────────────┘ │ stdio ▼ ┌─────────────────────────────────────────────────────────────────┐ │ MCP Bridge (Node.js) │ │ Server~/mcp-bridge/index.js │ └─────────────────────────────────────────────────────────────────┘ │ HTTP (port 5051) ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Unity Editor │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ UnityMcpHttpServer (HTTP) │ │ │ │ port 5051 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ API Router │ │ │ │ │ │ - tools/list → ApiRegistry │ │ │ │ │ │ - tools/call → Controller Methods │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ UnityMcpServer (WebSocket) │ │ │ │ port 5050 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ McpSession │ │ │ │ │ │ - WebSocket Handshake │ │ │ │ │ │ - JSON-RPC Message Processing │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ ApiRegistry │ │ │ │ - API Definitions (770+ APIs) │ │ │ │ - Edition Filtering (Public/Standard/Pro) │ │ │ │ - tools/list Response Generation │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Controllers │ │ │ │ - SceneController │ │ │ │ - GameObjectController │ │ │ │ - ComponentController │ │ │ │ - AudioController │ │ │ │ - ... (50+ Controllers) │ │ │ └──────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` </details> ### JSON-RPC リクエストフロー ![JSON-RPC Flow](diagrams/jsonrpc_flow.png) --- ## コアコンポーネント ### 1. UnityMcpServer (WebSocket) **ファイル:** `Editor/UnityMcpServer.cs` WebSocketサーバーのメインクラス。TCPリスナーでクライアント接続を受け付け、各接続に対してMcpSessionを生成します。 ```csharp public class UnityMcpServer { private TcpListener tcpListener; private int port = 5050; private List<McpSession> activeSessions; public void StartServer(int serverPort = 5050); public void StopServer(); } ``` **特徴:** - シングルトンパターン (`Instance`) - バックグラウンドスレッドで動作 - 複数クライアントの同時接続対応 - Unity Editor終了時の自動クリーンアップ ### 2. McpSession **ファイル:** `Editor/McpSession.cs` 個々のWebSocket接続を管理するクラス。WebSocketハンドシェイク、JSON-RPCメッセージの受信・処理を行います。 ```csharp public class McpSession { private TcpClient client; private NetworkStream stream; public void HandleClient(); // メインループ private bool PerformWebSocketHandshake(); // WebSocketハンドシェイク private void ProcessMessage(string json); // JSON-RPC処理 public void SendMessage(string message); // メッセージ送信 } ``` **WebSocketハンドシェイク:** ``` Client → Server: HTTP Upgrade Request Sec-WebSocket-Key: xxx Server → Client: HTTP 101 Switching Protocols Sec-WebSocket-Accept: yyy ``` ### 3. UnityMcpHttpServer (HTTP) **ファイル:** `Editor/UnityMcpHttpServer.cs` HTTP REST APIサーバー。MCPブリッジからのリクエストを受け付けます。 ```csharp public class UnityMcpHttpServer { private HttpListener httpListener; private int port = 5051; public void StartServer(int serverPort = 5051); public void StopServer(); } ``` **エンドポイント:** | エンドポイント | メソッド | 説明 | |---------------|---------|------| | `/health` | GET | ヘルスチェック | | `/api/mcp` | POST | JSON-RPC リクエスト | ### 4. ApiRegistry **ファイル:** `Editor/ApiRegistry.cs` API定義を管理するレジストリ。MCP `tools/list` レスポンスを生成します。 ```csharp public static class ApiRegistry { public static McpEdition CurrentEdition { get; set; } public static List<ApiDefinition> GetAllApis(); public static List<ApiDefinition> GetApisByCategory(string category); public static string GenerateToolsList(); } public class ApiDefinition { public string name; // "unity.scene.list" public string category; // "scene" public string description; // API説明 public McpEdition edition; // Public/Standard/Pro public InputSchema inputSchema; } ``` **エディション:** ![API Editions](diagrams/api_editions.png) | エディション | API数 | 対象 | |-------------|-------|------| | Public | ~100 | 基本操作 (scene, gameObject, component, prefab, asset) | | Standard | ~350 | 拡張機能 (timeline, cinemachine, recorder, uitoolkit) | | Pro | ~770 | 全機能 (probuilder, lighting, shadergraph, audio) | --- ## JSON-RPC 2.0 プロトコル ### リクエスト形式 ```json { "jsonrpc": "2.0", "method": "unity.scene.list", "params": { "maxDepth": 2 }, "id": 1 } ``` ### レスポンス形式(成功) ```json { "jsonrpc": "2.0", "result": { "sceneName": "SampleScene", "objects": [...] }, "id": 1 } ``` ### レスポンス形式(エラー) ```json { "jsonrpc": "2.0", "error": { "code": -32600, "message": "GameObject not found: Player" }, "id": 1 } ``` --- ## MCP標準メソッド ### tools/list 利用可能なAPIの一覧を返します。 **リクエスト:** ```json { "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1 } ``` **レスポンス:** ```json { "jsonrpc": "2.0", "result": { "tools": [ { "name": "unity.scene.list", "description": "シーン内のGameObject一覧を取得", "inputSchema": { "type": "object", "properties": { "maxDepth": { "type": "integer", "description": "階層の深さ" } } } } ] }, "id": 1 } ``` ### tools/call 指定したAPIを実行します。 **リクエスト:** ```json { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "unity.gameObject.create", "arguments": { "name": "NewObject", "parentPath": "/Canvas" } }, "id": 2 } ``` --- ## Controller パターン ### 基本構造 ```csharp public static class ExampleController { // パラメータクラス public class CreateParams { public string name; public string parentPath; } // 結果クラス public class CreateResult { public bool success; public string path; } // APIメソッド public static string Create(string paramsJson, object id) { try { var p = JsonUtility.FromJson<CreateParams>(paramsJson); // Unity API操作 var go = new GameObject(p.name); Undo.RegisterCreatedObjectUndo(go, "Create Object"); // 結果を返す var result = new CreateResult { success = true, path = go.name }; return JsonRpcResponse.Success(result, id).ToJson(); } catch (Exception e) { return JsonRpcResponse.Error(e.Message, id).ToJson(); } } } ``` ### 命名規則 | 項目 | 規則 | 例 | |------|------|-----| | API名 | `unity.{category}.{action}` | `unity.audio.createSource` | | Controllerクラス | `{Category}Controller` | `AudioController` | | パラメータクラス | `{Action}Params` | `CreateSourceParams` | | 結果クラス | `{Action}Result` | `AudioSourceInfo` | --- ## ルーティング ### HTTP ルーティング (UnityMcpHttpServer.cs) ```csharp private string RouteToolCall(string method, string paramsJson, object id) { // Audio API if (method == "unity.audio.createSource") return AudioController.CreateSource(paramsJson, id); if (method == "unity.audio.play") return AudioController.Play(paramsJson, id); // Scene API if (method == "unity.scene.list") return SceneController.List(paramsJson, id); // ... 他のAPI } ``` ### WebSocket ルーティング (McpSession.cs) HTTPと同様の構造。両方に同じルーティングを追加する必要があります。 --- ## ファイル構成 ![File Structure](diagrams/file_structure.png) ``` Editor/ ├── UnityMcpServer.cs # WebSocketサーバー本体 ├── McpSession.cs # WebSocketセッション管理 ├── UnityMcpHttpServer.cs # HTTPサーバー ├── ApiRegistry.cs # API定義レジストリ ├── JsonRpcResponse.cs # JSON-RPCレスポンスヘルパー ├── McpSetupWindow.cs # セットアップGUI │ ├── SceneController.cs # シーン操作API ├── GameObjectController.cs # GameObject操作API ├── ComponentController.cs # コンポーネント操作API ├── AudioController.cs # オーディオAPI ├── ... # その他のController │ ├── Timeline/ # パッケージ依存API │ ├── TimelineBuilder.cs │ └── LocalMcp.UnityServer.Timeline.Editor.asmdef │ ├── Cinemachine/ ├── ProBuilder/ ├── Volume/ └── ... Server~/ └── mcp-bridge/ ├── index.js # MCPブリッジ(Node.js) ├── package.json └── README.md ``` --- ## 自動起動 ### McpAutoStart.cs Unity Editor起動時にサーバーを自動起動します。 ```csharp [InitializeOnLoad] public static class McpAutoStart { static McpAutoStart() { EditorApplication.delayCall += () => { var wsServer = new UnityMcpServer(); wsServer.StartServer(5050); var httpServer = new UnityMcpHttpServer(); httpServer.StartServer(5051); // ランタイム設定ファイルを生成 WriteRuntimeConfig(); }; } } ``` ### .unity-mcp-runtime.json ```json { "projectName": "MyProject", "projectPath": "/path/to/project", "unityVersion": "6000.2.8f1", "wsPort": 5050, "httpPort": 5051, "serverVersion": "0.7.2", "timestamp": "2025-12-19T10:00:00Z" } ``` --- ## Assembly Definition ### パッケージ依存APIの分離 パッケージ依存のAPIは専用のasmdefで分離し、パッケージ未インストール時のコンパイルエラーを防止します。 ```json // Editor/Timeline/LocalMcp.UnityServer.Timeline.Editor.asmdef { "name": "LocalMcp.UnityServer.Timeline.Editor", "references": ["Unity.Timeline", "Unity.Timeline.Editor"], "includePlatforms": ["Editor"], "defineConstraints": ["UNITY_TIMELINE"], "versionDefines": [ { "name": "com.unity.timeline", "expression": "1.0.0", "define": "UNITY_TIMELINE" } ] } ``` ### リフレクションベース呼び出し メインasmdefからパッケージ依存APIを呼び出す場合はリフレクションを使用: ```csharp // PackageApiInvoker.cs public static string Invoke(string assemblyName, string typeName, string methodName, string paramsJson, object id) { var assembly = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.GetName().Name == assemblyName); if (assembly == null) return JsonRpcResponse.Error("Package not installed", id).ToJson(); var type = assembly.GetType(typeName); var method = type.GetMethod(methodName); return (string)method.Invoke(null, new object[] { paramsJson, id }); } ``` --- ## エラーハンドリング ### 標準エラーコード | コード | 説明 | |--------|------| | -32700 | Parse error (JSONパースエラー) | | -32600 | Invalid Request | | -32601 | Method not found | | -32602 | Invalid params | | -32603 | Internal error | ### カスタムエラー ```csharp return JsonRpcResponse.Error("GameObject not found: " + path, id).ToJson(); ``` --- ## ベストプラクティス ### 1. Undo対応 すべての変更操作にUndoを登録: ```csharp Undo.RegisterCreatedObjectUndo(go, "Create Object"); Undo.RecordObject(component, "Modify Component"); ``` ### 2. メインスレッド実行 Unity APIはメインスレッドでのみ実行可能。`EditorApplication.delayCall`を使用: ```csharp EditorApplication.delayCall += () => { // Unity API操作 }; ``` ### 3. エディションフィルタリング APIをエディションで分類: ```csharp AddApi(new ApiDefinition { name = "unity.probuilder.createPrimitive", edition = McpEdition.Pro, // Pro限定API // ... }); ``` --- ## バージョン情報 ### MCP Server 1.0 (現行) 現在のアーキテクチャは **MCP Server 1.0** として位置づけられます。 **特徴:** - Node.js MCP Bridge によるプロトコル変換 - HTTP/WebSocket 二重サーバー構成 - 770+ API の一括提供 (`tools/list`) - エディション別フィルタリング (Public/Standard/Pro) - リフレクションベースのパッケージ依存API呼び出し **課題:** (GitHub Issues #77-#82) - API数の爆発問題(LLMのコンテキストを圧迫) - Node.jsブリッジのオーバーヘッド - API選択・発見の非効率性 - セットアップの複雑さ - リアルタイム性の欠如 - エラーハンドリングの不十分さ --- ## MCP Server 2.0 ロードマップ ### アーキテクチャ概要 ![MCP Architecture 2.0](diagrams/mcp_architecture_2_0.png) **2.0 の主要コンポーネント:** - **Native MCP Server (C#)**: Node.js 不要、直接 stdio 通信 - **Dynamic API Loader**: カテゴリベースの動的 API 提供 - **API Recommender**: シーン状態に基づく API 推薦 - **Event Notifier**: Unity → Claude Code へのプッシュ通知 - **IPC Bridge**: Unity Editor との高速プロセス間通信 ### 2.0 の主要改善点 #### 1. Node.js ブリッジの排除 (Issue #78) **現状 (1.0):** ``` Claude Code → stdio → Node.js Bridge → HTTP → Unity ``` **目標 (2.0):** ``` Claude Code → stdio → Unity (Native MCP Server) ``` **実装アプローチ:** - C# で MCP プロトコルを直接実装 - `System.Console` の stdin/stdout を使用 - Unity Editor 起動時に別プロセスとして MCP Server を起動 - IPC (Inter-Process Communication) で Unity Editor と通信 ```csharp // 構想: NativeMcpServer.cs public class NativeMcpServer { public void Start() { // stdin から JSON-RPC メッセージを読み取り while (true) { var line = Console.ReadLine(); var response = ProcessMessage(line); Console.WriteLine(response); } } } ``` #### 2. カテゴリベース動的API提供 (Issue #77, #79) **現状 (1.0):** - `tools/list` で 770+ API を一括返却 - LLM のコンテキストを大量消費 **目標 (2.0):** - 階層的 API ディスカバリ - 必要な時に必要な API のみを提供 **実装アプローチ:** ```json // Step 1: カテゴリ一覧を取得 { "method": "tools/list", "params": { "level": "categories" } } // → ["scene", "gameObject", "timeline", "audio", ...] // Step 2: 特定カテゴリのAPIを取得 { "method": "tools/list", "params": { "category": "timeline" } } // → timeline関連の42 APIのみ返却 ``` **API階層設計:** ``` unity. ├── core/ # 常に利用可能(~30 API) │ ├── scene.* │ ├── gameObject.* │ └── log.* │ ├── standard/ # 要求時に展開 │ ├── timeline.* │ ├── cinemachine.* │ └── animator.* │ └── pro/ # 要求時に展開 ├── probuilder.* ├── lighting.* └── volume.* ``` #### 3. スマートAPI推薦 (Issue #79) **コンテキスト認識型API提案:** ```csharp public class ApiRecommender { // 現在のシーン状態から推奨APIを返す public List<string> GetRecommendedApis() { var recommendations = new List<string>(); // Timeline がシーンにあれば timeline API を推奨 if (HasTimelineInScene()) recommendations.Add("timeline"); // Cinemachine カメラがあれば cinemachine API を推奨 if (HasCinemachineCamera()) recommendations.Add("cinemachine"); // 選択中のオブジェクトに基づく推奨 if (Selection.activeGameObject?.GetComponent<AudioSource>()) recommendations.Add("audio"); return recommendations; } } ``` #### 4. リアルタイムイベント通知 (Issue #81) **現状 (1.0):** - ポーリングベース(状態確認は毎回 API 呼び出し) **目標 (2.0):** - プッシュ型イベント通知 - Unity Editor の変更を即座に LLM へ通知 **実装アプローチ:** ```csharp // MCP notifications (Server → Client) public class UnityEventNotifier { public void Initialize() { // シーン変更を監視 EditorSceneManager.sceneOpened += (scene, mode) => { SendNotification("unity/sceneChanged", new { sceneName = scene.name, scenePath = scene.path }); }; // 選択変更を監視 Selection.selectionChanged += () => { SendNotification("unity/selectionChanged", new { selectedObjects = Selection.gameObjects.Select(g => g.name) }); }; // コンパイル状態を監視 CompilationPipeline.compilationStarted += _ => { SendNotification("unity/compilationStarted", new { }); }; } private void SendNotification(string method, object data) { var notification = new { jsonrpc = "2.0", method = method, @params = data }; Console.WriteLine(JsonUtility.ToJson(notification)); } } ``` **通知イベント一覧:** | イベント | 説明 | |---------|------| | `unity/sceneChanged` | シーン変更 | | `unity/selectionChanged` | 選択オブジェクト変更 | | `unity/hierarchyChanged` | ヒエラルキー構造変更 | | `unity/compilationStarted` | コンパイル開始 | | `unity/compilationFinished` | コンパイル完了 | | `unity/playModeChanged` | Play/Edit モード変更 | | `unity/assetImported` | アセットインポート完了 | #### 5. エラーハンドリング強化 (Issue #82) **構造化エラーレスポンス:** ```json { "jsonrpc": "2.0", "error": { "code": -32001, "message": "GameObject not found", "data": { "errorType": "NotFound", "searchedPath": "/Canvas/Button", "suggestions": ["/Canvas/StartButton", "/Canvas/ExitButton"], "context": { "sceneObjects": ["Canvas", "EventSystem", "Main Camera"] }, "documentation": "https://docs.unity3d.com/..." } }, "id": 1 } ``` **エラーカテゴリ:** | コード | カテゴリ | 説明 | |--------|---------|------| | -32001 | NotFound | オブジェクト/アセットが見つからない | | -32002 | InvalidState | 不正な状態(Play中に編集など) | | -32003 | PackageNotInstalled | 必要なパッケージ未インストール | | -32004 | PermissionDenied | 操作権限なし | | -32005 | Timeout | 操作タイムアウト | #### 6. ゼロコンフィグ接続 (Issue #80) **現状 (1.0):** 1. npm install 実行 2. .mcp.json 作成 3. Unity でサーバー起動確認 4. Claude Code 再起動 **目標 (2.0):** 1. Unity パッケージインストール → 自動完了 **実装アプローチ:** - Claude Code の設定ファイルを自動検出・更新 - Unity 起動時に MCP Server 自動起動 - ヘルスチェック & 自動再接続 --- ## 2.0 マイルストーン ### Phase 1: 基盤整備 - [ ] Native MCP Protocol 実装 (C#) - [ ] stdio 通信基盤 - [ ] Unity Editor ↔ MCP Server IPC ### Phase 2: API最適化 - [ ] カテゴリベース API 提供 - [ ] 動的 tools/list - [ ] API 推薦システム ### Phase 3: リアルタイム機能 - [ ] イベント通知システム - [ ] 状態同期機構 - [ ] 双方向通信 ### Phase 4: DX改善 - [ ] ゼロコンフィグセットアップ - [ ] エラーハンドリング強化 - [ ] デバッグツール --- ## 参考リンク - [Model Context Protocol Specification](https://modelcontextprotocol.io/) - [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification) - [Unity Editor Scripting](https://docs.unity3d.com/Manual/ExtendingTheEditor.html)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dsgarage/UniMCP4CC'

If you have feedback or need assistance with the MCP directory API, please join our Discord server