Skip to content

Commit 4e1b905

Browse files
committed
chore: bump version to 2.1.0; Windows uv resolver improvements; preserve existing uv command; Claude unregister UI fix; .ps1 handling; add generic mcp_source.py
1 parent 5583327 commit 4e1b905

File tree

5 files changed

+69
-43
lines changed

5 files changed

+69
-43
lines changed

UnityMcpBridge/Editor/Helpers/ExecPath.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,16 @@ internal static bool TryRun(
176176
stderr = string.Empty;
177177
try
178178
{
179+
// Handle PowerShell scripts on Windows by invoking through powershell.exe
180+
bool isPs1 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
181+
file.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase);
182+
179183
var psi = new ProcessStartInfo
180184
{
181-
FileName = file,
182-
Arguments = args,
185+
FileName = isPs1 ? "powershell.exe" : file,
186+
Arguments = isPs1
187+
? $"-NoProfile -ExecutionPolicy Bypass -File \"{file}\" {args}".Trim()
188+
: args,
183189
WorkingDirectory = string.IsNullOrEmpty(workingDir) ? Environment.CurrentDirectory : workingDir,
184190
UseShellExecute = false,
185191
RedirectStandardOutput = true,

UnityMcpBridge/Editor/Helpers/ServerInstaller.cs

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.IO;
33
using System.Runtime.InteropServices;
44
using System.Text;
5-
using System.Reflection;
65
using UnityEditor;
76
using UnityEngine;
87

@@ -70,21 +69,19 @@ private static string GetSaveLocation()
7069
{
7170
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
7271
{
73-
return Path.Combine(
74-
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
75-
"AppData",
76-
"Local",
77-
"Programs",
78-
RootFolder
79-
);
72+
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
73+
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty, "AppData", "Local");
74+
return Path.Combine(localAppData, "Programs", RootFolder);
8075
}
8176
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
8277
{
83-
return Path.Combine(
84-
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
85-
"bin",
86-
RootFolder
87-
);
78+
var xdg = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
79+
if (string.IsNullOrEmpty(xdg))
80+
{
81+
xdg = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty,
82+
".local", "share");
83+
}
84+
return Path.Combine(xdg, RootFolder);
8885
}
8986
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
9087
{
@@ -273,12 +270,41 @@ internal static string FindUvPath()
273270
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
274271
string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty;
275272
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty;
273+
string programData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) ?? string.Empty; // optional fallback
274+
275+
// Fast path: resolve from PATH first
276+
try
277+
{
278+
var wherePsi = new System.Diagnostics.ProcessStartInfo
279+
{
280+
FileName = "where",
281+
Arguments = "uv.exe",
282+
UseShellExecute = false,
283+
RedirectStandardOutput = true,
284+
RedirectStandardError = true,
285+
CreateNoWindow = true
286+
};
287+
using var wp = System.Diagnostics.Process.Start(wherePsi);
288+
string output = wp.StandardOutput.ReadToEnd().Trim();
289+
wp.WaitForExit(1500);
290+
if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output))
291+
{
292+
foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
293+
{
294+
string path = line.Trim();
295+
if (File.Exists(path) && ValidateUvBinary(path)) return path;
296+
}
297+
}
298+
}
299+
catch { }
276300

277301
candidates = new[]
278302
{
279303
// Preferred: WinGet Links shims (stable entrypoints)
280304
Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"),
281305
Path.Combine(programFiles, "WinGet", "Links", "uv.exe"),
306+
// Optional low-priority fallback for atypical images
307+
Path.Combine(programData, "Microsoft", "WinGet", "Links", "uv.exe"),
282308

283309
// Common per-user installs
284310
Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"),
@@ -325,33 +351,10 @@ internal static string FindUvPath()
325351
catch { /* ignore */ }
326352
}
327353

328-
// Use platform-appropriate which/where to resolve from PATH
354+
// Use platform-appropriate which/where to resolve from PATH (non-Windows handled here; Windows tried earlier)
329355
try
330356
{
331-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
332-
{
333-
var wherePsi = new System.Diagnostics.ProcessStartInfo
334-
{
335-
FileName = "where",
336-
Arguments = "uv.exe",
337-
UseShellExecute = false,
338-
RedirectStandardOutput = true,
339-
RedirectStandardError = true,
340-
CreateNoWindow = true
341-
};
342-
using var wp = System.Diagnostics.Process.Start(wherePsi);
343-
string output = wp.StandardOutput.ReadToEnd().Trim();
344-
wp.WaitForExit(3000);
345-
if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output))
346-
{
347-
foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
348-
{
349-
string path = line.Trim();
350-
if (File.Exists(path) && ValidateUvBinary(path)) return path;
351-
}
352-
}
353-
}
354-
else
357+
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
355358
{
356359
var whichPsi = new System.Diagnostics.ProcessStartInfo
357360
{

UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,13 +1064,29 @@ private string WriteToConfig(string pythonDir, string configPath, McpClient mcpC
10641064
// Merge without replacing the existing command
10651065
if (mcpClient?.mcpType == McpTypes.VSCode)
10661066
{
1067+
if (existingConfig.servers == null)
1068+
{
1069+
existingConfig.servers = new Newtonsoft.Json.Linq.JObject();
1070+
}
1071+
if (existingConfig.servers.unityMCP == null)
1072+
{
1073+
existingConfig.servers.unityMCP = new Newtonsoft.Json.Linq.JObject();
1074+
}
10671075
existingConfig.servers.unityMCP.args =
10681076
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
10691077
JsonConvert.SerializeObject(unityMCPConfig.args)
10701078
);
10711079
}
10721080
else
10731081
{
1082+
if (existingConfig.mcpServers == null)
1083+
{
1084+
existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject();
1085+
}
1086+
if (existingConfig.mcpServers.unityMCP == null)
1087+
{
1088+
existingConfig.mcpServers.unityMCP = new Newtonsoft.Json.Linq.JObject();
1089+
}
10741090
existingConfig.mcpServers.unityMCP.args =
10751091
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
10761092
JsonConvert.SerializeObject(unityMCPConfig.args)
@@ -1617,7 +1633,8 @@ private void UnregisterWithClaudeCode()
16171633
UnityEngine.Debug.Log($"Successfully removed MCP server: {serverName}");
16181634
break;
16191635
}
1620-
else if (!stderr.Contains("No MCP server found"))
1636+
else if (!string.IsNullOrEmpty(stderr) &&
1637+
!stderr.Contains("No MCP server found", StringComparison.OrdinalIgnoreCase))
16211638
{
16221639
// If it's not a "not found" error, log it and stop trying
16231640
UnityEngine.Debug.LogWarning($"Error removing {serverName}: {stderr}");

UnityMcpBridge/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.coplaydev.unity-mcp",
3-
"version": "2.0.2",
3+
"version": "2.1.0",
44
"displayName": "Unity MCP Bridge",
55
"description": "A bridge that manages and communicates with the sister application, Unity MCP Server, which allows for communications with MCP Clients like Claude Desktop or Cursor.",
66
"unity": "2020.3",

mcp_source.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22
"""
33
Generic helper to switch the Unity MCP package source in a Unity project's
4-
Packages/manifest.json without embedding any personal paths.
4+
Packages/manifest.json. This is useful for switching between upstream and local repos while working on the MCP.
55
66
Usage:
77
python mcp_source.py [--manifest /abs/path/to/manifest.json] [--repo /abs/path/to/unity-mcp] [--choice 1|2|3]

0 commit comments

Comments
 (0)