#if TOOLS namespace Rokojori.Tools { using Rokojori; // Pure protocol logic - no Godot API access except inside ExecuteTool's route calls, // which is why only tools/call needs to cross onto the main thread (see McpServer). public class McpProtocolHandler { public JSONObject Initialize( JSONData id, JSONObject paramsObj ) { var requestedVersion = JsonUtil.GetStringOrNull( paramsObj, "protocolVersion" ); var protocolVersion = string.IsNullOrEmpty( requestedVersion ) ? "2025-06-18" : requestedVersion; var capabilities = new JSONObject(); capabilities.Set( "tools", new JSONObject() ); var serverInfo = new JSONObject(); serverInfo.Set( "name", "godot-mcp" ); serverInfo.Set( "version", "0.1.0" ); var result = new JSONObject(); result.Set( "protocolVersion", protocolVersion ); result.Set( "capabilities", capabilities ); result.Set( "serverInfo", serverInfo ); return JsonRpc.BuildResult( id, result ); } public JSONObject ToolsList( JSONData id ) { var tools = new JSONArray(); tools.Push( ReadResourceRoute.ToolDefinition() ); tools.Push( WriteResourceRoute.ToolDefinition() ); tools.Push( ReadSceneFragmentRoute.ToolDefinition() ); tools.Push( WriteSceneFragmentRoute.ToolDefinition() ); var result = new JSONObject(); result.Set( "tools", tools ); return JsonRpc.BuildResult( id, result ); } public JSONObject ToolCallResult( JSONData id, ToolCallOutcome outcome ) { var item = new JSONObject(); item.Set( "type", "text" ); item.Set( "text", outcome.text ); var content = new JSONArray(); content.Push( item ); var result = new JSONObject(); result.Set( "content", content ); result.Set( "isError", outcome.isError ); return JsonRpc.BuildResult( id, result ); } // Runs on the main thread, dequeued from McpServer's pending-call queue. public ToolCallOutcome ExecuteTool( string toolName, JSONObject arguments ) { switch ( toolName ) { case "read_resource": return ReadResourceRoute.Execute( arguments ); case "write_resource": return WriteResourceRoute.Execute( arguments ); case "read_scene_fragment": return ReadSceneFragmentRoute.Execute( arguments ); case "write_scene_fragment": return WriteSceneFragmentRoute.Execute( arguments ); default: return ToolCallOutcome.Error( "Unknown tool: " + toolName ); } } } } #endif