Skip to content

Commit f21c2ce

Browse files
committed
fix(installer): skip legacy deletion when still referenced in prefs or Cursor config
1 parent ee23346 commit f21c2ce

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

UnityMcpBridge/Editor/Helpers/ServerInstaller.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ public static void EnsureServerInstalled()
6767
|| (!string.IsNullOrEmpty(embeddedVer) && CompareSemverSafe(legacyVer, embeddedVer) < 0);
6868
if (legacyOlder)
6969
{
70+
// Skip deletion if this path is still referenced by prefs or known client configs
71+
if (IsPathPossiblyReferencedByPrefsOrKnownConfigs(legacySrc))
72+
{
73+
McpLog.Info($"Skipping removal of legacy server at '{legacyRoot}' (still referenced).", always: false);
74+
continue;
75+
}
7076
TryKillUvForPath(legacySrc);
7177
try
7278
{
@@ -258,6 +264,85 @@ private static bool PathsEqualSafe(string a, string b)
258264
catch { return false; }
259265
}
260266

267+
private static bool IsPathPossiblyReferencedByPrefsOrKnownConfigs(string serverSrcPath)
268+
{
269+
try
270+
{
271+
if (string.IsNullOrEmpty(serverSrcPath)) return false;
272+
273+
// EditorPrefs overrides
274+
try
275+
{
276+
string prefServerSrc = EditorPrefs.GetString("MCPForUnity.ServerSrc", string.Empty) ?? string.Empty;
277+
if (!string.IsNullOrEmpty(prefServerSrc) && PathsEqualSafe(prefServerSrc, serverSrcPath)) return true;
278+
279+
string prefOverride = EditorPrefs.GetString("MCPForUnity.PythonDirOverride", string.Empty) ?? string.Empty;
280+
if (!string.IsNullOrEmpty(prefOverride) && PathsEqualSafe(prefOverride, serverSrcPath)) return true;
281+
}
282+
catch { }
283+
284+
// Cursor config (~/.cursor/mcp.json)
285+
string user = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty;
286+
string cursorCfg = Path.Combine(user, ".cursor", "mcp.json");
287+
if (File.Exists(cursorCfg))
288+
{
289+
try
290+
{
291+
string json = File.ReadAllText(cursorCfg);
292+
string dir = ExtractDirectoryArgFromJson(json);
293+
if (!string.IsNullOrEmpty(dir) && PathsEqualSafe(dir, serverSrcPath)) return true;
294+
}
295+
catch { }
296+
}
297+
}
298+
catch { }
299+
return false;
300+
}
301+
302+
// Minimal helper to extract the value following a --directory token in a plausible JSON args array
303+
private static string ExtractDirectoryArgFromJson(string json)
304+
{
305+
try
306+
{
307+
if (string.IsNullOrEmpty(json)) return null;
308+
int argsIdx = json.IndexOf("\"args\"", StringComparison.OrdinalIgnoreCase);
309+
if (argsIdx < 0) return null;
310+
int arrStart = json.IndexOf('[', argsIdx);
311+
if (arrStart < 0) return null;
312+
int depth = 0;
313+
int arrEnd = -1;
314+
for (int i = arrStart; i < json.Length; i++)
315+
{
316+
char c = json[i];
317+
if (c == '[') depth++;
318+
else if (c == ']') { depth--; if (depth == 0) { arrEnd = i; break; } }
319+
}
320+
if (arrEnd <= arrStart) return null;
321+
string arrBody = json.Substring(arrStart + 1, arrEnd - arrStart - 1);
322+
// Split on commas at top-level (best effort for simple arrays of strings)
323+
string[] raw = arrBody.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
324+
var parts = new List<string>(raw.Length);
325+
foreach (var r in raw)
326+
{
327+
string s = r.Trim();
328+
if (s.Length >= 2 && s[0] == '"' && s[s.Length - 1] == '"')
329+
{
330+
s = s.Substring(1, s.Length - 2);
331+
}
332+
parts.Add(s);
333+
}
334+
for (int i = 0; i < parts.Count - 1; i++)
335+
{
336+
if (string.Equals(parts[i], "--directory", StringComparison.OrdinalIgnoreCase))
337+
{
338+
return parts[i + 1];
339+
}
340+
}
341+
}
342+
catch { }
343+
return null;
344+
}
345+
261346
private static IEnumerable<string> GetLegacyRootsForDetection()
262347
{
263348
var roots = new System.Collections.Generic.List<string>();

0 commit comments

Comments
 (0)