Unity MCP WebSocket Hub Session Management Explained
Unity MCP WebSocket hub session management establishes persistent connections between AI assistants and the Unity editor through a resilient transport layer that handles registration, keep-alive pings, and automatic reconnection with exponential backoff.
The Model Context Protocol (MCP) bridge in the CoplayDev/unity-mcp repository enables AI assistants to communicate with the Unity editor via a WebSocket transport connected to the MCP server's plugin hub (/hub/plugin). Understanding how this WebSocket hub manages session lifecycles—from initial connection establishment through error recovery—is essential for building reliable AI-powered Unity workflows.
WebSocket Connection Establishment
The session lifecycle begins in WebSocketTransportClient.cs where the transport builds connection candidates and resolves the correct URI for the MCP hub.
The BuildWebSocketUri method (lines 22‑48) constructs the WebSocket endpoint, while BuildConnectionCandidateUris (lines 61‑72) handles edge cases with bind-only hosts. When the server binds to 0.0.0.0, the client translates this to 127.0.0.1; similarly, :: becomes ::1 for local connections. If the user selects "localhost," the transport falls back to explicit loopback addresses to ensure reliable connectivity.
Client Registration and Session ID Assignment
Once the socket opens, the client initiates the registration protocol. The SendRegisterAsync method (lines 92‑104) transmits a register message containing project metadata including the project name, hash, Unity version, and file path.
The server responds with a registered message processed by HandleRegisteredAsync (lines 110‑118). This response contains the critical session ID that uniquely identifies this editor instance to the MCP hub. The client immediately stores this identifier in ProjectIdentityUtility for reuse across reconnects and includes it in every subsequent ping/pong exchange.
Persistent Session State with ProjectIdentityUtility
Session persistence relies on ProjectIdentityUtility.cs (lines 13‑20), which stores the session ID in EditorPrefs keyed to the specific project. This per-project storage enables:
- Session restoration after network interruptions or editor domain reloads
- Cross-transport recognition allowing HTTP local transports to detect active WebSocket sessions
- UI state synchronization ensuring the connection interface reflects the actual hub registration status
The SetSessionId helper persists the identifier, while companion methods retrieve project hashes and names required during re-registration.
Keep-Alive Mechanism and Ping/Pong Protocol
Active sessions require periodic health checks. The KeepAliveLoopAsync method (lines 66‑76) manages the heartbeat interval, which is negotiated from the server's welcome message (keepAliveInterval).
The transport sends pong payloads via SendPongAsync (lines 108‑115) containing the current session ID. This allows the MCP server to detect stale connections and maintain accurate session rosters. If the server fails to receive these pongs within the negotiated window, it marks the session as disconnected.
Error Handling and Auto-Reconnection Strategy
When network failures occur, HandleSocketClosureAsync (lines 145‑164) captures the error, logs the failure, and transitions the transport to a disconnected state. Control then passes to AttemptReconnectAsync (lines 166‑208), which implements a sophisticated retry schedule.
The reconnection algorithm follows this delay pattern:
- Immediate first attempt
- 1 second delay
- 3 second delay
- 5 second delay
- 10 second delay
- 30 second delay
- Perpetual 30‑second retries thereafter
Upon successful reconnection, the client automatically re-registers tools via SendRegisterToolsAsync and restores the previous session ID from ProjectIdentityUtility, maintaining continuity for AI assistant interactions.
UI Integration and Session Visualization
The McpConnectionSection.cs component (lines 21‑38) provides the visual interface for session management. The UpdateConnectionStatus method reflects the transport state by:
- Disabling the connection toggle when a session is already active
- Updating button labels to show current status
- Automatically terminating orphaned sessions when the server disappears unexpectedly
This ensures users always have accurate visibility into the WebSocket hub connection state without manual verification.
Practical Implementation Examples
Starting a WebSocket Session
var transport = new WebSocketTransportClient();
await transport.StartAsync(); // triggers connection, registration, keep‑alive
Debug.Log($"Session ID: {transport.State.SessionId}");
Sending Diagnostic Pings
await transport.SendPongAsync(CancellationToken.None);
Force-Stopping a Session
Useful during domain reloads or when switching transports:
transport.ForceStop(); // aborts socket, cancels reconnection loops
Re-registering After Hot-Reload
await transport.ReregisterToolsAsync();
Summary
- Connection establishment handles localhost binding edge cases through
BuildWebSocketUriandBuildConnectionCandidateUrisinWebSocketTransportClient.cs - Session registration exchanges project metadata for a unique session ID stored in
ProjectIdentityUtility - State persistence uses
EditorPrefsto maintain session continuity across editor restarts and domain reloads - Keep-alive protocol sends periodic
pongmessages with session IDs to prevent server-side timeout - Auto-reconnection implements exponential backoff (1s, 3s, 5s, 10s, 30s) via
AttemptReconnectAsync - UI synchronization through
McpConnectionSectionensures users have real-time visibility into session status
Frequently Asked Questions
How does Unity MCP handle session persistence between editor restarts?
The transport persists session IDs using EditorPrefs through the ProjectIdentityUtility.SetSessionId method (lines 13‑20). When Unity restarts, the client retrieves the previous session identifier from MCPForUnity/Editor/Helpers/ProjectIdentityUtility.cs and attempts to reclaim the existing session during registration, ensuring AI assistants maintain context across editor sessions.
What happens when the WebSocket connection drops unexpectedly?
The HandleSocketClosureAsync method (lines 145‑164) detects the closure and triggers AttemptReconnectAsync (lines 166‑208), which follows a progressive retry schedule (immediate, 1s, 3s, 5s, 10s, 30s, then perpetual 30s). During successful reconnection, the client automatically re-registers tools and restores the session ID without user intervention.
How does the transport resolve localhost binding issues?
In WebSocketTransportClient.cs, the BuildConnectionCandidateUris method (lines 61‑72) translates bind-all addresses to loopback equivalents—converting 0.0.0.0 to 127.0.0.1 and :: to ::1—ensuring the client connects correctly regardless of whether the server binds to specific interfaces or wildcard addresses.
Can multiple Unity projects maintain simultaneous MCP sessions?
Yes. Because ProjectIdentityUtility stores session data in EditorPrefs using project-specific keys (combining project hash and name), each Unity project maintains its own independent session ID. The WebSocket transport connects to /hub/plugin with unique identifiers, allowing the MCP server to distinguish between multiple concurrent Unity editor instances.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →