How UnityInstanceMiddleware Enables Session-Based Routing in MCP
UnityInstanceMiddleware is a FastMCP middleware that maintains a session-scoped mapping of client IDs to Unity instance identifiers, injecting the active instance into each request's context to enable isolated, concurrent routing across multiple Unity Editor sessions.
The CoplayDev/unity-mcp repository implements a FastMCP-based bridge between AI assistants and Unity Editor instances. At the core of this architecture lies the UnityInstanceMiddleware, which solves the critical challenge of routing MCP tool calls to the correct Unity session when multiple editors or projects are active simultaneously.
Middleware Architecture and Registration
UnityInstanceMiddleware sits between every MCP tool or resource invocation and the underlying Unity instance. According to the architecture documentation in website/docs/architecture/remote-auth.md (lines 119-124), this middleware registers itself in the FastMCP middleware chain to intercept requests before they reach tool handlers. This positioning allows the middleware to inspect the incoming request context and determine which Unity instance should handle the operation.
Session-Based Instance Resolution
Computing the Session Key
The middleware computes a unique session key via get_session_key(ctx), which prioritizes the client_id supplied by the remote HTTP transport or falls back to the Stdio session ID. As implemented in the test suite at Server/tests/test_transport_characterization.py (lines 124-131), this approach ensures that two concurrent clients maintain distinct active instances even when targeting the same Unity Editor pool. The session key derivation ensures that requests from different clients never share instance state unless explicitly configured.
Thread-Safe Storage Mechanism
Internally, the middleware uses an async-safe in-memory dictionary keyed by session keys. The test suite validates concurrent updates at Server/tests/test_transport_characterization.py (lines 190-206), confirming that the middleware safely handles parallel requests from multiple agents without race conditions. The last-write-wins semantics ensure that the most recent instance assignment for a given session is always the one used for routing.
Active Instance Lifecycle Management
The middleware exposes explicit methods for managing the session-to-instance mapping. When a client attaches to a specific Unity project, the bridge calls set_active_instance(context, instance_id), which stores the mapping in the session-scoped store. Conversely, clear_active_instance(context) removes the entry when a client disconnects or switches projects. Tests in Server/tests/test_transport_characterization.py (lines 173-188) verify that instances can be set, retrieved, and cleared correctly per session, ensuring clean isolation between client connections.
Request Context Injection
Per-Request Instance Injection
For every tool or resource invocation, the middleware's on_call_tool and on_read_resource hooks invoke the internal _inject_unity_instance method. This method looks up the session key and, if an instance mapping exists, injects it into the FastMCP context at fastmcp_context.state["unity_instance"] = instance_id (referenced in Server/tests/test_transport_characterization.py, lines 216-224). Tool implementations then read this value to determine which Unity editor to communicate with.
Fallback to Global Instance
If no instance is stored for the current session, the middleware passes the request through without modification, allowing the tool to fall back to a global default instance. This behavior ensures backward compatibility for single-instance deployments while enabling multi-session support when explicitly configured.
Tool Visibility and Project Filtering
Because the middleware executes before tool visibility checks, it can filter available tools based on the active project configuration. As noted in Server/tests/test_transport_characterization.py (lines 336-352), the middleware integrates with PluginHub.get_tools_for_project to ensure clients only see tools belonging to the specific Unity instance they are attached to. This prevents cross-contamination between projects and ensures that tool schemas match the capabilities of the targeted Unity version.
Implementation Example
The following pattern demonstrates how to configure the middleware and manage instance routing in practice:
from unity_mcp.transport import UnityInstanceMiddleware
# Initialize the middleware
middleware = UnityInstanceMiddleware()
# Set the active instance after client selects a project
await middleware.set_active_instance(ctx, "MyProject@hash123")
# Inside a tool handler, retrieve the injected instance
instance_id = ctx.state.get("unity_instance")
# Use instance_id to route commands to the correct Unity editor
# Clean up when client disconnects
await middleware.clear_active_instance(ctx)
Summary
- UnityInstanceMiddleware registers with FastMCP to intercept all tool and resource calls before they reach handlers.
- Session keys are derived from
client_idor transport session IDs, ensuring isolated routing per client connection. - Thread-safe storage uses an async-safe dictionary keyed by session keys, validated for concurrent access.
- Automatic injection populates
ctx.state["unity_instance"]via_inject_unity_instance, allowing tools to route commands correctly. - Lifecycle methods
set_active_instanceandclear_active_instanceenable dynamic attachment and detachment from Unity projects. - Tool filtering ensures clients only see tools compatible with their active Unity instance.
Frequently Asked Questions
What is UnityInstanceMiddleware?
UnityInstanceMiddleware is a FastMCP middleware component in the CoplayDev/unity-mcp repository that manages the relationship between MCP client sessions and Unity Editor instances. It maintains a session-scoped mapping and injects the correct instance identifier into each request's context, enabling multiple AI assistants to work with different Unity projects simultaneously.
How does session isolation work between concurrent clients?
The middleware computes a unique session key via get_session_key(ctx), which prioritizes the client_id from the HTTP transport or Stdio session. Each client's requests are routed to their own slot in the internal storage dictionary, meaning two clients can maintain different active instances against the same Unity Editor pool without interfering with each other.
Can multiple clients connect to the same Unity instance?
Yes, while the default behavior isolates clients by session key, the middleware supports scenarios where multiple clients share an instance by explicitly setting the same instance ID via set_active_instance. The routing logic simply retrieves whatever instance ID is stored for that client's session key, allowing both shared and isolated usage patterns.
What happens if no Unity instance is set for the current session?
If _inject_unity_instance finds no mapping for the computed session key, the middleware passes the request through without modification. This allows the tool implementation to fall back to a global default instance, ensuring backward compatibility for deployments where only one Unity instance is available.
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 →