Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using MCPForUnity.Editor.Helpers;
using MCPForUnity.Editor.Services.Transport;
using UnityEditor;
using UnityEngine;

namespace MCPForUnity.Editor.Services
{
Expand All @@ -22,8 +23,19 @@ static McpEditorShutdownCleanup()
EditorApplication.quitting += OnEditorQuitting;
}

// A -batchmode/CI instance resolves the interactive editor's server via the global
// pidfile+port handshake, so cleanup there would stop another user's server. Mirror the
// sibling guards (HttpAutoStartHandler, StdioBridgeHost): skip in batch unless opted in.
internal static bool ShouldRunCleanup() =>
ShouldRunCleanup(Application.isBatchMode, Environment.GetEnvironmentVariable("UNITY_MCP_ALLOW_BATCH"));

internal static bool ShouldRunCleanup(bool isBatchMode, string allowBatchEnv) =>
!isBatchMode || !string.IsNullOrWhiteSpace(allowBatchEnv);

private static void OnEditorQuitting()
{
if (!ShouldRunCleanup()) return;

// 1) Stop transports (best-effort, bounded wait).
try
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using NUnit.Framework;
using MCPForUnity.Editor.Services;
using UnityEngine;

namespace MCPForUnityTests.Editor.Services
{
[TestFixture]
public class McpEditorShutdownCleanupTests
{
[Test]
public void ShouldRunCleanup_InteractiveEditor_RunsCleanup()
{
Assert.IsTrue(McpEditorShutdownCleanup.ShouldRunCleanup(isBatchMode: false, allowBatchEnv: null));
}

[Test]
public void ShouldRunCleanup_BatchWithoutOverride_IsNoOp()
{
// Regression for #1196/#1010: a -batchmode/CI instance must not stop the
// interactive editor's server resolved via the global pidfile+port handshake.
Assert.IsFalse(McpEditorShutdownCleanup.ShouldRunCleanup(isBatchMode: true, allowBatchEnv: null));
}

[Test]
public void ShouldRunCleanup_BatchWithBlankOverride_IsNoOp()
{
// Whitespace is treated as unset, mirroring string.IsNullOrWhiteSpace in the sibling guards.
Assert.IsFalse(McpEditorShutdownCleanup.ShouldRunCleanup(isBatchMode: true, allowBatchEnv: ""));
Assert.IsFalse(McpEditorShutdownCleanup.ShouldRunCleanup(isBatchMode: true, allowBatchEnv: " "));
}

[Test]
public void ShouldRunCleanup_BatchWithOverride_RunsCleanup()
{
Assert.IsTrue(McpEditorShutdownCleanup.ShouldRunCleanup(isBatchMode: true, allowBatchEnv: "1"));
}

[Test]
public void ShouldRunCleanup_Parameterless_MatchesEnvironment()
{
// Proves the wiring to Application.isBatchMode / UNITY_MCP_ALLOW_BATCH is correct
// without assuming how this test run was launched (GUI Test Runner vs -batchmode CI).
bool expected = !Application.isBatchMode
|| !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("UNITY_MCP_ALLOW_BATCH"));
Assert.AreEqual(expected, McpEditorShutdownCleanup.ShouldRunCleanup());
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading