using System.Collections.Generic; namespace io.github.hatayama.uLoopMCP { /// /// Factory class for creating MCP server configuration objects. /// Single Responsibility Principle: Only responsible for object creation. /// /// Design document reference: Packages/src/Editor/ARCHITECTURE.md /// /// Related classes: /// - McpConfigService: Uses this factory to create server configurations /// - McpServerConfigData: Value object that this factory creates /// - UnityMcpPathResolver: Provides TypeScript server paths and project root /// - McpConstants: Contains command constants (NODE_COMMAND) and environment keys /// - McpEditorType: Enum defining supported editor types /// /// Key features: /// - Creates server configuration with editor-specific path formats (absolute/relative) /// - Generates server keys with or without port numbers based on editor type /// - Environment variables are minimal (only UNITY_TCP_PORT, no MCP_CLIENT_NAME) /// public static class McpServerConfigFactory { /// /// Creates Unity MCP server configuration. /// /// The port number to use. /// The path to the TypeScript server. /// The editor type for client name. /// Settings data for Unity MCP. public static McpServerConfigData CreateUnityMcpConfig(int port, string serverPath, McpEditorType editorType) { // Convert server path to appropriate format based on editor type string finalServerPath = GetServerPathForEditor(serverPath, editorType); Dictionary env = new Dictionary { { McpConstants.UNITY_TCP_PORT_ENV_KEY, port.ToString() } // MCP_CLIENT_NAME removed - now using clientInfo.name from MCP protocol #if ULOOPMCP_DEBUG , { McpConstants.ENV_KEY_MCP_DEBUG, McpConstants.ENV_VALUE_TRUE } , { McpConstants.ENV_KEY_NODE_OPTIONS, McpConstants.NODE_OPTIONS_ENABLE_SOURCE_MAPS } #endif }; if (!NodePathResolver.IsNodeAvailable()) { throw new System.InvalidOperationException( "Node.js is not available. Ensure Node.js is installed and accessible via PATH."); } return new McpServerConfigData( command: McpConstants.NODE_COMMAND, args: new[] { finalServerPath }, env: env ); } /// /// Get appropriate server path based on editor type /// /// The original server path /// The editor type /// The processed server path private static string GetServerPathForEditor(string serverPath, McpEditorType editorType) { // Desktop editors (Cursor, VSCode, Windsurf) require absolute path for proper connection if (editorType == McpEditorType.Cursor || editorType == McpEditorType.VSCode || editorType == McpEditorType.Windsurf) { return serverPath; } // CLI / project-level editors (Claude Code, Gemini CLI, Codex) use relative path for better portability return ConvertToRelativePath(serverPath); } /// /// Convert absolute path to relative path for all editors /// /// The absolute path to convert /// The relative path from project root private static string ConvertToRelativePath(string absolutePath) { return UnityMcpPathResolver.MakeRelativeToConfigurationRoot(absolutePath); } /// /// Creates Unity MCP server configuration (legacy overload for backward compatibility). /// /// The port number to use. /// The path to the TypeScript server. /// Settings data for Unity MCP. public static McpServerConfigData CreateUnityMcpConfig(int port, string serverPath) { return CreateUnityMcpConfig(port, serverPath, McpEditorType.ClaudeCode); } /// /// Creates Unity MCP server configuration with development mode support. /// /// The port number. /// The path to the TypeScript server. /// Whether to enable development mode. /// Settings data for Unity MCP. public static McpServerConfigData CreateUnityMcpConfigWithDevelopmentMode(int port, string serverPath, bool developmentMode) { Dictionary env = new Dictionary { { McpConstants.UNITY_TCP_PORT_ENV_KEY, port.ToString() } #if ULOOPMCP_DEBUG , { McpConstants.ENV_KEY_MCP_DEBUG, McpConstants.ENV_VALUE_TRUE } #endif }; if (!NodePathResolver.IsNodeAvailable()) { throw new System.InvalidOperationException( "Node.js is not available. Ensure Node.js is installed and accessible via PATH."); } return new McpServerConfigData( command: McpConstants.NODE_COMMAND, args: new[] { serverPath }, env: env ); } /// /// Creates Unity MCP server key. /// /// The port number. /// The server key. public static string CreateUnityMcpServerKey(int port) { return $"{McpConstants.PROJECT_NAME}-{port}"; } /// /// Creates Unity MCP server key with editor type consideration. /// /// The port number. /// The editor type. /// The server key. public static string CreateUnityMcpServerKey(int port, McpEditorType editorType) { // Windsurf keeps the port number in the key if (editorType == McpEditorType.Windsurf) { return $"{McpConstants.PROJECT_NAME}-{port}"; } // Other editors use simple key without port return McpConstants.PROJECT_NAME; } } }