diff --git a/UnityMcpBridge/Editor/Helpers/ServerInstaller.cs b/UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
index 7f22c41a..9d5682f4 100644
--- a/UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
+++ b/UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
@@ -33,15 +33,7 @@ public static void EnsureServerInstalled()
}
else
{
- string pyprojectPath = Path.Combine(
- saveLocation,
- ServerFolder,
- "src",
- "pyproject.toml"
- );
- string installedVersion = ParseVersionFromPyproject(
- File.ReadAllText(pyprojectPath)
- );
+ string installedVersion = GetInstalledVersion();
string latestVersion = GetLatestVersion();
if (IsNewerVersion(latestVersion, installedVersion))
@@ -148,10 +140,24 @@ private static void InstallServer(string location)
RunCommand("git", $"checkout {BranchName}", workingDirectory: location);
}
+ ///
+ /// Fetches the currently installed version from the local pyproject.toml file.
+ ///
+ public static string GetInstalledVersion()
+ {
+ string pyprojectPath = Path.Combine(
+ GetSaveLocation(),
+ ServerFolder,
+ "src",
+ "pyproject.toml"
+ );
+ return ParseVersionFromPyproject(File.ReadAllText(pyprojectPath));
+ }
+
///
/// Fetches the latest version from the GitHub pyproject.toml file.
///
- private static string GetLatestVersion()
+ public static string GetLatestVersion()
{
using WebClient webClient = new();
string pyprojectContent = webClient.DownloadString(PyprojectUrl);
@@ -188,7 +194,7 @@ private static string ParseVersionFromPyproject(string content)
///
/// Compares two version strings to determine if the latest is newer.
///
- private static bool IsNewerVersion(string latest, string installed)
+ public static bool IsNewerVersion(string latest, string installed)
{
int[] latestParts = latest.Split('.').Select(int.Parse).ToArray();
int[] installedParts = installed.Split('.').Select(int.Parse).ToArray();
diff --git a/UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs b/UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs
index c9ebd769..c794fb71 100644
--- a/UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs
+++ b/UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs
@@ -1,10 +1,6 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Net.Sockets;
using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
@@ -18,13 +14,11 @@ public class UnityMcpEditorWindow : EditorWindow
{
private bool isUnityBridgeRunning = false;
private Vector2 scrollPosition;
- private string claudeConfigStatus = "Not configured";
- private string cursorConfigStatus = "Not configured";
- private string pythonServerStatus = "Not Connected";
- private Color pythonServerStatusColor = Color.red;
+ private string pythonServerInstallationStatus = "Not Installed";
+ private Color pythonServerInstallationStatusColor = Color.red;
private const int unityPort = 6400; // Hardcoded Unity port
private const int mcpPort = 6500; // Hardcoded MCP port
- private McpClients mcpClients = new();
+ private readonly McpClients mcpClients = new();
[MenuItem("Window/Unity MCP")]
public static void ShowWindow()
@@ -34,7 +28,8 @@ public static void ShowWindow()
private void OnEnable()
{
- // Check initial states
+ UpdatePythonServerInstallationStatus();
+
isUnityBridgeRunning = UnityMcpBridge.IsRunning;
foreach (McpClient mcpClient in mcpClients.clients)
{
@@ -57,12 +52,39 @@ private Color GetStatusColor(McpStatus status)
};
}
+ private void UpdatePythonServerInstallationStatus()
+ {
+ string serverPath = ServerInstaller.GetServerPath();
+
+ if (File.Exists(Path.Combine(serverPath, "server.py")))
+ {
+ string installedVersion = ServerInstaller.GetInstalledVersion();
+ string latestVersion = ServerInstaller.GetLatestVersion();
+
+ if (ServerInstaller.IsNewerVersion(latestVersion, installedVersion))
+ {
+ pythonServerInstallationStatus = "Newer Version Available";
+ pythonServerInstallationStatusColor = Color.yellow;
+ }
+ else
+ {
+ pythonServerInstallationStatus = "Up to Date";
+ pythonServerInstallationStatusColor = Color.green;
+ }
+ }
+ else
+ {
+ pythonServerInstallationStatus = "Not Installed";
+ pythonServerInstallationStatusColor = Color.red;
+ }
+ }
+
private void ConfigurationSection(McpClient mcpClient)
{
// Calculate if we should use half-width layout
// Minimum width for half-width layout is 400 pixels
bool useHalfWidth = position.width >= 800;
- float sectionWidth = useHalfWidth ? position.width / 2 - 15 : position.width - 20;
+ float sectionWidth = useHalfWidth ? (position.width / 2) - 15 : position.width - 20;
// Begin horizontal layout if using half-width
if (useHalfWidth && mcpClients.clients.IndexOf(mcpClient) % 2 == 0)
@@ -106,9 +128,11 @@ private void ConfigurationSection(McpClient mcpClient)
EditorGUILayout.Space(8);
// Configure button with improved styling
- GUIStyle buttonStyle = new(GUI.skin.button);
- buttonStyle.padding = new RectOffset(15, 15, 5, 5);
- buttonStyle.margin = new RectOffset(10, 10, 5, 5);
+ GUIStyle buttonStyle = new(GUI.skin.button)
+ {
+ padding = new RectOffset(15, 15, 5, 5),
+ margin = new RectOffset(10, 10, 5, 5),
+ };
// Create muted button style for Manual Setup
GUIStyle mutedButtonStyle = new(buttonStyle);
@@ -156,7 +180,11 @@ private void ConfigurationSection(McpClient mcpClient)
private void DrawStatusDot(Rect statusRect, Color statusColor)
{
Rect dotRect = new(statusRect.x + 6, statusRect.y + 4, 12, 12);
- Vector3 center = new(dotRect.x + dotRect.width / 2, dotRect.y + dotRect.height / 2, 0);
+ Vector3 center = new(
+ dotRect.x + (dotRect.width / 2),
+ dotRect.y + (dotRect.height / 2),
+ 0
+ );
float radius = dotRect.width / 2;
// Draw the main dot
@@ -191,14 +219,14 @@ private void OnGUI()
);
EditorGUILayout.Space(10);
- // Python Server Status Section
+ // Python Server Installation Status Section
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.LabelField("Python Server Status", EditorStyles.boldLabel);
// Status indicator with colored dot
- var statusRect = EditorGUILayout.BeginHorizontal(GUILayout.Height(20));
- DrawStatusDot(statusRect, pythonServerStatusColor);
- EditorGUILayout.LabelField(" " + pythonServerStatus);
+ Rect installStatusRect = EditorGUILayout.BeginHorizontal(GUILayout.Height(20));
+ DrawStatusDot(installStatusRect, pythonServerInstallationStatusColor);
+ EditorGUILayout.LabelField(" " + pythonServerInstallationStatus);
EditorGUILayout.EndHorizontal();
EditorGUILayout.LabelField($"Unity Port: {unityPort}");
@@ -249,13 +277,13 @@ private void ToggleUnityBridge()
private string WriteToConfig(string pythonDir, string configPath)
{
// Create configuration object for unityMCP
- var unityMCPConfig = new McpConfigServer
+ McpConfigServer unityMCPConfig = new()
{
command = "uv",
args = new[] { "--directory", pythonDir, "run", "server.py" },
};
- var jsonSettings = new JsonSerializerSettings { Formatting = Formatting.Indented };
+ JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
// Read existing config if it exists
string existingJson = "{}";
@@ -267,16 +295,13 @@ private string WriteToConfig(string pythonDir, string configPath)
}
catch (Exception e)
{
- UnityEngine.Debug.LogWarning($"Error reading existing config: {e.Message}.");
+ Debug.LogWarning($"Error reading existing config: {e.Message}.");
}
}
// Parse the existing JSON while preserving all properties
dynamic existingConfig = JsonConvert.DeserializeObject(existingJson);
- if (existingConfig == null)
- {
- existingConfig = new Newtonsoft.Json.Linq.JObject();
- }
+ existingConfig ??= new Newtonsoft.Json.Linq.JObject();
// Ensure mcpServers object exists
if (existingConfig.mcpServers == null)
@@ -311,7 +336,7 @@ private void ShowManualInstructionsWindow(string configPath, McpClient mcpClient
string pythonDir = FindPackagePythonDirectory();
// Create the manual configuration message
- var jsonConfig = new McpConfig
+ McpConfig jsonConfig = new()
{
mcpServers = new McpConfigServers
{
@@ -323,7 +348,7 @@ private void ShowManualInstructionsWindow(string configPath, McpClient mcpClient
},
};
- var jsonSettings = new JsonSerializerSettings { Formatting = Formatting.Indented };
+ JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
string manualConfigJson = JsonConvert.SerializeObject(jsonConfig, jsonSettings);
ManualConfigEditorWindow.ShowWindow(configPath, manualConfigJson, mcpClient);
@@ -331,17 +356,18 @@ private void ShowManualInstructionsWindow(string configPath, McpClient mcpClient
private string FindPackagePythonDirectory()
{
- string pythonDir = "/path/to/your/unity-mcp/Python";
+ string pythonDir = ServerInstaller.GetServerPath();
try
{
// Try to find the package using Package Manager API
- var request = UnityEditor.PackageManager.Client.List();
+ UnityEditor.PackageManager.Requests.ListRequest request =
+ UnityEditor.PackageManager.Client.List();
while (!request.IsCompleted) { } // Wait for the request to complete
if (request.Status == UnityEditor.PackageManager.StatusCode.Success)
{
- foreach (var package in request.Result)
+ foreach (UnityEditor.PackageManager.PackageInfo package in request.Result)
{
if (package.name == "com.justinpbarnett.unity-mcp")
{
@@ -360,7 +386,7 @@ private string FindPackagePythonDirectory()
}
else if (request.Error != null)
{
- UnityEngine.Debug.LogError("Failed to list packages: " + request.Error.message);
+ Debug.LogError("Failed to list packages: " + request.Error.message);
}
// If not found via Package Manager, try manual approaches
@@ -370,7 +396,7 @@ private string FindPackagePythonDirectory()
Path.GetFullPath(Path.Combine(Application.dataPath, "unity-mcp", "Python")),
};
- foreach (var dir in possibleDirs)
+ foreach (string dir in possibleDirs)
{
if (Directory.Exists(dir) && File.Exists(Path.Combine(dir, "server.py")))
{
@@ -379,13 +405,11 @@ private string FindPackagePythonDirectory()
}
// If still not found, return the placeholder path
- UnityEngine.Debug.LogWarning(
- "Could not find Python directory, using placeholder path"
- );
+ Debug.LogWarning("Could not find Python directory, using placeholder path");
}
catch (Exception e)
{
- UnityEngine.Debug.LogError($"Error finding package path: {e.Message}");
+ Debug.LogError($"Error finding package path: {e.Message}");
}
return pythonDir;
@@ -453,7 +477,7 @@ private string ConfigureMcpClient(McpClient mcpClient)
}
ShowManualInstructionsWindow(configPath, mcpClient);
- UnityEngine.Debug.LogError(
+ Debug.LogError(
$"Failed to configure {mcpClient.name}: {e.Message}\n{e.StackTrace}"
);
return $"Failed to configure {mcpClient.name}";
@@ -471,7 +495,7 @@ McpClient mcpClient
string pythonDir = FindPackagePythonDirectory();
// Create the manual configuration message
- var jsonConfig = new McpConfig
+ McpConfig jsonConfig = new()
{
mcpServers = new McpConfigServers
{
@@ -483,7 +507,7 @@ McpClient mcpClient
},
};
- var jsonSettings = new JsonSerializerSettings { Formatting = Formatting.Indented };
+ JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
string manualConfigJson = JsonConvert.SerializeObject(jsonConfig, jsonSettings);
ManualConfigEditorWindow.ShowWindow(configPath, manualConfigJson, mcpClient);
@@ -518,7 +542,7 @@ private void CheckMcpConfiguration(McpClient mcpClient)
}
string configJson = File.ReadAllText(configPath);
- var config = JsonConvert.DeserializeObject(configJson);
+ McpConfig config = JsonConvert.DeserializeObject(configJson);
if (config?.mcpServers?.unityMCP != null)
{