Skip to content

Commit 50c67b1

Browse files
committed
fix: critical timezone and import bugs from code review
- Remove incorrect port safety check that treated reclaimed ports as errors (GetPortWithFallback may legitimately return same port if it became available) - Fix timezone-aware vs naive datetime mixing in unity_connection.py sorting (use timestamp() for comparison to avoid TypeError) - Normalize all datetime comparisons in port_discovery.py to UTC (file_mtime and last_heartbeat now consistently timezone-aware) - Add missing send_with_unity_instance import in Server/tools/manage_script.py (was causing NameError at runtime on lines 108 and 488) All 88 tests pass (76 passed + 5 skipped + 7 xpassed)
1 parent 0633261 commit 50c67b1

File tree

5 files changed

+31
-18
lines changed

5 files changed

+31
-18
lines changed

MCPForUnity/Editor/MCPForUnityBridge.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -366,16 +366,18 @@ public static void Start()
366366
int oldPort = currentUnityPort;
367367
currentUnityPort = PortManager.GetPortWithFallback();
368368

369-
// Safety check: ensure we got a different port
370-
if (currentUnityPort == oldPort)
371-
{
372-
McpLog.Error($"Port {oldPort} is occupied and no alternative port available");
373-
throw;
374-
}
375-
369+
// GetPortWithFallback() may return the same port if it became available during wait
370+
// or a different port if switching to an alternative
376371
if (IsDebugEnabled())
377372
{
378-
McpLog.Info($"Port {oldPort} occupied, switching to port {currentUnityPort}");
373+
if (currentUnityPort == oldPort)
374+
{
375+
McpLog.Info($"Port {oldPort} became available, proceeding");
376+
}
377+
else
378+
{
379+
McpLog.Info($"Port {oldPort} occupied, switching to port {currentUnityPort}");
380+
}
379381
}
380382

381383
listener = new TcpListener(IPAddress.Loopback, currentUnityPort);

MCPForUnity/UnityMcpServer~/src/unity_connection.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,12 @@ def _resolve_instance_id(self, instance_identifier: Optional[str], instances: Li
484484
logger.debug(f"Using default instance: {instance_identifier}")
485485
else:
486486
# Use the most recently active instance
487-
# Instances with no heartbeat (None) should be sorted last (use epoch as sentinel)
488-
from datetime import datetime
489-
sorted_instances = sorted(instances, key=lambda i: i.last_heartbeat or datetime.fromtimestamp(0), reverse=True)
487+
# Instances with no heartbeat (None) should be sorted last (use 0 as sentinel)
488+
sorted_instances = sorted(
489+
instances,
490+
key=lambda inst: inst.last_heartbeat.timestamp() if inst.last_heartbeat else 0.0,
491+
reverse=True,
492+
)
490493
logger.info(f"No instance specified, using most recent: {sorted_instances[0].id}")
491494
return sorted_instances[0]
492495

Server/port_discovery.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import logging
1717
import os
1818
import struct
19-
from datetime import datetime
19+
from datetime import datetime, timezone
2020
from pathlib import Path
2121
import socket
2222
from typing import Optional, List, Dict
@@ -238,7 +238,7 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
238238
for status_file_path in status_files:
239239
try:
240240
status_path = Path(status_file_path)
241-
file_mtime = datetime.fromtimestamp(status_path.stat().st_mtime)
241+
file_mtime = datetime.fromtimestamp(status_path.stat().st_mtime, tz=timezone.utc)
242242

243243
with status_path.open('r') as f:
244244
data = json.load(f)
@@ -258,7 +258,12 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
258258
heartbeat_str = data.get('last_heartbeat')
259259
if heartbeat_str:
260260
try:
261-
last_heartbeat = datetime.fromisoformat(heartbeat_str.replace('Z', '+00:00'))
261+
parsed = datetime.fromisoformat(heartbeat_str.replace('Z', '+00:00'))
262+
# Normalize to UTC for consistent comparison
263+
if parsed.tzinfo is None:
264+
last_heartbeat = parsed.replace(tzinfo=timezone.utc)
265+
else:
266+
last_heartbeat = parsed.astimezone(timezone.utc)
262267
except Exception:
263268
pass
264269

Server/tools/manage_script.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from fastmcp import FastMCP, Context
77

88
from registry import mcp_for_unity_tool
9-
from tools import get_unity_instance_from_context
9+
from tools import get_unity_instance_from_context, send_with_unity_instance
1010
import unity_connection
1111

1212

Server/unity_connection.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,12 @@ def _resolve_instance_id(self, instance_identifier: Optional[str], instances: Li
484484
logger.debug(f"Using default instance: {instance_identifier}")
485485
else:
486486
# Use the most recently active instance
487-
# Instances with no heartbeat (None) should be sorted last (use epoch as sentinel)
488-
from datetime import datetime
489-
sorted_instances = sorted(instances, key=lambda i: i.last_heartbeat or datetime.fromtimestamp(0), reverse=True)
487+
# Instances with no heartbeat (None) should be sorted last (use 0 as sentinel)
488+
sorted_instances = sorted(
489+
instances,
490+
key=lambda inst: inst.last_heartbeat.timestamp() if inst.last_heartbeat else 0.0,
491+
reverse=True,
492+
)
490493
logger.info(f"No instance specified, using most recent: {sorted_instances[0].id}")
491494
return sorted_instances[0]
492495

0 commit comments

Comments
 (0)