Skip to content

Commit a2d76b6

Browse files
committed
feat: Rebuild MCP server installation with embedded source
Refactored the server repair logic to implement a full rebuild of the MCP server installation using the embedded source. The new RebuildMcpServer method now: - Uses embedded server source instead of attempting repair of existing installation - Deletes the entire existing server directory before re-copying - Handles UV process cleanup for the target path - Simplifies the installation flow by removing the complex Python environment repair logic - Maintains the same installation behavior but with a cleaner, more reliable rebuild approach This change improves reliability of server installations by ensuring a clean slate rebuild rather than attempting to repair potentially corrupted environments.
1 parent d8fd19d commit a2d76b6

File tree

3 files changed

+40
-84
lines changed

3 files changed

+40
-84
lines changed

UnityMcpBridge/Editor/Helpers/ServerInstaller.cs

Lines changed: 33 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -423,105 +423,61 @@ private static void CopyDirectoryRecursive(string sourceDir, string destinationD
423423
}
424424
}
425425

426-
public static bool RepairPythonEnvironment()
426+
public static bool RebuildMcpServer()
427427
{
428428
try
429429
{
430-
string serverSrc = GetServerPath();
431-
bool hasServer = File.Exists(Path.Combine(serverSrc, "server.py"));
432-
if (!hasServer)
433-
{
434-
// In dev mode or if not installed yet, try the embedded/dev source
435-
if (TryGetEmbeddedServerSource(out string embeddedSrc) && File.Exists(Path.Combine(embeddedSrc, "server.py")))
436-
{
437-
serverSrc = embeddedSrc;
438-
hasServer = true;
439-
}
440-
else
441-
{
442-
// Attempt to install then retry
443-
EnsureServerInstalled();
444-
serverSrc = GetServerPath();
445-
hasServer = File.Exists(Path.Combine(serverSrc, "server.py"));
446-
}
447-
}
448-
449-
if (!hasServer)
450-
{
451-
Debug.LogWarning("RepairPythonEnvironment: server.py not found; ensure server is installed first.");
452-
return false;
453-
}
454-
455-
// Remove stale venv and pinned version file if present
456-
string venvPath = Path.Combine(serverSrc, ".venv");
457-
if (Directory.Exists(venvPath))
458-
{
459-
try { Directory.Delete(venvPath, recursive: true); } catch (Exception ex) { Debug.LogWarning($"Failed to delete .venv: {ex.Message}"); }
460-
}
461-
string pyPin = Path.Combine(serverSrc, ".python-version");
462-
if (File.Exists(pyPin))
463-
{
464-
try { File.Delete(pyPin); } catch (Exception ex) { Debug.LogWarning($"Failed to delete .python-version: {ex.Message}"); }
465-
}
466-
467-
string uvPath = FindUvPath();
468-
if (uvPath == null)
430+
// Find embedded source
431+
if (!TryGetEmbeddedServerSource(out string embeddedSrc))
469432
{
470-
Debug.LogError("UV not found. Please install uv (https://docs.astral.sh/uv/).");
433+
Debug.LogError("RebuildMcpServer: Could not find embedded server source.");
471434
return false;
472435
}
473436

474-
var psi = new System.Diagnostics.ProcessStartInfo
475-
{
476-
FileName = uvPath,
477-
Arguments = "sync",
478-
WorkingDirectory = serverSrc,
479-
UseShellExecute = false,
480-
RedirectStandardOutput = true,
481-
RedirectStandardError = true,
482-
CreateNoWindow = true
483-
};
437+
string saveLocation = GetSaveLocation();
438+
string destRoot = Path.Combine(saveLocation, ServerFolder);
439+
string destSrc = Path.Combine(destRoot, "src");
484440

485-
using var proc = new System.Diagnostics.Process { StartInfo = psi };
486-
var sbOut = new StringBuilder();
487-
var sbErr = new StringBuilder();
488-
proc.OutputDataReceived += (_, e) => { if (e.Data != null) sbOut.AppendLine(e.Data); };
489-
proc.ErrorDataReceived += (_, e) => { if (e.Data != null) sbErr.AppendLine(e.Data); };
441+
// Kill any running uv processes for this server
442+
TryKillUvForPath(destSrc);
490443

491-
if (!proc.Start())
444+
// Delete the entire installed server directory
445+
if (Directory.Exists(destRoot))
492446
{
493-
Debug.LogError("Failed to start uv process.");
494-
return false;
447+
try
448+
{
449+
Directory.Delete(destRoot, recursive: true);
450+
Debug.Log($"<b><color=#2EA3FF>MCP-FOR-UNITY</color></b>: Deleted existing server at {destRoot}");
451+
}
452+
catch (Exception ex)
453+
{
454+
Debug.LogError($"Failed to delete existing server: {ex.Message}");
455+
return false;
456+
}
495457
}
496458

497-
proc.BeginOutputReadLine();
498-
proc.BeginErrorReadLine();
459+
// Re-copy from embedded source
460+
string embeddedRoot = Path.GetDirectoryName(embeddedSrc) ?? embeddedSrc;
461+
Directory.CreateDirectory(destRoot);
462+
CopyDirectoryRecursive(embeddedRoot, destRoot);
499463

500-
if (!proc.WaitForExit(60000))
464+
// Write version file
465+
string embeddedVer = ReadVersionFile(Path.Combine(embeddedSrc, VersionFileName)) ?? "unknown";
466+
try
501467
{
502-
try { proc.Kill(); } catch { }
503-
Debug.LogError("uv sync timed out.");
504-
return false;
468+
File.WriteAllText(Path.Combine(destSrc, VersionFileName), embeddedVer);
505469
}
506-
507-
// Ensure async buffers flushed
508-
proc.WaitForExit();
509-
510-
string stdout = sbOut.ToString();
511-
string stderr = sbErr.ToString();
512-
513-
if (proc.ExitCode != 0)
470+
catch (Exception ex)
514471
{
515-
Debug.LogError($"uv sync failed: {stderr}\n{stdout}");
516-
return false;
472+
Debug.LogWarning($"Failed to write version file: {ex.Message}");
517473
}
518474

519-
Debug.Log("<b><color=#2EA3FF>MCP-FOR-UNITY</color></b>: Python environment repaired successfully.");
475+
Debug.Log($"<b><color=#2EA3FF>MCP-FOR-UNITY</color></b>: Server rebuilt successfully at {destRoot} (version {embeddedVer})");
520476
return true;
521477
}
522478
catch (Exception ex)
523479
{
524-
Debug.LogError($"RepairPythonEnvironment failed: {ex.Message}");
480+
Debug.LogError($"RebuildMcpServer failed: {ex.Message}");
525481
return false;
526482
}
527483
}

UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,25 +368,25 @@ private void DrawServerStatusSection()
368368
}
369369
EditorGUILayout.Space(4);
370370

371-
// Repair Python Env button with tooltip tag
371+
// Rebuild MCP Server button with tooltip tag
372372
using (new EditorGUILayout.HorizontalScope())
373373
{
374374
GUILayout.FlexibleSpace();
375375
GUIContent repairLabel = new GUIContent(
376-
"Repair Python Env",
377-
"Deletes the server's .venv and runs 'uv sync' to rebuild a clean environment. Use this if modules are missing or Python upgraded."
376+
"Rebuild MCP Server",
377+
"Deletes the installed server and re-copies it from the package. Use this to update the server after making source code changes or if the installation is corrupted."
378378
);
379379
if (GUILayout.Button(repairLabel, GUILayout.Width(160), GUILayout.Height(22)))
380380
{
381-
bool ok = global::MCPForUnity.Editor.Helpers.ServerInstaller.RepairPythonEnvironment();
381+
bool ok = global::MCPForUnity.Editor.Helpers.ServerInstaller.RebuildMcpServer();
382382
if (ok)
383383
{
384-
EditorUtility.DisplayDialog("MCP For Unity", "Python environment repaired.", "OK");
384+
EditorUtility.DisplayDialog("MCP For Unity", "Server rebuilt successfully.", "OK");
385385
UpdatePythonServerInstallationStatus();
386386
}
387387
else
388388
{
389-
EditorUtility.DisplayDialog("MCP For Unity", "Repair failed. Please check Console for details.", "OK");
389+
EditorUtility.DisplayDialog("MCP For Unity", "Rebuild failed. Please check Console for details.", "OK");
390390
}
391391
}
392392
}

UnityMcpBridge/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The window has four areas: Server Status, Unity Bridge, MCP Client Configuration
2929
- Ports: Unity (varies; shown in UI), MCP 6500.
3030
- Actions:
3131
- Auto-Setup: Registers/updates your selected MCP client(s), ensures bridge connectivity. Shows “Connected ✓” after success.
32-
- Repair Python Env: Rebuilds a clean Python environment (deletes `.venv`, runs `uv sync`).
32+
- Rebuild MCP Server: Rebuilds the Python based MCP server
3333
- Select server folder…: Choose the folder containing `server.py`.
3434
- Verify again: Re-checks server presence.
3535
- If Python isn’t detected, use “Open Install Instructions”.

0 commit comments

Comments
 (0)