diff --git a/MCPForUnity/Editor/Constants/EditorPrefKeys.cs b/MCPForUnity/Editor/Constants/EditorPrefKeys.cs index 5f99d3e5a..54a5fd006 100644 --- a/MCPForUnity/Editor/Constants/EditorPrefKeys.cs +++ b/MCPForUnity/Editor/Constants/EditorPrefKeys.cs @@ -63,5 +63,6 @@ internal static class EditorPrefKeys internal const string CustomerUuid = "MCPForUnity.CustomerUUID"; internal const string ApiKey = "MCPForUnity.ApiKey"; + internal const string KeepServerRunning = "MCPForUnity.KeepServerRunning"; } } diff --git a/MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs b/MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs index 9b4bd6143..de3683777 100644 --- a/MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs +++ b/MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs @@ -41,8 +41,17 @@ private static void OnEditorQuitting() } // 2) Stop local HTTP server if it was Unity-managed (best-effort). + // Skip shutdown if Keep Server Running is enabled - server should persist for reconnection. try { + bool keepServerRunning = EditorPrefs.GetBool(EditorPrefKeys.KeepServerRunning, false); + + if (keepServerRunning) + { + McpLog.Info("Keep Server Running is enabled - leaving MCP server running after Unity quits"); + return; + } + bool useHttp = EditorConfigurationCache.Instance.UseHttpTransport; string scope = string.Empty; try { scope = EditorPrefs.GetString(EditorPrefKeys.HttpTransportScope, string.Empty); } catch { } diff --git a/MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs b/MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs index b94c0836f..c16605495 100644 --- a/MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs +++ b/MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs @@ -58,6 +58,7 @@ public class WebSocketTransportClient : IMcpTransportClient, IDisposable private int _isReconnectingFlag; private TransportState _state = TransportState.Disconnected(TransportDisplayName, "Transport not started"); private string _apiKey; + private bool _keepServerRunning; private bool _disposed; public WebSocketTransportClient(IToolDiscoveryService toolDiscoveryService = null) @@ -85,6 +86,7 @@ public async Task StartAsync() _apiKey = HttpEndpointUtility.IsRemoteScope() ? EditorPrefs.GetString(EditorPrefKeys.ApiKey, string.Empty) : string.Empty; + _keepServerRunning = EditorPrefs.GetBool(EditorPrefKeys.KeepServerRunning, false); // Get project root path (strip /Assets from dataPath) for focus nudging string dataPath = Application.dataPath; @@ -608,7 +610,8 @@ private async Task SendRegisterAsync(CancellationToken token) ["project_name"] = _projectName, ["project_hash"] = _projectHash, ["unity_version"] = _unityVersion, - ["project_path"] = _projectPath + ["project_path"] = _projectPath, + ["keep_server_running"] = _keepServerRunning }; await SendJsonAsync(registerPayload, token).ConfigureAwait(false); diff --git a/MCPForUnity/Editor/Windows/Components/Advanced/McpAdvancedSection.cs b/MCPForUnity/Editor/Windows/Components/Advanced/McpAdvancedSection.cs index 4957e7da8..7ef801f1d 100644 --- a/MCPForUnity/Editor/Windows/Components/Advanced/McpAdvancedSection.cs +++ b/MCPForUnity/Editor/Windows/Components/Advanced/McpAdvancedSection.cs @@ -38,12 +38,14 @@ public class McpAdvancedSection private VisualElement healthIndicator; private Label healthStatus; private Button testConnectionButton; + private Toggle keepServerRunningToggle; // Events public event Action OnGitUrlChanged; public event Action OnHttpServerCommandUpdateRequested; public event Action OnTestConnectionRequested; public event Action OnBetaModeChanged; + public event Action OnKeepServerRunningChanged; public VisualElement Root { get; private set; } @@ -77,6 +79,7 @@ private void CacheUIElements() deployStatusLabel = Root.Q