Improve Windows compatibility and code cleanup
- Enhanced Windows support for UV and Claude executable detection with OS-specific path handling - Added PowerShell integration for Windows command execution with proper PATH environment setup - Implemented comprehensive UV path scanning for various installation methods (Python, Chocolatey, Scoop, Cargo, etc.) - Added executable validation using IsValidUvInstallation() method - Improved Claude path detection with fallback to PowerShell's Get-Command - Enhanced configuration path handling with Windows-specific paths and cross-platform normalization - Cleaned up exception handling by removing unused exception variables - Fixed method signature in VSCodeManualSetupWindow 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>main
parent
0ced4d7bea
commit
94bbc9873c
|
|
@ -360,9 +360,9 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
Type propType = propInfo.PropertyType;
|
Type propType = propInfo.PropertyType;
|
||||||
AddSerializableValue(serializablePropertiesOutput, propName, propType, value);
|
AddSerializableValue(serializablePropertiesOutput, propName, propType, value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// Debug.LogWarning($"Could not read property {propName} on {componentType.Name}: {ex.Message}");
|
// Debug.LogWarning($"Could not read property {propName} on {componentType.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,9 +383,9 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
Type fieldType = fieldInfo.FieldType;
|
Type fieldType = fieldInfo.FieldType;
|
||||||
AddSerializableValue(serializablePropertiesOutput, fieldName, fieldType, value);
|
AddSerializableValue(serializablePropertiesOutput, fieldName, fieldType, value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// Debug.LogWarning($"Could not read field {fieldInfo.Name} on {componentType.Name}: {ex.Message}");
|
// Debug.LogWarning($"Could not read field {fieldInfo.Name} on {componentType.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// --- End Use cached metadata ---
|
// --- End Use cached metadata ---
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -941,7 +942,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find uv.exe in common locations
|
// Try to find uv.exe in common locations
|
||||||
string uvPath = FindWindowsUvPath();
|
string uvPath = FindUvPath();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(uvPath))
|
if (string.IsNullOrEmpty(uvPath))
|
||||||
{
|
{
|
||||||
|
|
@ -966,21 +967,49 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
string unityProjectDir = Application.dataPath;
|
string unityProjectDir = Application.dataPath;
|
||||||
string projectDir = Path.GetDirectoryName(unityProjectDir);
|
string projectDir = Path.GetDirectoryName(unityProjectDir);
|
||||||
|
|
||||||
var psi = new ProcessStartInfo
|
var psi = new ProcessStartInfo();
|
||||||
{
|
|
||||||
FileName = command,
|
|
||||||
Arguments = args,
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
WorkingDirectory = projectDir // Set working directory to Unity project directory
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set PATH to include common binary locations
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
// On Windows, run through PowerShell with explicit PATH setting
|
||||||
|
psi.FileName = "powershell.exe";
|
||||||
|
string nodePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "nodejs");
|
||||||
|
psi.Arguments = $"-Command \"$env:PATH += ';{nodePath}'; & '{command}' {args}\"";
|
||||||
|
UnityEngine.Debug.Log($"Executing: powershell.exe {psi.Arguments}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psi.FileName = command;
|
||||||
|
psi.Arguments = args;
|
||||||
|
UnityEngine.Debug.Log($"Executing: {command} {args}");
|
||||||
|
}
|
||||||
|
|
||||||
|
psi.UseShellExecute = false;
|
||||||
|
psi.RedirectStandardOutput = true;
|
||||||
|
psi.RedirectStandardError = true;
|
||||||
|
psi.CreateNoWindow = true;
|
||||||
|
psi.WorkingDirectory = projectDir;
|
||||||
|
|
||||||
|
// Set PATH to include common binary locations (OS-specific)
|
||||||
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
|
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
// Windows: Add common Node.js and npm locations
|
||||||
|
string[] windowsPaths = {
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "nodejs"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "nodejs"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "npm")
|
||||||
|
};
|
||||||
|
string additionalPaths = string.Join(";", windowsPaths);
|
||||||
|
psi.EnvironmentVariables["PATH"] = $"{currentPath};{additionalPaths}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// macOS/Linux: Add common binary locations
|
||||||
string additionalPaths = "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin";
|
string additionalPaths = "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin";
|
||||||
psi.EnvironmentVariables["PATH"] = $"{additionalPaths}:{currentPath}";
|
psi.EnvironmentVariables["PATH"] = $"{additionalPaths}:{currentPath}";
|
||||||
|
}
|
||||||
|
|
||||||
using var process = Process.Start(psi);
|
using var process = Process.Start(psi);
|
||||||
string output = process.StandardOutput.ReadToEnd();
|
string output = process.StandardOutput.ReadToEnd();
|
||||||
|
|
@ -996,7 +1025,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
|
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
|
||||||
if (claudeClient != null)
|
if (claudeClient != null)
|
||||||
{
|
{
|
||||||
CheckMcpConfiguration(claudeClient);
|
CheckClaudeCodeConfiguration(claudeClient);
|
||||||
}
|
}
|
||||||
Repaint();
|
Repaint();
|
||||||
UnityEngine.Debug.Log("UnityMCP server successfully registered from Claude Code.");
|
UnityEngine.Debug.Log("UnityMCP server successfully registered from Claude Code.");
|
||||||
|
|
@ -1040,21 +1069,47 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
string unityProjectDir = Application.dataPath;
|
string unityProjectDir = Application.dataPath;
|
||||||
string projectDir = Path.GetDirectoryName(unityProjectDir);
|
string projectDir = Path.GetDirectoryName(unityProjectDir);
|
||||||
|
|
||||||
var psi = new ProcessStartInfo
|
var psi = new ProcessStartInfo();
|
||||||
{
|
|
||||||
FileName = command,
|
|
||||||
Arguments = "mcp remove UnityMCP",
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
WorkingDirectory = projectDir // Set working directory to Unity project directory
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set PATH to include common binary locations
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
// On Windows, run through PowerShell with explicit PATH setting
|
||||||
|
psi.FileName = "powershell.exe";
|
||||||
|
string nodePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "nodejs");
|
||||||
|
psi.Arguments = $"-Command \"$env:PATH += ';{nodePath}'; & '{command}' mcp remove UnityMCP\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psi.FileName = command;
|
||||||
|
psi.Arguments = "mcp remove UnityMCP";
|
||||||
|
}
|
||||||
|
|
||||||
|
psi.UseShellExecute = false;
|
||||||
|
psi.RedirectStandardOutput = true;
|
||||||
|
psi.RedirectStandardError = true;
|
||||||
|
psi.CreateNoWindow = true;
|
||||||
|
psi.WorkingDirectory = projectDir;
|
||||||
|
|
||||||
|
// Set PATH to include common binary locations (OS-specific)
|
||||||
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
|
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
// Windows: Add common Node.js and npm locations
|
||||||
|
string[] windowsPaths = {
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "nodejs"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "nodejs"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "npm")
|
||||||
|
};
|
||||||
|
string additionalPaths = string.Join(";", windowsPaths);
|
||||||
|
psi.EnvironmentVariables["PATH"] = $"{currentPath};{additionalPaths}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// macOS/Linux: Add common binary locations
|
||||||
string additionalPaths = "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin";
|
string additionalPaths = "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin";
|
||||||
psi.EnvironmentVariables["PATH"] = $"{additionalPaths}:{currentPath}";
|
psi.EnvironmentVariables["PATH"] = $"{additionalPaths}:{currentPath}";
|
||||||
|
}
|
||||||
|
|
||||||
using var process = Process.Start(psi);
|
using var process = Process.Start(psi);
|
||||||
string output = process.StandardOutput.ReadToEnd();
|
string output = process.StandardOutput.ReadToEnd();
|
||||||
|
|
@ -1068,7 +1123,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
|
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
|
||||||
if (claudeClient != null)
|
if (claudeClient != null)
|
||||||
{
|
{
|
||||||
CheckMcpConfiguration(claudeClient);
|
CheckClaudeCodeConfiguration(claudeClient);
|
||||||
}
|
}
|
||||||
Repaint();
|
Repaint();
|
||||||
|
|
||||||
|
|
@ -1105,7 +1160,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
|
|
||||||
foreach (string path in possiblePaths)
|
foreach (string path in possiblePaths)
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (File.Exists(path) && IsValidUvInstallation(path))
|
||||||
{
|
{
|
||||||
uvPath = path;
|
uvPath = path;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1130,7 +1185,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
string output = process.StandardOutput.ReadToEnd().Trim();
|
string output = process.StandardOutput.ReadToEnd().Trim();
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(output) && File.Exists(output))
|
if (!string.IsNullOrEmpty(output) && File.Exists(output) && IsValidUvInstallation(output))
|
||||||
{
|
{
|
||||||
uvPath = output;
|
uvPath = output;
|
||||||
}
|
}
|
||||||
|
|
@ -1142,6 +1197,17 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no specific path found, fall back to using 'uv' from PATH
|
||||||
|
if (uvPath == null)
|
||||||
|
{
|
||||||
|
// Test if 'uv' is available in PATH by trying to run it
|
||||||
|
string uvCommand = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "uv.exe" : "uv";
|
||||||
|
if (IsValidUvInstallation(uvCommand))
|
||||||
|
{
|
||||||
|
uvPath = uvCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (uvPath == null)
|
if (uvPath == null)
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogError("UV package manager not found! Please install UV first:\n" +
|
UnityEngine.Debug.LogError("UV package manager not found! Please install UV first:\n" +
|
||||||
|
|
@ -1154,42 +1220,201 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
return uvPath;
|
return uvPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsValidUvInstallation(string uvPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = uvPath,
|
||||||
|
Arguments = "--version",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using var process = Process.Start(psi);
|
||||||
|
process.WaitForExit(5000); // 5 second timeout
|
||||||
|
|
||||||
|
if (process.ExitCode == 0)
|
||||||
|
{
|
||||||
|
string output = process.StandardOutput.ReadToEnd().Trim();
|
||||||
|
// Basic validation - just check if it responds with version info
|
||||||
|
// UV typically outputs "uv 0.x.x" format
|
||||||
|
if (output.StartsWith("uv ") && output.Contains("."))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string FindWindowsUvPath()
|
private string FindWindowsUvPath()
|
||||||
{
|
{
|
||||||
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
string userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||||
|
|
||||||
// Check for different Python versions
|
// Dynamic Python version detection - check what's actually installed
|
||||||
string[] pythonVersions = { "Python313", "Python312", "Python311", "Python310", "Python39", "Python38" };
|
List<string> pythonVersions = new List<string>();
|
||||||
|
|
||||||
foreach (string version in pythonVersions)
|
// Add common versions but also scan for any Python* directories
|
||||||
{
|
string[] commonVersions = { "Python313", "Python312", "Python311", "Python310", "Python39", "Python38", "Python37" };
|
||||||
string uvPath = Path.Combine(appData, version, "Scripts", "uv.exe");
|
pythonVersions.AddRange(commonVersions);
|
||||||
if (File.Exists(uvPath))
|
|
||||||
{
|
|
||||||
return uvPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Program Files locations
|
// Scan for additional Python installations
|
||||||
string[] programFilesPaths = {
|
string[] pythonBasePaths = {
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Python"),
|
Path.Combine(appData, "Python"),
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Python"),
|
Path.Combine(localAppData, "Programs", "Python"),
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", "Python")
|
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\Python",
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + "\\Python"
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (string basePath in programFilesPaths)
|
foreach (string basePath in pythonBasePaths)
|
||||||
{
|
{
|
||||||
if (Directory.Exists(basePath))
|
if (Directory.Exists(basePath))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
foreach (string dir in Directory.GetDirectories(basePath, "Python*"))
|
foreach (string dir in Directory.GetDirectories(basePath, "Python*"))
|
||||||
{
|
{
|
||||||
string uvPath = Path.Combine(dir, "Scripts", "uv.exe");
|
string versionName = Path.GetFileName(dir);
|
||||||
if (File.Exists(uvPath))
|
if (!pythonVersions.Contains(versionName))
|
||||||
|
{
|
||||||
|
pythonVersions.Add(versionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore directory access errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Python installations for UV
|
||||||
|
foreach (string version in pythonVersions)
|
||||||
|
{
|
||||||
|
string[] pythonPaths = {
|
||||||
|
Path.Combine(appData, "Python", version, "Scripts", "uv.exe"),
|
||||||
|
Path.Combine(localAppData, "Programs", "Python", version, "Scripts", "uv.exe"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Python", version, "Scripts", "uv.exe"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Python", version, "Scripts", "uv.exe")
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (string uvPath in pythonPaths)
|
||||||
|
{
|
||||||
|
if (File.Exists(uvPath) && IsValidUvInstallation(uvPath))
|
||||||
{
|
{
|
||||||
return uvPath;
|
return uvPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check package manager installations
|
||||||
|
string[] packageManagerPaths = {
|
||||||
|
// Chocolatey
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "chocolatey", "lib", "uv", "tools", "uv.exe"),
|
||||||
|
Path.Combine("C:", "ProgramData", "chocolatey", "lib", "uv", "tools", "uv.exe"),
|
||||||
|
|
||||||
|
// Scoop
|
||||||
|
Path.Combine(userProfile, "scoop", "apps", "uv", "current", "uv.exe"),
|
||||||
|
Path.Combine(userProfile, "scoop", "shims", "uv.exe"),
|
||||||
|
|
||||||
|
// Winget/msstore
|
||||||
|
Path.Combine(localAppData, "Microsoft", "WinGet", "Packages", "astral-sh.uv_Microsoft.Winget.Source_8wekyb3d8bbwe", "uv.exe"),
|
||||||
|
|
||||||
|
// Common standalone installations
|
||||||
|
Path.Combine(localAppData, "uv", "uv.exe"),
|
||||||
|
Path.Combine(appData, "uv", "uv.exe"),
|
||||||
|
Path.Combine(userProfile, ".local", "bin", "uv.exe"),
|
||||||
|
Path.Combine(userProfile, "bin", "uv.exe"),
|
||||||
|
|
||||||
|
// Cargo/Rust installations
|
||||||
|
Path.Combine(userProfile, ".cargo", "bin", "uv.exe"),
|
||||||
|
|
||||||
|
// Manual installations in common locations
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "uv", "uv.exe"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "uv", "uv.exe")
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (string uvPath in packageManagerPaths)
|
||||||
|
{
|
||||||
|
if (File.Exists(uvPath) && IsValidUvInstallation(uvPath))
|
||||||
|
{
|
||||||
|
return uvPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find uv via where command (Windows equivalent of which)
|
||||||
|
// Use where.exe explicitly to avoid PowerShell alias conflicts
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "where.exe",
|
||||||
|
Arguments = "uv",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using var process = Process.Start(psi);
|
||||||
|
string output = process.StandardOutput.ReadToEnd().Trim();
|
||||||
|
process.WaitForExit();
|
||||||
|
|
||||||
|
if (process.ExitCode == 0 && !string.IsNullOrEmpty(output))
|
||||||
|
{
|
||||||
|
string[] lines = output.Split('\n');
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
string cleanPath = line.Trim();
|
||||||
|
if (File.Exists(cleanPath) && IsValidUvInstallation(cleanPath))
|
||||||
|
{
|
||||||
|
return cleanPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// If where.exe fails, try PowerShell's Get-Command as fallback
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "powershell.exe",
|
||||||
|
Arguments = "-Command \"(Get-Command uv -ErrorAction SilentlyContinue).Source\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using var process = Process.Start(psi);
|
||||||
|
string output = process.StandardOutput.ReadToEnd().Trim();
|
||||||
|
process.WaitForExit();
|
||||||
|
|
||||||
|
if (process.ExitCode == 0 && !string.IsNullOrEmpty(output) && File.Exists(output))
|
||||||
|
{
|
||||||
|
if (IsValidUvInstallation(output))
|
||||||
|
{
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore PowerShell errors too
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null; // Will fallback to using 'uv' from PATH
|
return null; // Will fallback to using 'uv' from PATH
|
||||||
|
|
@ -1215,15 +1440,16 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find via where command
|
// Try to find via where command (PowerShell compatible)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var psi = new ProcessStartInfo
|
var psi = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "where",
|
FileName = "where.exe",
|
||||||
Arguments = "claude",
|
Arguments = "claude",
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
CreateNoWindow = true
|
CreateNoWindow = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1231,7 +1457,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
string output = process.StandardOutput.ReadToEnd().Trim();
|
string output = process.StandardOutput.ReadToEnd().Trim();
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(output))
|
if (process.ExitCode == 0 && !string.IsNullOrEmpty(output))
|
||||||
{
|
{
|
||||||
string[] lines = output.Split('\n');
|
string[] lines = output.Split('\n');
|
||||||
foreach (string line in lines)
|
foreach (string line in lines)
|
||||||
|
|
@ -1246,7 +1472,32 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// Ignore errors and fall back
|
// If where.exe fails, try PowerShell's Get-Command as fallback
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "powershell.exe",
|
||||||
|
Arguments = "-Command \"(Get-Command claude -ErrorAction SilentlyContinue).Source\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using var process = Process.Start(psi);
|
||||||
|
string output = process.StandardOutput.ReadToEnd().Trim();
|
||||||
|
process.WaitForExit();
|
||||||
|
|
||||||
|
if (process.ExitCode == 0 && !string.IsNullOrEmpty(output) && File.Exists(output))
|
||||||
|
{
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore PowerShell errors too
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "claude"; // Final fallback to PATH
|
return "claude"; // Final fallback to PATH
|
||||||
|
|
@ -1266,9 +1517,15 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
string projectDir = Path.GetDirectoryName(unityProjectDir);
|
string projectDir = Path.GetDirectoryName(unityProjectDir);
|
||||||
|
|
||||||
// Read the global Claude config file
|
// Read the global Claude config file
|
||||||
string configPath = mcpClient.linuxConfigPath; // ~/.claude.json
|
string configPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? mcpClient.windowsConfigPath
|
||||||
|
: mcpClient.linuxConfigPath;
|
||||||
|
|
||||||
|
UnityEngine.Debug.Log($"Checking Claude config at: {configPath}");
|
||||||
|
|
||||||
if (!File.Exists(configPath))
|
if (!File.Exists(configPath))
|
||||||
{
|
{
|
||||||
|
UnityEngine.Debug.LogWarning($"Claude config file not found at: {configPath}");
|
||||||
mcpClient.SetStatus(McpStatus.NotConfigured);
|
mcpClient.SetStatus(McpStatus.NotConfigured);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1295,7 +1552,12 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
foreach (var project in claudeConfig.projects)
|
foreach (var project in claudeConfig.projects)
|
||||||
{
|
{
|
||||||
string projectPath = project.Name;
|
string projectPath = project.Name;
|
||||||
if (projectPath == projectDir && project.Value?.mcpServers != null)
|
|
||||||
|
// Normalize paths for comparison (handle forward/back slash differences)
|
||||||
|
string normalizedProjectPath = Path.GetFullPath(projectPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
string normalizedProjectDir = Path.GetFullPath(projectDir).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
|
||||||
|
if (string.Equals(normalizedProjectPath, normalizedProjectDir, StringComparison.OrdinalIgnoreCase) && project.Value?.mcpServers != null)
|
||||||
{
|
{
|
||||||
// Check for UnityMCP (case variations)
|
// Check for UnityMCP (case variations)
|
||||||
var servers = project.Value.mcpServers;
|
var servers = project.Value.mcpServers;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
{
|
{
|
||||||
public class VSCodeManualSetupWindow : ManualConfigEditorWindow
|
public class VSCodeManualSetupWindow : ManualConfigEditorWindow
|
||||||
{
|
{
|
||||||
public static new void ShowWindow(string configPath, string configJson)
|
public static void ShowWindow(string configPath, string configJson)
|
||||||
{
|
{
|
||||||
var window = GetWindow<VSCodeManualSetupWindow>("VSCode GitHub Copilot Setup");
|
var window = GetWindow<VSCodeManualSetupWindow>("VSCode GitHub Copilot Setup");
|
||||||
window.configPath = configPath;
|
window.configPath = configPath;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue