Windows: robust Claude CLI resolution (prefer .cmd, fallback .ps1, where.exe); Unregister UX: use 'claude mcp get' exit codes; stop PATH prepend on Windows; safer detection when unregistered
parent
a2a14c179c
commit
b6b8d47dfe
|
|
@ -53,11 +53,15 @@ namespace UnityMcpBridge.Editor.Helpers
|
||||||
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
|
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
|
||||||
string[] candidates =
|
string[] candidates =
|
||||||
{
|
{
|
||||||
|
// Prefer .cmd (most reliable from non-interactive processes)
|
||||||
Path.Combine(appData, "npm", "claude.cmd"),
|
Path.Combine(appData, "npm", "claude.cmd"),
|
||||||
Path.Combine(localAppData, "npm", "claude.cmd"),
|
Path.Combine(localAppData, "npm", "claude.cmd"),
|
||||||
|
// Fall back to PowerShell shim if only .ps1 is present
|
||||||
|
Path.Combine(appData, "npm", "claude.ps1"),
|
||||||
|
Path.Combine(localAppData, "npm", "claude.ps1"),
|
||||||
};
|
};
|
||||||
foreach (string c in candidates) { if (File.Exists(c)) return c; }
|
foreach (string c in candidates) { if (File.Exists(c)) return c; }
|
||||||
string fromWhere = Where("claude.exe") ?? Where("claude.cmd") ?? Where("claude");
|
string fromWhere = Where("claude.exe") ?? Where("claude.cmd") ?? Where("claude.ps1") ?? Where("claude");
|
||||||
if (!string.IsNullOrEmpty(fromWhere)) return fromWhere;
|
if (!string.IsNullOrEmpty(fromWhere)) return fromWhere;
|
||||||
#endif
|
#endif
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -1578,9 +1578,54 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
string projectDir = Path.GetDirectoryName(Application.dataPath);
|
string projectDir = Path.GetDirectoryName(Application.dataPath);
|
||||||
string pathPrepend = Application.platform == RuntimePlatform.OSXEditor
|
string pathPrepend = Application.platform == RuntimePlatform.OSXEditor
|
||||||
? "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
|
? "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
|
||||||
: "/usr/local/bin:/usr/bin:/bin";
|
: null; // On Windows, don't modify PATH - use system PATH as-is
|
||||||
|
|
||||||
if (ExecPath.TryRun(claudePath, "mcp remove UnityMCP", projectDir, out var stdout, out var stderr, 10000, pathPrepend))
|
// Determine if Claude has a UnityMCP server registered by using exit codes from `claude mcp get <name>`
|
||||||
|
string[] candidateNamesForGet = { "UnityMCP", "unityMCP", "unity-mcp", "UnityMcpServer" };
|
||||||
|
List<string> existingNames = new List<string>();
|
||||||
|
foreach (var candidate in candidateNamesForGet)
|
||||||
|
{
|
||||||
|
if (ExecPath.TryRun(claudePath, $"mcp get {candidate}", projectDir, out var getStdout, out var getStderr, 7000, pathPrepend))
|
||||||
|
{
|
||||||
|
// Success exit code indicates the server exists
|
||||||
|
existingNames.Add(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingNames.Count == 0)
|
||||||
|
{
|
||||||
|
// Nothing to unregister – set status and bail early
|
||||||
|
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
|
||||||
|
if (claudeClient != null)
|
||||||
|
{
|
||||||
|
claudeClient.SetStatus(McpStatus.NotConfigured);
|
||||||
|
UnityEngine.Debug.Log("Claude CLI reports no UnityMCP server via 'mcp get' – setting status to NotConfigured and aborting unregister.");
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try different possible server names
|
||||||
|
string[] possibleNames = { "UnityMCP", "unityMCP", "unity-mcp", "UnityMcpServer" };
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
foreach (string serverName in possibleNames)
|
||||||
|
{
|
||||||
|
if (ExecPath.TryRun(claudePath, $"mcp remove {serverName}", projectDir, out var stdout, out var stderr, 10000, pathPrepend))
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
UnityEngine.Debug.Log($"Successfully removed MCP server: {serverName}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!stderr.Contains("No MCP server found"))
|
||||||
|
{
|
||||||
|
// If it's not a "not found" error, log it and stop trying
|
||||||
|
UnityEngine.Debug.LogWarning($"Error removing {serverName}: {stderr}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
@ -1594,16 +1639,45 @@ namespace UnityMcpBridge.Editor.Windows
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogWarning($"Claude MCP removal failed: {stderr}\n{stdout}");
|
// If no servers were found to remove, they're already unregistered
|
||||||
|
// Force status to NotConfigured and update the UI
|
||||||
|
UnityEngine.Debug.Log("No MCP servers found to unregister - already unregistered.");
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
claudeClient.SetStatus(McpStatus.NotConfigured);
|
||||||
CheckClaudeCodeConfiguration(claudeClient);
|
CheckClaudeCodeConfiguration(claudeClient);
|
||||||
}
|
}
|
||||||
Repaint();
|
Repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ParseTextOutput(string claudePath, string projectDir, string pathPrepend)
|
||||||
|
{
|
||||||
|
if (ExecPath.TryRun(claudePath, "mcp list", projectDir, out var listStdout, out var listStderr, 10000, pathPrepend))
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log($"Claude MCP servers (text): {listStdout}");
|
||||||
|
|
||||||
|
// Check if output indicates no servers or contains UnityMCP variants
|
||||||
|
if (listStdout.Contains("No MCP servers configured") ||
|
||||||
|
listStdout.Contains("no servers") ||
|
||||||
|
listStdout.Contains("No servers") ||
|
||||||
|
string.IsNullOrWhiteSpace(listStdout) ||
|
||||||
|
listStdout.Trim().Length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for UnityMCP variants in the output
|
||||||
|
return listStdout.Contains("UnityMCP") ||
|
||||||
|
listStdout.Contains("unityMCP") ||
|
||||||
|
listStdout.Contains("unity-mcp");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If command failed, assume no servers
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private string FindUvPath()
|
private string FindUvPath()
|
||||||
{
|
{
|
||||||
string uvPath = null;
|
string uvPath = null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue