Skip to content

Commit b6b8d47

Browse files
committed
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
1 parent a2a14c1 commit b6b8d47

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

UnityMcpBridge/Editor/Helpers/ExecPath.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,15 @@ internal static string ResolveClaude()
5353
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
5454
string[] candidates =
5555
{
56+
// Prefer .cmd (most reliable from non-interactive processes)
5657
Path.Combine(appData, "npm", "claude.cmd"),
5758
Path.Combine(localAppData, "npm", "claude.cmd"),
59+
// Fall back to PowerShell shim if only .ps1 is present
60+
Path.Combine(appData, "npm", "claude.ps1"),
61+
Path.Combine(localAppData, "npm", "claude.ps1"),
5862
};
5963
foreach (string c in candidates) { if (File.Exists(c)) return c; }
60-
string fromWhere = Where("claude.exe") ?? Where("claude.cmd") ?? Where("claude");
64+
string fromWhere = Where("claude.exe") ?? Where("claude.cmd") ?? Where("claude.ps1") ?? Where("claude");
6165
if (!string.IsNullOrEmpty(fromWhere)) return fromWhere;
6266
#endif
6367
return null;

UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,9 +1578,54 @@ private void UnregisterWithClaudeCode()
15781578
string projectDir = Path.GetDirectoryName(Application.dataPath);
15791579
string pathPrepend = Application.platform == RuntimePlatform.OSXEditor
15801580
? "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
1581-
: "/usr/local/bin:/usr/bin:/bin";
1581+
: null; // On Windows, don't modify PATH - use system PATH as-is
15821582

1583-
if (ExecPath.TryRun(claudePath, "mcp remove UnityMCP", projectDir, out var stdout, out var stderr, 10000, pathPrepend))
1583+
// Determine if Claude has a UnityMCP server registered by using exit codes from `claude mcp get <name>`
1584+
string[] candidateNamesForGet = { "UnityMCP", "unityMCP", "unity-mcp", "UnityMcpServer" };
1585+
List<string> existingNames = new List<string>();
1586+
foreach (var candidate in candidateNamesForGet)
1587+
{
1588+
if (ExecPath.TryRun(claudePath, $"mcp get {candidate}", projectDir, out var getStdout, out var getStderr, 7000, pathPrepend))
1589+
{
1590+
// Success exit code indicates the server exists
1591+
existingNames.Add(candidate);
1592+
}
1593+
}
1594+
1595+
if (existingNames.Count == 0)
1596+
{
1597+
// Nothing to unregister – set status and bail early
1598+
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
1599+
if (claudeClient != null)
1600+
{
1601+
claudeClient.SetStatus(McpStatus.NotConfigured);
1602+
UnityEngine.Debug.Log("Claude CLI reports no UnityMCP server via 'mcp get' – setting status to NotConfigured and aborting unregister.");
1603+
Repaint();
1604+
}
1605+
return;
1606+
}
1607+
1608+
// Try different possible server names
1609+
string[] possibleNames = { "UnityMCP", "unityMCP", "unity-mcp", "UnityMcpServer" };
1610+
bool success = false;
1611+
1612+
foreach (string serverName in possibleNames)
1613+
{
1614+
if (ExecPath.TryRun(claudePath, $"mcp remove {serverName}", projectDir, out var stdout, out var stderr, 10000, pathPrepend))
1615+
{
1616+
success = true;
1617+
UnityEngine.Debug.Log($"Successfully removed MCP server: {serverName}");
1618+
break;
1619+
}
1620+
else if (!stderr.Contains("No MCP server found"))
1621+
{
1622+
// If it's not a "not found" error, log it and stop trying
1623+
UnityEngine.Debug.LogWarning($"Error removing {serverName}: {stderr}");
1624+
break;
1625+
}
1626+
}
1627+
1628+
if (success)
15841629
{
15851630
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
15861631
if (claudeClient != null)
@@ -1594,16 +1639,45 @@ private void UnregisterWithClaudeCode()
15941639
}
15951640
else
15961641
{
1597-
UnityEngine.Debug.LogWarning($"Claude MCP removal failed: {stderr}\n{stdout}");
1642+
// If no servers were found to remove, they're already unregistered
1643+
// Force status to NotConfigured and update the UI
1644+
UnityEngine.Debug.Log("No MCP servers found to unregister - already unregistered.");
15981645
var claudeClient = mcpClients.clients.FirstOrDefault(c => c.mcpType == McpTypes.ClaudeCode);
15991646
if (claudeClient != null)
16001647
{
1648+
claudeClient.SetStatus(McpStatus.NotConfigured);
16011649
CheckClaudeCodeConfiguration(claudeClient);
16021650
}
16031651
Repaint();
16041652
}
16051653
}
16061654

1655+
private bool ParseTextOutput(string claudePath, string projectDir, string pathPrepend)
1656+
{
1657+
if (ExecPath.TryRun(claudePath, "mcp list", projectDir, out var listStdout, out var listStderr, 10000, pathPrepend))
1658+
{
1659+
UnityEngine.Debug.Log($"Claude MCP servers (text): {listStdout}");
1660+
1661+
// Check if output indicates no servers or contains UnityMCP variants
1662+
if (listStdout.Contains("No MCP servers configured") ||
1663+
listStdout.Contains("no servers") ||
1664+
listStdout.Contains("No servers") ||
1665+
string.IsNullOrWhiteSpace(listStdout) ||
1666+
listStdout.Trim().Length == 0)
1667+
{
1668+
return false;
1669+
}
1670+
1671+
// Look for UnityMCP variants in the output
1672+
return listStdout.Contains("UnityMCP") ||
1673+
listStdout.Contains("unityMCP") ||
1674+
listStdout.Contains("unity-mcp");
1675+
}
1676+
1677+
// If command failed, assume no servers
1678+
return false;
1679+
}
1680+
16071681
private string FindUvPath()
16081682
{
16091683
string uvPath = null;

0 commit comments

Comments
 (0)