Skip to content

fix(ui): refresh transport status labels after a Transport Mode switch settles - #48

Merged
Winlifes merged 1 commit into
FunplayAI:mainfrom
dehuaichendragonplus:fix/transport-status-label-refresh
Jul 27, 2026
Merged

fix(ui): refresh transport status labels after a Transport Mode switch settles#48
Winlifes merged 1 commit into
FunplayAI:mainfrom
dehuaichendragonplus:fix/transport-status-label-refresh

Conversation

@dehuaichendragonplus

Copy link
Copy Markdown
Contributor

Why

Switching the MCP Server window's Transport Mode between Direct HTTP and Broker Mode restarts the server asynchronously (StopAsyncStartAsync, and broker bring-up spawns a process + health-probes + attaches over several frames). But the two status labels were refreshed on a fixed 2-frame delayCall, which fires long before the async restart settles:

EditorApplication.delayCall += () =>
    EditorApplication.delayCall += () => { UpdateBrokerStatus(); InvokeRefreshStatus(); };

So after switching to Broker Mode the header kept showing "Running on …" and the transport line kept showing "Transport: Direct HTTP.", even though the server had already switched (a broker process owning the port, the editor attached to it as a client).

Verified on a live editor: with the server actually in broker mode (IsAttachedToExistingTransport == true, a broker process listening on 8765, the editor connected to it), the labels still read the pre-switch Direct-HTTP text. It's a stale display, not a wrong computation — a fresh refresh produces the correct text.

What changed

FunplayMCPServerControlsPanel now refreshes the labels once the restart has actually settled instead of on a fixed delay: the transport-mode change handler awaits StopAsync/StartAsync, then calls UpdateBrokerStatus() + the header refresh. Awaiting captures the editor main-thread SynchronizationContext, so the refresh runs on the main thread against the final transport state. This also makes the labels correctly show a direct-HTTP fallback when broker mode fails to start (the settled state), which the old racing refresh could miss.

No recurring polling is introduced on purpose: MCPBrokerProcessManager.IsRunning does a synchronous loopback health probe, so polling it every frame/second would risk stalling the editor UI thread when the broker is unreachable — the refresh stays event-driven, just correctly timed.

Testing

  • Compiles clean on Unity 6000.3.13f1.
  • On a live editor in broker mode, confirmed the labels compute the correct text ("Attached to existing server on http://127.0.0.1:8765/ …" + "Transport: Broker running (pid …, port …).") — the fix makes that refresh happen after a Transport Mode switch, not only on a later window rebuild.

Independence

Touches only Editor/MCP/Server/FunplayMCPServerControlsPanel.cs. No overlap with the other open PRs; applies cleanly on current main.

Changelog

Added under ## Unreleased (Fixed).


🤖 Generated with Claude Code

…h settles

Switching to/from Broker Mode restarts the server asynchronously, but the MCP Server
window refreshed its status labels on a fixed 2-frame delayCall that raced the async
broker bring-up. After a switch to broker mode the header kept showing "Running on …"
and the transport line kept showing "Transport: Direct HTTP." even though the server
had already switched (broker process owning the port, editor attached as a client).

The refresh now runs once StopAsync/StartAsync have completed (awaited, so it resumes on
the editor main thread against the settled transport state) instead of on a fixed delay.
It also correctly reflects a direct-HTTP fallback when broker mode fails to start.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Winlifes
Winlifes merged commit 7e28572 into FunplayAI:main Jul 27, 2026
1 check passed
@Winlifes

Copy link
Copy Markdown
Member

Thanks @dehuaichendragonplus. The stale-label diagnosis was correct, and I landed the fix in main via a merge commit that preserves this PR's commit as a parent.

I adjusted the implementation before merging because assigning MCPBrokerModeEnabled already synchronously triggers the service-owned ScheduleRestart(). Awaiting another panel-owned StopAsync() / StartAsync() would create two competing restart sequences. The landed version keeps MCPServerService as the single lifecycle owner:

  • Settings restarts expose one coalesced completion task for the UI to await.
  • Transport, port, and broker-path controls show an in-progress status and refresh only after the final restart settles.
  • Rapid setting changes wait for the final queued restart instead of allowing an older completion to overwrite the labels.
  • A setting change during an in-progress startup is now restarted with the final settings.
  • Disabling the server while a settings restart is pending cannot start it again.
  • No recurring broker health polling was added.

Validation after the final changes:

  • Live Unity 2022.3 Editor: Direct to Broker, Broker to Direct, rapid Broker/Direct changes, and disable-during-restart all passed with correct header and transport labels.
  • Unity 2022.3: 240/240 EditMode tests passed.
  • Unity 6.3: 240/240 EditMode tests passed.
  • Unity 6.5: 240/240 EditMode tests passed.
  • No C# compilation errors or unhandled exceptions in the final test logs.

You are credited in the Unreleased changelog entry for #48. Thanks for the clear reproduction and for avoiding a polling-based workaround.

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.

2 participants