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
parent
5583327a03
commit
4e1b905ea0
|
|
@ -176,10 +176,16 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
stderr = string.Empty;
|
stderr = string.Empty;
|
||||||
try
|
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
|
var psi = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = file,
|
FileName = isPs1 ? "powershell.exe" : file,
|
||||||
Arguments = args,
|
Arguments = isPs1
|
||||||
|
? $"-NoProfile -ExecutionPolicy Bypass -File \"{file}\" {args}".Trim()
|
||||||
|
: args,
|
||||||
WorkingDirectory = string.IsNullOrEmpty(workingDir) ? Environment.CurrentDirectory : workingDir,
|
WorkingDirectory = string.IsNullOrEmpty(workingDir) ? Environment.CurrentDirectory : workingDir,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Reflection;
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
@ -70,21 +69,19 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
{
|
{
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
return Path.Combine(
|
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty, "AppData", "Local");
|
||||||
"AppData",
|
return Path.Combine(localAppData, "Programs", RootFolder);
|
||||||
"Local",
|
|
||||||
"Programs",
|
|
||||||
RootFolder
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
{
|
{
|
||||||
return Path.Combine(
|
var xdg = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
if (string.IsNullOrEmpty(xdg))
|
||||||
"bin",
|
{
|
||||||
RootFolder
|
xdg = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty,
|
||||||
);
|
".local", "share");
|
||||||
|
}
|
||||||
|
return Path.Combine(xdg, RootFolder);
|
||||||
}
|
}
|
||||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||||
{
|
{
|
||||||
|
|
@ -273,12 +270,41 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
|
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
|
||||||
string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty;
|
string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty;
|
||||||
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? 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[]
|
candidates = new[]
|
||||||
{
|
{
|
||||||
// Preferred: WinGet Links shims (stable entrypoints)
|
// Preferred: WinGet Links shims (stable entrypoints)
|
||||||
Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"),
|
Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"),
|
||||||
Path.Combine(programFiles, "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
|
// Common per-user installs
|
||||||
Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"),
|
Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"),
|
||||||
|
|
@ -325,33 +351,10 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
catch { /* ignore */ }
|
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
|
try
|
||||||
{
|
{
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
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
|
|
||||||
{
|
{
|
||||||
var whichPsi = new System.Diagnostics.ProcessStartInfo
|
var whichPsi = new System.Diagnostics.ProcessStartInfo
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1064,6 +1064,14 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
// Merge without replacing the existing command
|
// Merge without replacing the existing command
|
||||||
if (mcpClient?.mcpType == McpTypes.VSCode)
|
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 =
|
existingConfig.servers.unityMCP.args =
|
||||||
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
|
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
|
||||||
JsonConvert.SerializeObject(unityMCPConfig.args)
|
JsonConvert.SerializeObject(unityMCPConfig.args)
|
||||||
|
|
@ -1071,6 +1079,14 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
else
|
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 =
|
existingConfig.mcpServers.unityMCP.args =
|
||||||
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
|
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
|
||||||
JsonConvert.SerializeObject(unityMCPConfig.args)
|
JsonConvert.SerializeObject(unityMCPConfig.args)
|
||||||
|
|
@ -1617,7 +1633,8 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
UnityEngine.Debug.Log($"Successfully removed MCP server: {serverName}");
|
UnityEngine.Debug.Log($"Successfully removed MCP server: {serverName}");
|
||||||
break;
|
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
|
// If it's not a "not found" error, log it and stop trying
|
||||||
UnityEngine.Debug.LogWarning($"Error removing {serverName}: {stderr}");
|
UnityEngine.Debug.LogWarning($"Error removing {serverName}: {stderr}");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "com.coplaydev.unity-mcp",
|
"name": "com.coplaydev.unity-mcp",
|
||||||
"version": "2.0.2",
|
"version": "2.1.0",
|
||||||
"displayName": "Unity MCP Bridge",
|
"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.",
|
"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",
|
"unity": "2020.3",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Generic helper to switch the Unity MCP package source in a Unity project's
|
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:
|
Usage:
|
||||||
python mcp_source.py [--manifest /abs/path/to/manifest.json] [--repo /abs/path/to/unity-mcp] [--choice 1|2|3]
|
python mcp_source.py [--manifest /abs/path/to/manifest.json] [--repo /abs/path/to/unity-mcp] [--choice 1|2|3]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue