Skip to content

Commit ce8ab83

Browse files
authored
Merge pull request #208 from dsarno/feature/claude-cli-detection-ui
UX and Fix: Claude Code detection + UV gating (Cursor/Windsurf) + VSCode mcp.json schema
2 parents 86198a0 + b09a86f commit ce8ab83

File tree

5 files changed

+291
-71
lines changed

5 files changed

+291
-71
lines changed

UnityMcpBridge/Editor/Data/McpClients.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,15 @@ public class McpClients
8787
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
8888
"Code",
8989
"User",
90-
"settings.json"
90+
"mcp.json"
9191
),
9292
linuxConfigPath = Path.Combine(
9393
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
9494
"Library",
9595
"Application Support",
9696
"Code",
9797
"User",
98-
"settings.json"
98+
"mcp.json"
9999
),
100100
mcpType = McpTypes.VSCode,
101101
configStatus = "Not Configured",

UnityMcpBridge/Editor/Helpers/ExecPath.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ internal static string ResolveClaude()
3535
Path.Combine(home, ".local", "bin", "claude"),
3636
};
3737
foreach (string c in candidates) { if (File.Exists(c)) return c; }
38+
// Try NVM-installed claude under ~/.nvm/versions/node/*/bin/claude
39+
string nvmClaude = ResolveClaudeFromNvm(home);
40+
if (!string.IsNullOrEmpty(nvmClaude)) return nvmClaude;
3841
#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
3942
return Which("claude", "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin");
4043
#else
@@ -70,6 +73,9 @@ internal static string ResolveClaude()
7073
Path.Combine(home, ".local", "bin", "claude"),
7174
};
7275
foreach (string c in candidates) { if (File.Exists(c)) return c; }
76+
// Try NVM-installed claude under ~/.nvm/versions/node/*/bin/claude
77+
string nvmClaude = ResolveClaudeFromNvm(home);
78+
if (!string.IsNullOrEmpty(nvmClaude)) return nvmClaude;
7379
#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
7480
return Which("claude", "/usr/local/bin:/usr/bin:/bin");
7581
#else
@@ -78,6 +84,75 @@ internal static string ResolveClaude()
7884
}
7985
}
8086

87+
// Attempt to resolve claude from NVM-managed Node installations, choosing the newest version
88+
private static string ResolveClaudeFromNvm(string home)
89+
{
90+
try
91+
{
92+
if (string.IsNullOrEmpty(home)) return null;
93+
string nvmNodeDir = Path.Combine(home, ".nvm", "versions", "node");
94+
if (!Directory.Exists(nvmNodeDir)) return null;
95+
96+
string bestPath = null;
97+
Version bestVersion = null;
98+
foreach (string versionDir in Directory.EnumerateDirectories(nvmNodeDir))
99+
{
100+
string name = Path.GetFileName(versionDir);
101+
if (string.IsNullOrEmpty(name)) continue;
102+
if (name.StartsWith("v", StringComparison.OrdinalIgnoreCase))
103+
{
104+
// Extract numeric portion: e.g., v18.19.0-nightly -> 18.19.0
105+
string versionStr = name.Substring(1);
106+
int dashIndex = versionStr.IndexOf('-');
107+
if (dashIndex > 0)
108+
{
109+
versionStr = versionStr.Substring(0, dashIndex);
110+
}
111+
if (Version.TryParse(versionStr, out Version parsed))
112+
{
113+
string candidate = Path.Combine(versionDir, "bin", "claude");
114+
if (File.Exists(candidate))
115+
{
116+
if (bestVersion == null || parsed > bestVersion)
117+
{
118+
bestVersion = parsed;
119+
bestPath = candidate;
120+
}
121+
}
122+
}
123+
}
124+
}
125+
return bestPath;
126+
}
127+
catch { return null; }
128+
}
129+
130+
// Explicitly set the Claude CLI absolute path override in EditorPrefs
131+
internal static void SetClaudeCliPath(string absolutePath)
132+
{
133+
try
134+
{
135+
if (!string.IsNullOrEmpty(absolutePath) && File.Exists(absolutePath))
136+
{
137+
EditorPrefs.SetString(PrefClaude, absolutePath);
138+
}
139+
}
140+
catch { }
141+
}
142+
143+
// Clear any previously set Claude CLI override path
144+
internal static void ClearClaudeCliPath()
145+
{
146+
try
147+
{
148+
if (EditorPrefs.HasKey(PrefClaude))
149+
{
150+
EditorPrefs.DeleteKey(PrefClaude);
151+
}
152+
}
153+
catch { }
154+
}
155+
81156
// Use existing UV resolver; returns absolute path or null.
82157
internal static string ResolveUv()
83158
{

UnityMcpBridge/Editor/Models/MCPConfigServer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,9 @@ public class McpConfigServer
1111

1212
[JsonProperty("args")]
1313
public string[] args;
14+
15+
// VSCode expects a transport type; include only when explicitly set
16+
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
17+
public string type;
1418
}
1519
}

0 commit comments

Comments
 (0)