@@ -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