Skip to content

Skip plugin auto-start in headless batchmode (fix CI / -runTests)#838

Open
nwl9009 wants to merge 1 commit into
IvanMurzak:mainfrom
nwl9009:feat/skip-autostart-in-batchmode
Open

Skip plugin auto-start in headless batchmode (fix CI / -runTests)#838
nwl9009 wants to merge 1 commit into
IvanMurzak:mainfrom
nwl9009:feat/skip-autostart-in-batchmode

Conversation

@nwl9009

@nwl9009 nwl9009 commented Jun 19, 2026

Copy link
Copy Markdown

Problem

The Editor plugin auto-starts and connects to the local MCP server on every domain load via Startup ([InitializeOnLoad]UnityMcpPluginEditor.Instance.BuildMcpPluginIfNeeded() in Editor/Scripts/Startup.cs). This also fires under headless -batchmode -runTests. When the package is committed to a project whose CI runs Unity headless:

  1. The headless instance connects to the same local MCP server as the developer's interactive Editor on that machine and forcibly disconnects the interactive client — log: McpManagerClientHub: Server forcefully disconnected this plugin. Reason: Authorization failed. Token may be missing, invalid, or revoked.
  2. In a clean CI checkout there's no token, so the plugin logs an [Error] from a background SignalR connection callback. Unity's Test Framework converts that stray error into a test failure, so every PlayMode test goes red regardless of its own assertions. It can't be suppressed with LogAssert.ignoreFailingMessages because the log isn't raised on the test's main-thread scope.

Fix

Return early from Startup's static constructor when Application.isBatchMode, so the plugin neither builds nor connects during headless runs. Intentional headless use (e.g. running the MCP server in CI on purpose) is preserved via an opt-in environment variable UNITY_MCP_BATCHMODE=1.

if (Application.isBatchMode && System.Environment.GetEnvironmentVariable("UNITY_MCP_BATCHMODE") != "1")
    return;

Notes

  • Minimal, behavior-preserving for interactive use (the common path is unaffected).
  • Workaround without this change: strip the package from the CI worktree before -runTests. A built-in gate removes that need.

🤖 Generated with Claude Code

The Editor plugin auto-starts and connects to the local MCP server on every domain load via
`Startup` ([InitializeOnLoad]). This also fires in headless `-batchmode -runTests`. When the package
is committed to a project whose CI runs headless:

1. The headless instance connects to the same local server as the developer's interactive Editor and
   forcibly disconnects the interactive client ("Server forcefully disconnected this plugin. Reason:
   Authorization failed.").
2. With no token in a clean CI checkout, the plugin logs an [Error] from a background SignalR
   connection callback, which Unity's Test Framework turns into a test failure — failing every
   PlayMode test regardless of its own result. It can't be suppressed with
   LogAssert.ignoreFailingMessages (the log isn't on the test's main-thread scope).

Fix: return early from `Startup`'s static constructor when `Application.isBatchMode`, so the plugin
neither builds nor connects in headless. Preserves intentional headless use via an opt-in env var
`UNITY_MCP_BATCHMODE=1`.
@nwl9009 nwl9009 requested a review from IvanMurzak as a code owner June 19, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant