Skip to content

Commit 1bd1565

Browse files
Merge pull request #22 from nowsprinting/feature/bridge-timeout
Add timeout settings for the WebSocket and the test execution.
2 parents 129d7e3 + 59e2891 commit 1bd1565

File tree

9 files changed

+207
-14
lines changed

9 files changed

+207
-14
lines changed

Editor/Services/ITestRunnerService.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@ public interface ITestRunnerService
2828
/// <param name="testMode">Test mode to run</param>
2929
/// <param name="testFilter">Optional test filter</param>
3030
/// <param name="completionSource">TaskCompletionSource to resolve when tests are complete</param>
31-
/// <param name="timeoutMinutes">Timeout in minutes, defaults to 10</param>
3231
/// <returns>Task that resolves with test results when tests are complete</returns>
3332
void ExecuteTests(
3433
TestMode testMode,
3534
string testFilter,
36-
TaskCompletionSource<JObject> completionSource,
37-
int timeoutMinutes = 1);
35+
TaskCompletionSource<JObject> completionSource);
3836
}
3937
}

Editor/Services/TestRunnerService.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,11 @@ public List<TestItemInfo> GetAllTests(string testMode = "")
5959
/// <param name="testMode">Test mode to run</param>
6060
/// <param name="testFilter">Optional test filter</param>
6161
/// <param name="completionSource">TaskCompletionSource to resolve when tests are complete</param>
62-
/// <param name="timeoutMinutes">Timeout in minutes, defaults to 10</param>
6362
/// <returns>Task that resolves with test results when tests are complete</returns>
6463
public async void ExecuteTests(
6564
TestMode testMode,
6665
string testFilter,
67-
TaskCompletionSource<JObject> completionSource,
68-
int timeoutMinutes = 1)
66+
TaskCompletionSource<JObject> completionSource)
6967
{
7068
// Create filter
7169
var filter = new Filter
@@ -82,15 +80,18 @@ public async void ExecuteTests(
8280
// Execute tests
8381
_testRunnerApi.Execute(new ExecutionSettings(filter));
8482

83+
// Use timeout from settings if not specified
84+
var timeoutSeconds = McpUnitySettings.Instance.RequestTimeoutSeconds;
85+
8586
Task completedTask = await Task.WhenAny(
8687
completionSource.Task,
87-
Task.Delay(TimeSpan.FromMinutes(timeoutMinutes))
88+
Task.Delay(TimeSpan.FromSeconds(timeoutSeconds))
8889
);
8990

9091
if (completedTask != completionSource.Task)
9192
{
9293
completionSource.SetResult(McpUnitySocketHandler.CreateErrorResponse(
93-
$"Test run timed out after {timeoutMinutes} minutes",
94+
$"Test run timed out after {timeoutSeconds} seconds",
9495
"test_runner_timeout"
9596
));
9697
}

Editor/UnityBridge/McpUnityEditorWindow.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,24 @@ private void DrawServerTab()
107107

108108
EditorGUILayout.Space();
109109

110+
// Test timeout setting
111+
EditorGUILayout.BeginHorizontal();
112+
int newTimeout = EditorGUILayout.IntField(new GUIContent("Request Timeout (seconds)", "Timeout in seconds for tool request"), settings.RequestTimeoutSeconds);
113+
if (newTimeout < McpUnitySettings.RequestTimeoutMinimum)
114+
{
115+
newTimeout = McpUnitySettings.RequestTimeoutMinimum;
116+
Debug.LogError($"Request timeout must be at least {McpUnitySettings.RequestTimeoutMinimum} seconds.");
117+
}
118+
119+
if (newTimeout != settings.RequestTimeoutSeconds)
120+
{
121+
settings.RequestTimeoutSeconds = newTimeout;
122+
settings.SaveSettings();
123+
}
124+
EditorGUILayout.EndHorizontal();
125+
126+
EditorGUILayout.Space();
127+
110128
// Auto start server toggle
111129
bool autoStartServer = EditorGUILayout.Toggle(new GUIContent("Auto Start Server", "Automatically starts the MCP server when Unity opens"), settings.AutoStartServer);
112130
if (autoStartServer != settings.AutoStartServer)

Editor/UnityBridge/McpUnitySettings.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,28 @@ public class McpUnitySettings
1515
// Constants
1616
public const string ServerVersion = "1.0.0";
1717
public const string PackageName = "com.gamelovers.mcp-unity";
18+
public const int RequestTimeoutMinimum = 10;
19+
20+
#if UNITY_EDITOR_WIN
21+
private const string EnvUnityPort = "UNITY_PORT";
22+
private const string EnvUnityRequestTimeout = "UNITY_REQUEST_TIMEOUT";
23+
#endif
1824

1925
private static McpUnitySettings _instance;
2026
private static readonly string SettingsPath = "ProjectSettings/McpUnitySettings.json";
2127

2228
// Server settings
29+
#if !UNITY_EDITOR_WIN
30+
[field: SerializeField] // Note: On Windows, this property is persisted in per-user environment variables.
31+
#endif
2332
public int Port { get; set; } = 8090;
2433

34+
#if !UNITY_EDITOR_WIN
35+
[field: SerializeField] // Note: On Windows, this property is persisted in per-user environment variables.
36+
#endif
37+
[Tooltip("Timeout in seconds for tool request")]
38+
public int RequestTimeoutSeconds { get; set; } = RequestTimeoutMinimum;
39+
2540
[Tooltip("Whether to automatically start the MCP server when Unity opens")]
2641
public bool AutoStartServer = true;
2742

@@ -66,12 +81,19 @@ public void LoadSettings()
6681
JsonUtility.FromJsonOverwrite(json, this);
6782
}
6883

84+
#if UNITY_EDITOR_WIN
6985
// Check for environment variable PORT
70-
string envPort = System.Environment.GetEnvironmentVariable("UNITY_PORT");
86+
string envPort = System.Environment.GetEnvironmentVariable(EnvUnityPort);
7187
if (!string.IsNullOrEmpty(envPort) && int.TryParse(envPort, out int port))
7288
{
7389
Port = port;
7490
}
91+
string envTimeout = System.Environment.GetEnvironmentVariable(EnvUnityRequestTimeout);
92+
if (!string.IsNullOrEmpty(envTimeout) && int.TryParse(envTimeout, out int timeout))
93+
{
94+
RequestTimeoutSeconds = timeout;
95+
}
96+
#endif
7597
}
7698
catch (Exception ex)
7799
{
@@ -90,10 +112,15 @@ public void SaveSettings()
90112
// Save settings to McpUnitySettings.json
91113
string json = JsonUtility.ToJson(this, true);
92114
File.WriteAllText(SettingsPath, json);
93-
115+
116+
#if UNITY_EDITOR_WIN
94117
// Set environment variable PORT for the Node.js process
95118
// Note: This will only affect processes started after this point
96-
System.Environment.SetEnvironmentVariable("UNITY_PORT", Port.ToString(), System.EnvironmentVariableTarget.User);
119+
// Note: EnvironmentVariableTarget.User should be used on .NET implementations running on Windows systems only.
120+
// see: https://learn.microsoft.com/ja-jp/dotnet/api/system.environmentvariabletarget?view=net-8.0#fields
121+
Environment.SetEnvironmentVariable(EnvUnityPort, Port.ToString(), EnvironmentVariableTarget.User);
122+
Environment.SetEnvironmentVariable(EnvUnityRequestTimeout, RequestTimeoutSeconds.ToString(), EnvironmentVariableTarget.User);
123+
#endif
97124
}
98125
catch (Exception ex)
99126
{

README-ja.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,53 @@ MCP Unityサーバーを起動するには2つの方法があります:
211211
node Server/build/index.js
212212
```
213213

214+
## オプション: タイムアウト設定
215+
216+
デフォルトでは、MCPサーバーとWebSocket間のタイムアウトは 10 秒です。
217+
お使いのOSに応じて変更できます。
218+
219+
<details>
220+
<summary><span style="font-size: 1.1em; font-weight: bold;">Option 1: Windows OS</span></summary>
221+
222+
1. Unityエディターを開きます
223+
2. **Tools > MCP Unity > Server Window** に移動します
224+
3. **Request Timeout (seconds)** の値を希望のタイムアウト秒数に変更します
225+
4. Unityはシステム環境変数UNITY_REQUEST_TIMEOUTに新しいタイムアウト値を設定します
226+
5. Node.jsサーバーを再起動します
227+
6. **Start Server** をもう一度クリックして、UnityエディターのWebソケットをNode.js MCPサーバーに再接続します
228+
229+
</details>
230+
231+
<details>
232+
<summary><span style="font-size: 1.1em; font-weight: bold;">Option 2: Windows以外のOS</span></summary>
233+
234+
Windows 以外の OS の場合は、次の 2 か所で設定する必要があります。
235+
236+
### エディター内プロセスのタイムアウト
237+
238+
1. Unityエディターを開きます
239+
2. **Tools > MCP Unity > Server Window** に移動します
240+
3. **Request Timeout (seconds)** の値を希望のタイムアウト秒数に変更します
241+
242+
### WebSocketのタイムアウト
243+
244+
1. ターミナルで UNITY_REQUEST_TIMEOUT 環境変数を設定します
245+
- Powershell
246+
```powershell
247+
$env:UNITY_REQUEST_TIMEOUT = "300"
248+
```
249+
- Command Prompt/Terminal
250+
```cmd
251+
set UNITY_REQUEST_TIMEOUT=300
252+
```
253+
2. Node.jsサーバーを再起動します
254+
3. **Start Server** をもう一度クリックして、UnityエディターのWebソケットをNode.js MCPサーバーに再接続します
255+
256+
</details>
257+
258+
> [!TIP]
259+
> AIコーディングIDE(Claude Desktop、Cursor IDE、Windsurf IDE など)とMCPサーバー間のタイムアウト設定は、IDEによって異なります。
260+
214261
## <a name="debug-server"></a>サーバーのデバッグ
215262

216263
MCP Unityサーバーをデバッグするには、以下の方法を使用できます:

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,53 @@ By default, the WebSocket server runs on port 8090. You can change this port in
236236

237237
</details>
238238

239+
## Optional: Set Timeout
240+
241+
By default, the timeout between the MCP server and the WebSocket is 10 seconds.
242+
You can change depending on the OS you are using:
243+
244+
<details>
245+
<summary><span style="font-size: 1.1em; font-weight: bold;">Option 1: Windows OS</span></summary>
246+
247+
1. Open the Unity Editor
248+
2. Navigate to Tools > MCP Unity > Server Window
249+
3. Change the "Request Timeout (seconds)" value to your desired timeout seconds
250+
4. Unity will setup the system environment variable UNITY_REQUEST_TIMEOUT to the new timeout value
251+
5. Restart the Node.js server
252+
6. Click again on "Start Server" to reconnect the Unity Editor web socket to the Node.js MCP Server
253+
254+
</details>
255+
256+
<details>
257+
<summary><span style="font-size: 1.1em; font-weight: bold;">Option 2: Non-Windows OS</span></summary>
258+
259+
For non-Windows OS, you need to configure two places:
260+
261+
### In Editor Process Timeout
262+
263+
1. Open the Unity Editor
264+
2. Navigate to Tools > MCP Unity > Server Window
265+
3. Change the "Request Timeout (seconds)" value to your desired timeout seconds
266+
267+
### WebSocket Timeout
268+
269+
1. Set the UNITY_REQUEST_TIMEOUT environment variable in the terminal
270+
- Powershell
271+
```powershell
272+
$env:UNITY_REQUEST_TIMEOUT = "300"
273+
```
274+
- Command Prompt/Terminal
275+
```cmd
276+
set UNITY_REQUEST_TIMEOUT=300
277+
```
278+
2. Restart the Node.js server
279+
3. Click again on "Start Server" to reconnect the Unity Editor web socket to the Node.js MCP Server
280+
281+
</details>
282+
283+
> [!TIP]
284+
> The timeout between your AI Coding IDE (e.g., Claude Desktop, Cursor IDE, Windsurf IDE) and the MCP Server depends on the IDE.
285+
239286
## <a name="debug-server"></a>Debugging the Server
240287

241288
<details>

README_zh-CN.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,53 @@ MCP Unity 通过将 Unity `Library/PackedCache` 文件夹添加到您的工作
213213
node Server/build/index.js
214214
```
215215

216+
## 可选:设置超时
217+
218+
默认情况下,MCP 服务器与 WebSocket 之间的超时时间为 10 秒。
219+
您可以根据所使用的操作系统进行更改:
220+
221+
<details>
222+
<summary><span style="font-size: 1.1em; font-weight: bold;">Option 1: Windows OS</span></summary>
223+
224+
1. 打开 Unity 编辑器
225+
2. 导航至 Tools > MCP Unity > Server Window
226+
3. 将 "Request Timeout (seconds)" 值更改为所需的超时秒数
227+
4. Unity 会将系统环境变量 UNITY_REQUEST_TIMEOUT 设置为新的超时值
228+
5. 重启 Node.js 服务器
229+
6. 再次点击“启动服务器”,将 Unity 编辑器 Web 套接字重新连接到 Node.js MCP 服务器
230+
231+
</details>
232+
233+
<details>
234+
<summary><span style="font-size: 1.1em; font-weight: bold;">Option 2: 非Windows操作系统</span></summary>
235+
236+
对于非Windows操作系统,需要配置两个地方:
237+
238+
### 编辑器进程超时
239+
240+
1. 打开 Unity 编辑器
241+
2. 导航至 Tools > MCP Unity > Server Window
242+
3. 将 "Request Timeout (seconds)" 值更改为所需的超时秒数
243+
244+
### WebSocket 超时
245+
246+
1. 在终端中设置 UNITY_REQUEST_TIMEOUT 环境变量
247+
- Powershell
248+
```powershell
249+
$env:UNITY_REQUEST_TIMEOUT = "300"
250+
```
251+
- Command Prompt/Terminal
252+
```cmd
253+
set UNITY_REQUEST_TIMEOUT=300
254+
```
255+
2. 重启 Node.js 服务器
256+
3. 再次点击“启动服务器”,将 Unity 编辑器 Web 套接字重新连接到 Node.js MCP 服务器
257+
258+
</details>
259+
260+
> [!TIP]
261+
> 您的 AI 编码 IDE(例如,Claude Desktop、Cursor IDE、Windsurf IDE)和 MCP 服务器之间的超时取决于 IDE。
262+
216263
## <a name="debug-server"></a>调试服务器
217264

218265
要调试 MCP Unity 服务器,您可以使用以下方法:

Server/build/unity/mcpUnity.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export class McpUnity {
88
port;
99
ws = null;
1010
pendingRequests = new Map();
11-
REQUEST_TIMEOUT = 10000;
11+
REQUEST_TIMEOUT;
1212
retryDelay = 1000;
1313
constructor(logger) {
1414
this.logger = logger;
@@ -19,6 +19,10 @@ export class McpUnity {
1919
const envPort = process.env.UNITY_PORT || envRegistry;
2020
this.port = envPort ? parseInt(envPort, 10) : 8090;
2121
this.logger.info(`Using port: ${this.port} for Unity WebSocket connection`);
22+
// Initialize timeout from environment variable (in seconds; it is the same as Cline) or use default (10 seconds)
23+
const envTimeout = process.env.UNITY_REQUEST_TIMEOUT;
24+
this.REQUEST_TIMEOUT = envTimeout ? parseInt(envTimeout, 10) * 1000 : 10000;
25+
this.logger.info(`Using request timeout: ${this.REQUEST_TIMEOUT / 1000} seconds`);
2226
}
2327
/**
2428
* Start the Unity connection

Server/src/unity/mcpUnity.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class McpUnity {
3333
private port: number;
3434
private ws: WebSocket | null = null;
3535
private pendingRequests: Map<string, PendingRequest> = new Map<string, PendingRequest>();
36-
private readonly REQUEST_TIMEOUT = 10000;
36+
private readonly REQUEST_TIMEOUT: number;
3737
private retryDelay = 1000;
3838

3939
constructor(logger: Logger) {
@@ -46,8 +46,12 @@ export class McpUnity {
4646

4747
const envPort = process.env.UNITY_PORT || envRegistry;
4848
this.port = envPort ? parseInt(envPort, 10) : 8090;
49-
5049
this.logger.info(`Using port: ${this.port} for Unity WebSocket connection`);
50+
51+
// Initialize timeout from environment variable (in seconds; it is the same as Cline) or use default (10 seconds)
52+
const envTimeout = process.env.UNITY_REQUEST_TIMEOUT;
53+
this.REQUEST_TIMEOUT = envTimeout ? parseInt(envTimeout, 10) * 1000 : 10000;
54+
this.logger.info(`Using request timeout: ${this.REQUEST_TIMEOUT / 1000} seconds`);
5155
}
5256

5357
/**

0 commit comments

Comments
 (0)