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

main
David Sarno 2025-08-13 14:02:19 -07:00
parent 5583327a03
commit 4e1b905ea0
5 changed files with 69 additions and 43 deletions

View File

@ -176,10 +176,16 @@ namespace UnityMcpBridge.Editor.Helpers
stderr = string.Empty;
try
{
// Handle PowerShell scripts on Windows by invoking through powershell.exe
bool isPs1 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
file.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase);
var psi = new ProcessStartInfo
{
FileName = file,
Arguments = args,
FileName = isPs1 ? "powershell.exe" : file,
Arguments = isPs1
? $"-NoProfile -ExecutionPolicy Bypass -File \"{file}\" {args}".Trim()
: args,
WorkingDirectory = string.IsNullOrEmpty(workingDir) ? Environment.CurrentDirectory : workingDir,
UseShellExecute = false,
RedirectStandardOutput = true,

View File

@ -2,7 +2,6 @@ using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using UnityEditor;
using UnityEngine;
@ -70,21 +69,19 @@ namespace UnityMcpBridge.Editor.Helpers
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"AppData",
"Local",
"Programs",
RootFolder
);
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty, "AppData", "Local");
return Path.Combine(localAppData, "Programs", RootFolder);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"bin",
RootFolder
);
var xdg = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
if (string.IsNullOrEmpty(xdg))
{
xdg = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty,
".local", "share");
}
return Path.Combine(xdg, RootFolder);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
@ -273,12 +270,41 @@ namespace UnityMcpBridge.Editor.Helpers
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty;
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty;
string programData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) ?? string.Empty; // optional fallback
// Fast path: resolve from PATH first
try
{
var wherePsi = new System.Diagnostics.ProcessStartInfo
{
FileName = "where",
Arguments = "uv.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using var wp = System.Diagnostics.Process.Start(wherePsi);
string output = wp.StandardOutput.ReadToEnd().Trim();
wp.WaitForExit(1500);
if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output))
{
foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
{
string path = line.Trim();
if (File.Exists(path) && ValidateUvBinary(path)) return path;
}
}
}
catch { }
candidates = new[]
{
// Preferred: WinGet Links shims (stable entrypoints)
Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"),
Path.Combine(programFiles, "WinGet", "Links", "uv.exe"),
// Optional low-priority fallback for atypical images
Path.Combine(programData, "Microsoft", "WinGet", "Links", "uv.exe"),
// Common per-user installs
Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"),
@ -325,33 +351,10 @@ namespace UnityMcpBridge.Editor.Helpers
catch { /* ignore */ }
}
// Use platform-appropriate which/where to resolve from PATH
// Use platform-appropriate which/where to resolve from PATH (non-Windows handled here; Windows tried earlier)
try
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var wherePsi = new System.Diagnostics.ProcessStartInfo
{
FileName = "where",
Arguments = "uv.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using var wp = System.Diagnostics.Process.Start(wherePsi);
string output = wp.StandardOutput.ReadToEnd().Trim();
wp.WaitForExit(3000);
if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output))
{
foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
{
string path = line.Trim();
if (File.Exists(path) && ValidateUvBinary(path)) return path;
}
}
}
else
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var whichPsi = new System.Diagnostics.ProcessStartInfo
{

View File

@ -1064,6 +1064,14 @@ namespace UnityMcpBridge.Editor.Windows
// Merge without replacing the existing command
if (mcpClient?.mcpType == McpTypes.VSCode)
{
if (existingConfig.servers == null)
{
existingConfig.servers = new Newtonsoft.Json.Linq.JObject();
}
if (existingConfig.servers.unityMCP == null)
{
existingConfig.servers.unityMCP = new Newtonsoft.Json.Linq.JObject();
}
existingConfig.servers.unityMCP.args =
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
JsonConvert.SerializeObject(unityMCPConfig.args)
@ -1071,6 +1079,14 @@ namespace UnityMcpBridge.Editor.Windows
}
else
{
if (existingConfig.mcpServers == null)
{
existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject();
}
if (existingConfig.mcpServers.unityMCP == null)
{
existingConfig.mcpServers.unityMCP = new Newtonsoft.Json.Linq.JObject();
}
existingConfig.mcpServers.unityMCP.args =
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
JsonConvert.SerializeObject(unityMCPConfig.args)
@ -1617,7 +1633,8 @@ namespace UnityMcpBridge.Editor.Windows
UnityEngine.Debug.Log($"Successfully removed MCP server: {serverName}");
break;
}
else if (!stderr.Contains("No MCP server found"))
else if (!string.IsNullOrEmpty(stderr) &&
!stderr.Contains("No MCP server found", StringComparison.OrdinalIgnoreCase))
{
// If it's not a "not found" error, log it and stop trying
UnityEngine.Debug.LogWarning($"Error removing {serverName}: {stderr}");

View File

@ -1,6 +1,6 @@
{
"name": "com.coplaydev.unity-mcp",
"version": "2.0.2",
"version": "2.1.0",
"displayName": "Unity MCP Bridge",
"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.",
"unity": "2020.3",

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""
Generic helper to switch the Unity MCP package source in a Unity project's
Packages/manifest.json without embedding any personal paths.
Packages/manifest.json. This is useful for switching between upstream and local repos while working on the MCP.
Usage:
python mcp_source.py [--manifest /abs/path/to/manifest.json] [--repo /abs/path/to/unity-mcp] [--choice 1|2|3]