diff --git a/Editor/Services/ITestRunnerService.cs b/Editor/Services/ITestRunnerService.cs index 780ba3f3..d23f7cc7 100644 --- a/Editor/Services/ITestRunnerService.cs +++ b/Editor/Services/ITestRunnerService.cs @@ -26,12 +26,10 @@ public interface ITestRunnerService /// Test mode to run /// Optional test filter /// TaskCompletionSource to resolve when tests are complete - /// Timeout in minutes, defaults to 10 /// Task that resolves with test results when tests are complete void ExecuteTests( TestMode testMode, string testFilter, - TaskCompletionSource completionSource, - int timeoutMinutes = 1); + TaskCompletionSource completionSource); } } diff --git a/Editor/Services/TestRunnerService.cs b/Editor/Services/TestRunnerService.cs index 7b7fc87d..6d21e5ae 100644 --- a/Editor/Services/TestRunnerService.cs +++ b/Editor/Services/TestRunnerService.cs @@ -49,13 +49,11 @@ public List GetAllTests() /// Test mode to run /// Optional test filter /// TaskCompletionSource to resolve when tests are complete - /// Timeout in minutes, defaults to 10 /// Task that resolves with test results when tests are complete public async void ExecuteTests( TestMode testMode, string testFilter, - TaskCompletionSource completionSource, - int timeoutMinutes = 1) + TaskCompletionSource completionSource) { // Create filter var filter = new Filter @@ -72,15 +70,18 @@ public async void ExecuteTests( // Execute tests _testRunnerApi.Execute(new ExecutionSettings(filter)); + // Use timeout from settings if not specified + var timeoutSeconds = McpUnitySettings.Instance.RequestTimeoutSeconds; + Task completedTask = await Task.WhenAny( completionSource.Task, - Task.Delay(TimeSpan.FromMinutes(timeoutMinutes)) + Task.Delay(TimeSpan.FromSeconds(timeoutSeconds)) ); if (completedTask != completionSource.Task) { completionSource.SetResult(McpUnitySocketHandler.CreateErrorResponse( - $"Test run timed out after {timeoutMinutes} minutes", + $"Test run timed out after {timeoutSeconds} seconds", "test_runner_timeout" )); } diff --git a/Editor/UnityBridge/McpUnityEditorWindow.cs b/Editor/UnityBridge/McpUnityEditorWindow.cs index 86585300..ded9242f 100644 --- a/Editor/UnityBridge/McpUnityEditorWindow.cs +++ b/Editor/UnityBridge/McpUnityEditorWindow.cs @@ -107,6 +107,24 @@ private void DrawServerTab() EditorGUILayout.Space(); + // Test timeout setting + EditorGUILayout.BeginHorizontal(); + int newTimeout = EditorGUILayout.IntField(new GUIContent("Request Timeout (seconds)", "Timeout in seconds for tool request"), settings.RequestTimeoutSeconds); + if (newTimeout < McpUnitySettings.RequestTimeoutMinimum) + { + newTimeout = McpUnitySettings.RequestTimeoutMinimum; + Debug.LogError($"Request timeout must be at least {McpUnitySettings.RequestTimeoutMinimum} seconds."); + } + + if (newTimeout != settings.RequestTimeoutSeconds) + { + settings.RequestTimeoutSeconds = newTimeout; + settings.SaveSettings(); + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + // Auto start server toggle bool autoStartServer = EditorGUILayout.Toggle(new GUIContent("Auto Start Server", "Automatically starts the MCP server when Unity opens"), settings.AutoStartServer); if (autoStartServer != settings.AutoStartServer) diff --git a/Editor/UnityBridge/McpUnitySettings.cs b/Editor/UnityBridge/McpUnitySettings.cs index 821101ab..056cd431 100644 --- a/Editor/UnityBridge/McpUnitySettings.cs +++ b/Editor/UnityBridge/McpUnitySettings.cs @@ -15,13 +15,28 @@ public class McpUnitySettings // Constants public const string ServerVersion = "1.0.0"; public const string PackageName = "com.gamelovers.mcp-unity"; + public const int RequestTimeoutMinimum = 10; + +#if UNITY_EDITOR_WIN + private const string EnvUnityPort = "UNITY_PORT"; + private const string EnvUnityRequestTimeout = "UNITY_REQUEST_TIMEOUT"; +#endif private static McpUnitySettings _instance; private static readonly string SettingsPath = "ProjectSettings/McpUnitySettings.json"; // Server settings +#if !UNITY_EDITOR_WIN + [field: SerializeField] // Note: On Windows, this property is persisted in per-user environment variables. +#endif public int Port { get; set; } = 8090; +#if !UNITY_EDITOR_WIN + [field: SerializeField] // Note: On Windows, this property is persisted in per-user environment variables. +#endif + [Tooltip("Timeout in seconds for tool request")] + public int RequestTimeoutSeconds { get; set; } = RequestTimeoutMinimum; + [Tooltip("Whether to automatically start the MCP server when Unity opens")] public bool AutoStartServer = true; @@ -66,12 +81,19 @@ public void LoadSettings() JsonUtility.FromJsonOverwrite(json, this); } +#if UNITY_EDITOR_WIN // Check for environment variable PORT - string envPort = System.Environment.GetEnvironmentVariable("UNITY_PORT"); + string envPort = System.Environment.GetEnvironmentVariable(EnvUnityPort); if (!string.IsNullOrEmpty(envPort) && int.TryParse(envPort, out int port)) { Port = port; } + string envTimeout = System.Environment.GetEnvironmentVariable(EnvUnityRequestTimeout); + if (!string.IsNullOrEmpty(envTimeout) && int.TryParse(envTimeout, out int timeout)) + { + RequestTimeoutSeconds = timeout; + } +#endif } catch (Exception ex) { @@ -90,10 +112,15 @@ public void SaveSettings() // Save settings to McpUnitySettings.json string json = JsonUtility.ToJson(this, true); File.WriteAllText(SettingsPath, json); - + +#if UNITY_EDITOR_WIN // Set environment variable PORT for the Node.js process // Note: This will only affect processes started after this point - System.Environment.SetEnvironmentVariable("UNITY_PORT", Port.ToString(), System.EnvironmentVariableTarget.User); + // Note: EnvironmentVariableTarget.User should be used on .NET implementations running on Windows systems only. + // see: https://learn.microsoft.com/ja-jp/dotnet/api/system.environmentvariabletarget?view=net-8.0#fields + Environment.SetEnvironmentVariable(EnvUnityPort, Port.ToString(), EnvironmentVariableTarget.User); + Environment.SetEnvironmentVariable(EnvUnityRequestTimeout, RequestTimeoutSeconds.ToString(), EnvironmentVariableTarget.User); +#endif } catch (Exception ex) { diff --git a/README-ja.md b/README-ja.md index 93c0fcb6..cc4a75ef 100644 --- a/README-ja.md +++ b/README-ja.md @@ -211,6 +211,53 @@ MCP Unityサーバーを起動するには2つの方法があります: node Server/build/index.js ``` +## オプション: タイムアウト設定 + +デフォルトでは、MCPサーバーとWebSocket間のタイムアウトは 10 秒です。 +お使いのOSに応じて変更できます。 + +
+Option 1: Windows OS + +1. Unityエディターを開きます +2. **Tools > MCP Unity > Server Window** に移動します +3. **Request Timeout (seconds)** の値を希望のタイムアウト秒数に変更します +4. Unityはシステム環境変数UNITY_REQUEST_TIMEOUTに新しいタイムアウト値を設定します +5. Node.jsサーバーを再起動します +6. **Start Server** をもう一度クリックして、UnityエディターのWebソケットをNode.js MCPサーバーに再接続します + +
+ +
+Option 2: Windows以外のOS + +Windows 以外の OS の場合は、次の 2 か所で設定する必要があります。 + +### エディター内プロセスのタイムアウト + +1. Unityエディターを開きます +2. **Tools > MCP Unity > Server Window** に移動します +3. **Request Timeout (seconds)** の値を希望のタイムアウト秒数に変更します + +### WebSocketのタイムアウト + +1. ターミナルで UNITY_REQUEST_TIMEOUT 環境変数を設定します + - Powershell + ```powershell + $env:UNITY_REQUEST_TIMEOUT = "300" + ``` + - Command Prompt/Terminal + ```cmd + set UNITY_REQUEST_TIMEOUT=300 + ``` +2. Node.jsサーバーを再起動します +3. **Start Server** をもう一度クリックして、UnityエディターのWebソケットをNode.js MCPサーバーに再接続します + +
+ +> [!TIP] +> AIコーディングIDE(Claude Desktop、Cursor IDE、Windsurf IDE など)とMCPサーバー間のタイムアウト設定は、IDEによって異なります。 + ## サーバーのデバッグ MCP Unityサーバーをデバッグするには、以下の方法を使用できます: diff --git a/README.md b/README.md index c15a39bf..800ec710 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,53 @@ By default, the WebSocket server runs on port 8090. You can change this port in +## Optional: Set Timeout + +By default, the timeout between the MCP server and the WebSocket is 10 seconds. +You can change depending on the OS you are using: + +
+Option 1: Windows OS + +1. Open the Unity Editor +2. Navigate to Tools > MCP Unity > Server Window +3. Change the "Request Timeout (seconds)" value to your desired timeout seconds +4. Unity will setup the system environment variable UNITY_REQUEST_TIMEOUT to the new timeout value +5. Restart the Node.js server +6. Click again on "Start Server" to reconnect the Unity Editor web socket to the Node.js MCP Server + +
+ +
+Option 2: Non-Windows OS + +For non-Windows OS, you need to configure two places: + +### In Editor Process Timeout + +1. Open the Unity Editor +2. Navigate to Tools > MCP Unity > Server Window +3. Change the "Request Timeout (seconds)" value to your desired timeout seconds + +### WebSocket Timeout + +1. Set the UNITY_REQUEST_TIMEOUT environment variable in the terminal + - Powershell + ```powershell + $env:UNITY_REQUEST_TIMEOUT = "300" + ``` + - Command Prompt/Terminal + ```cmd + set UNITY_REQUEST_TIMEOUT=300 + ``` +2. Restart the Node.js server +3. Click again on "Start Server" to reconnect the Unity Editor web socket to the Node.js MCP Server + +
+ +> [!TIP] +> The timeout between your AI Coding IDE (e.g., Claude Desktop, Cursor IDE, Windsurf IDE) and the MCP Server depends on the IDE. + ## Debugging the Server
diff --git a/README_zh-CN.md b/README_zh-CN.md index be21ec0a..f1839213 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -213,6 +213,53 @@ MCP Unity 通过将 Unity `Library/PackedCache` 文件夹添加到您的工作 node Server/build/index.js ``` +## 可选:设置超时 + +默认情况下,MCP 服务器与 WebSocket 之间的超时时间为 10 秒。 +您可以根据所使用的操作系统进行更改: + +
+Option 1: Windows OS + +1. 打开 Unity 编辑器 +2. 导航至 Tools > MCP Unity > Server Window +3. 将 "Request Timeout (seconds)" 值更改为所需的超时秒数 +4. Unity 会将系统环境变量 UNITY_REQUEST_TIMEOUT 设置为新的超时值 +5. 重启 Node.js 服务器 +6. 再次点击“启动服务器”,将 Unity 编辑器 Web 套接字重新连接到 Node.js MCP 服务器 + +
+ +
+Option 2: 非Windows操作系统 + +对于非Windows操作系统,需要配置两个地方: + +### 编辑器进程超时 + +1. 打开 Unity 编辑器 +2. 导航至 Tools > MCP Unity > Server Window +3. 将 "Request Timeout (seconds)" 值更改为所需的超时秒数 + +### WebSocket 超时 + +1. 在终端中设置 UNITY_REQUEST_TIMEOUT 环境变量 + - Powershell + ```powershell + $env:UNITY_REQUEST_TIMEOUT = "300" + ``` + - Command Prompt/Terminal + ```cmd + set UNITY_REQUEST_TIMEOUT=300 + ``` +2. 重启 Node.js 服务器 +3. 再次点击“启动服务器”,将 Unity 编辑器 Web 套接字重新连接到 Node.js MCP 服务器 + +
+ +> [!TIP] +> 您的 AI 编码 IDE(例如,Claude Desktop、Cursor IDE、Windsurf IDE)和 MCP 服务器之间的超时取决于 IDE。 + ## 调试服务器 要调试 MCP Unity 服务器,您可以使用以下方法: diff --git a/Server/build/unity/mcpUnity.js b/Server/build/unity/mcpUnity.js index 44fd6935..7013a8f8 100644 --- a/Server/build/unity/mcpUnity.js +++ b/Server/build/unity/mcpUnity.js @@ -8,7 +8,7 @@ export class McpUnity { port; ws = null; pendingRequests = new Map(); - REQUEST_TIMEOUT = 10000; + REQUEST_TIMEOUT; retryDelay = 1000; constructor(logger) { this.logger = logger; @@ -19,6 +19,10 @@ export class McpUnity { const envPort = process.env.UNITY_PORT || envRegistry; this.port = envPort ? parseInt(envPort, 10) : 8090; this.logger.info(`Using port: ${this.port} for Unity WebSocket connection`); + // Initialize timeout from environment variable (in seconds; it is the same as Cline) or use default (10 seconds) + const envTimeout = process.env.UNITY_REQUEST_TIMEOUT; + this.REQUEST_TIMEOUT = envTimeout ? parseInt(envTimeout, 10) * 1000 : 10000; + this.logger.info(`Using request timeout: ${this.REQUEST_TIMEOUT / 1000} seconds`); } /** * Start the Unity connection diff --git a/Server/src/unity/mcpUnity.ts b/Server/src/unity/mcpUnity.ts index 3b552635..83838c00 100644 --- a/Server/src/unity/mcpUnity.ts +++ b/Server/src/unity/mcpUnity.ts @@ -33,7 +33,7 @@ export class McpUnity { private port: number; private ws: WebSocket | null = null; private pendingRequests: Map = new Map(); - private readonly REQUEST_TIMEOUT = 10000; + private readonly REQUEST_TIMEOUT: number; private retryDelay = 1000; constructor(logger: Logger) { @@ -46,8 +46,12 @@ export class McpUnity { const envPort = process.env.UNITY_PORT || envRegistry; this.port = envPort ? parseInt(envPort, 10) : 8090; - this.logger.info(`Using port: ${this.port} for Unity WebSocket connection`); + + // Initialize timeout from environment variable (in seconds; it is the same as Cline) or use default (10 seconds) + const envTimeout = process.env.UNITY_REQUEST_TIMEOUT; + this.REQUEST_TIMEOUT = envTimeout ? parseInt(envTimeout, 10) * 1000 : 10000; + this.logger.info(`Using request timeout: ${this.REQUEST_TIMEOUT / 1000} seconds`); } /**