Unity (C#) Backend Architecture
Relevant source files
The following files were used as context for generating this wiki page: - [Packages/src/Editor/Server/McpServerController.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Server/McpServerController.cs) - [Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs) - [Packages/src/Editor/Api/McpTools/Core/IUnityTool.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Api/McpTools/Core/IUnityTool.cs) - [Packages/src/Editor/Execution/CommandRunner.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Execution/CommandRunner.cs) - [Packages/src/Editor/UI/McpEditorWindow.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/UI/McpEditorWindow.cs) - [Packages/src/ARCHITECTURE.md](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/ARCHITECTURE.md) - [Packages/src/README.md](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/README.md) - [Packages/src/Editor/Compilation/RoslynCompiler.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Compilation/RoslynCompiler.cs) - [Packages/src/Editor/Config/UnityMcpPathResolver.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Config/UnityMcpPathResolver.cs) - [Packages/src/TOOL_REFERENCE.md](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/TOOL_REFERENCE.md)The uLoopMCP Unity (C#) Backend is an integrated TCP server that runs within the Unity Editor. Its primary purpose is to expose Unity's core functionalities—such as compilation, testing, scene manipulation, and dynamic code execution—to external Model Context Protocol (MCP) clients, typically a TypeScript server that bridges communication with LLM-powered tools. This allows AI agents to programmatically control the Unity Editor, enabling autonomous development loops.
The architecture is designed to be modular and extensible, centered around a "Tool" pattern. It features a robust security model to control access to sensitive Unity APIs, schema-driven communication for type safety, and session management resilient to domain reloads. The system is managed through a dedicated Editor window, which provides controls for server state, port configuration, and security settings. For more high-level context, see the TypeScript Server Architecture.
Sources: Packages/src/ARCHITECTURE.md, Packages/src/README.md
System Overview
The Unity C# backend is one of the three main components of the uLoopMCP system. It communicates exclusively with the TypeScript server, which in turn communicates with MCP clients like Cursor or Claude Code.
This diagram illustrates the high-level interaction between the system components.
The communication flow is as follows:
- The TypeScript server sends a JSON-RPC request to the Unity C# backend over a TCP socket.
- The
McpServerControllerreceives the raw data. - The request is passed to the
CommandRunnerfor processing. - The
CommandRunneridentifies the requested tool, validates it against security policies, and executes it. - The tool's response is serialized and sent back to the TypeScript server over the same TCP connection.
Sources: Packages/src/ARCHITECTURE.md, Packages/src/Editor/Server/McpServerController.cs, Packages/src/Editor/Execution/CommandRunner.cs
Core Components
The C# backend is composed of several key classes that manage the server lifecycle, UI, and command execution.
| Component | Description | Source File |
|---|---|---|
McpServerController | The central orchestrator. Manages the TCP server's lifecycle (start, stop, recovery after domain reload), handles client connections, and dispatches incoming requests. | Editor/Server/McpServerController.cs |
McpEditorWindow | Provides the GUI within the Unity Editor (Window > uLoopMCP) for managing the server, configuring settings (port, auto-start), and adjusting security levels. | Editor/UI/McpEditorWindow.cs |
CommandRunner | Receives parsed JSON-RPC requests, finds the corresponding tool via UnityToolRegistry, performs security checks, and executes the tool. | Editor/Execution/CommandRunner.cs |
UnityToolRegistry | Discovers and maintains a collection of all available tools (IUnityTool implementations) using reflection to find classes marked with the [McpTool] attribute. | Editor/Api/McpTools/Core/UnityToolRegistry.cs |
RoslynCompiler | Handles the execute-dynamic-code tool. It compiles and executes C# code snippets at runtime, subject to defined security levels. | Editor/Compilation/RoslynCompiler.cs |
UnityMcpPathResolver | A utility class responsible for resolving all necessary file paths, such as LLM tool configuration files (mcp.json) and the location of the TypeScript server bundle. | Editor/Config/UnityMcpPathResolver.cs |
Sources: Packages/src/Editor/Server/McpServerController.cs, Packages/src/Editor/UI/McpEditorWindow.cs, Packages/src/Editor/Execution/CommandRunner.cs, Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs, Packages/src/Editor/Compilation/RoslynCompiler.cs, Packages/src/Editor/Config/UnityMcpPathResolver.cs
Tool System Architecture
The extensibility of the C# backend is built on a "Tool" pattern. Every command exposed to the MCP client is an implementation of the IUnityTool interface.
Tool Definition
Tools are defined by implementing the IUnityTool interface, typically by inheriting from the generic AbstractUnityTool<TSchema, TResponse> class. This provides a type-safe structure for defining parameters and responses.
This class diagram shows the relationship between the core tool interfaces and a concrete implementation.
Key aspects of the tool system:
IUnityTool: The base interface for all tools, defining theToolNameand a genericExecuteAsyncmethod.AbstractUnityTool<TSchema, TResponse>: A base class that simplifies tool creation with strongly-typed, serializable schema and response classes.[McpTool]Attribute: A class-level attribute that marks a class as a tool, allowingUnityToolRegistryto discover it automatically during startup.- Execution on Main Thread: All tools are executed on Unity's main thread, ensuring safe access to Unity APIs.
Sources: Packages/src/Editor/Api/McpTools/Core/IUnityTool.cs, Packages/src/README.md, Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs
Creating a Custom Tool
Developers can extend uLoopMCP by creating their own tools. This involves creating schema/response classes and a tool class that inherits from AbstractUnityTool.
// 1. Define parameters
public class MyCustomSchema : BaseToolSchema
{
[Description("Parameter description")]
public string MyParameter { get; set; } = "default_value";
}
// 2. Define response
public class MyCustomResponse : BaseToolResponse
{
public string Result { get; set; }
}
// 3. Implement the tool
[McpTool(Description = "Description of my custom tool")]
public class MyCustomTool : AbstractUnityTool<MyCustomSchema, MyCustomResponse>
{
public override string ToolName => "my-custom-tool";
protected override Task<MyCustomResponse> ExecuteAsync(MyCustomSchema parameters, CancellationToken cancellationToken)
{
// Custom logic here...
string result = $"Processed '{parameters.MyParameter}'";
return Task.FromResult(new MyCustomResponse { Result = result });
}
}
Sources: Packages/src/README.md
Request Execution Flow
When a command is sent from an MCP client, it follows a specific sequence within the Unity backend.
This sequence diagram shows the lifecycle of a single tool execution request.
Security Architecture
Security is a critical aspect, especially for tools like execute-dynamic-code that can perform powerful operations. The security model is managed via the McpEditorWindow and settings are persisted in McpEditorSettings.
General Tool Security
The following tools can be enabled or disabled:
- Allow Tests Execution: Enables the
run-teststool. - Allow Menu Item Execution: Enables the
execute-menu-itemtool. - Allow Third Party Tools: Enables custom tools developed for a specific project.
Sources: Packages/src/README.md, Packages/src/Editor/UI/McpEditorWindow.cs
Dynamic Code Execution Security
The execute-dynamic-code tool has a three-tier security model, implemented by the RoslynCompiler and its internal SecurityValidator.
| Level | Name | Description |
|---|---|---|
| 0 | Disabled | No compilation or execution is allowed. This is the safest setting. |
| 1 | Restricted | (Recommended) Allows use of most Unity APIs and standard libraries but blocks security-critical operations like file deletion (File.Delete), network access (HttpClient), and process execution (Process.Start). |
| 2 | FullAccess | No restrictions. All assemblies and APIs are accessible. This poses a security risk and should only be used with fully trusted code. |
The RoslynCompiler initializes its assembly references based on the current security level. In Restricted mode, the SecurityValidator inspects the compiled code's syntax tree for calls to dangerous APIs before execution is permitted.
Sources: Packages/src/README.md, Packages/src/Editor/Compilation/RoslynCompiler.cs
Configuration and Path Management
The UnityMcpPathResolver class is a static utility responsible for locating all relevant configuration files and directories for various LLM tools. This centralization simplifies integration with different development environments.
Path Resolution Logic
The resolver can locate configuration files in different locations depending on the tool and user settings:
- Project-based: For tools like Cursor (
.cursor/mcp.json) and VSCode (.vscode/mcp.json), it looks in the project root. - Home Directory-based: For tools like Windsurf and Codex, it looks in the user's home directory (
~/.codeium/or~/.codex/). - Git Root vs. Project Root: The system can be configured to place configuration files at the Git repository root instead of the Unity project root, which is useful for monorepos.
The resolver also finds the server.bundle.js file for the TypeScript server, searching multiple locations to support both local development and package manager installations.
This flowchart shows the logic for resolving a configuration file path.
Conclusion
The uLoopMCP Unity (C#) Backend provides a powerful and secure bridge between AI agents and the Unity Editor. Its architecture, founded on the principles of modularity and extensibility through the Tool pattern, allows developers to easily add custom functionality. The schema-driven, type-safe communication combined with a multi-level security model ensures both reliability and safety. Centralized components like McpServerController, CommandRunner, and UnityToolRegistry work in concert to create a robust system for automating complex development tasks within Unity.
Sources: Packages/src/ARCHITECTURE.md, Packages/src/README.md## FULL FILE CONTEXT SUMMARY
The user wants a technical wiki page about the "Unity (C#) Backend Architecture" of the uLoopMCP project.
I need to provide a detailed breakdown of the C# components that run inside the Unity Editor.
Based on the file context, here's a summary of the key architectural points:
-
High-Level Structure (
ARCHITECTURE.md,README.md):- The system has three parts: MCP Clients (LLMs), a TypeScript Server (Node.js), and the Unity Editor Backend (C# TCP Server).
- The TypeScript server communicates with the Unity backend via TCP/JSON-RPC on localhost.
- The Unity backend is responsible for exposing editor functions as "tools" to the TypeScript server.
- Key patterns mentioned are MVP (Model-View-Presenter) for the UI, and a "Tool Pattern" for commands.
-
Core Components & Flow:
McpServerController.cs: This is the main entry point. It starts, stops, and manages the TCP server. It listens for client connections and receives raw request data. It's responsible for handling domain reloads and restoring the server state.McpEditorWindow.cs: This is the UI layer (the "View" in MVP). It provides buttons and settings in a Unity window to control theMcpServerController. It allows users to set the port, security levels, and configure different LLM tools.CommandRunner.cs: This class is the request handler. It takes a raw JSON-RPC request, parses it, finds the corresponding tool, checks security permissions, and executes it. It's the central dispatcher for all incoming commands.IUnityTool.cs&UnityToolRegistry.cs: This defines the "Tool" pattern.IUnityToolis the interface all command tools must implement.UnityToolRegistryuses reflection to discover all classes that implementIUnityTooland have the[McpTool]attribute. It acts as a service locator for tools.- The
README.mdshows how to create a custom tool by inheriting fromAbstractUnityTool<TSchema, TResponse>, which provides type-safe parameters and responses.
-
Security (
README.md,RoslynCompiler.cs,McpEditorWindow.cs):- Security is a major feature. It's configured in
McpEditorWindow. - There are general toggles for enabling/disabling features like test execution, menu item execution, and custom "third-party" tools.
- The most detailed security is around the
execute-dynamic-codetool, which is handled byRoslynCompiler.cs. RoslynCompilerimplements a 3-tier security level:- Level 0 (Disabled): No code execution.
- Level 1 (Restricted): Recommended. Blocks dangerous APIs like
File.Delete,HttpClient,Process.Start. This is enforced by aSecurityValidatorthat analyzes the compiled code. - Level 2 (FullAccess): No restrictions.
- Security is a major feature. It's configured in
-
Dynamic Code Execution (
RoslynCompiler.cs,README.md):- This is a core feature, powered by the
RoslynCompilerclass. - It requires the
Microsoft.CodeAnalysis.CSharp(Roslyn) package. - It can take a simple C# script, wrap it in a class and an
ExecuteAsyncmethod, compile it, and run it. - The wrapping logic is smart enough to handle existing
usingstatements and top-level code.
- This is a core feature, powered by the
-
Configuration & Path Management (
UnityMcpPathResolver.cs):- The system needs to interact with configuration files for various LLM tools (Cursor, Claude Code, VSCode, etc.). These files (
mcp.json,config.toml) can be in different locations (project root, user home directory). UnityMcpPathResolveris a static utility class that centralizes all this path-finding logic.- It also handles a setting to place configs in the Git repository root instead of the Unity project root, which is useful for monorepos.
- It has logic to find the TypeScript server's
server.bundle.jsfile, whether the package is in local development mode (Packages/src) or installed via the package manager (Library/PackageCache).
- The system needs to interact with configuration files for various LLM tools (Cursor, Claude Code, VSCode, etc.). These files (
-
Request Flow (Synthesized from multiple files):
- TypeScript server sends a JSON-RPC request over TCP.
McpServerControllerreceives it.- The request is passed to
CommandRunner. CommandRunnerusesUnityToolRegistryto find theIUnityToolinstance by name.CommandRunnerchecks security settings (e.g., isrun-testsallowed?).- If allowed,
CommandRunnercallsExecuteAsyncon the tool instance. - The tool runs on the Unity main thread.
- The result is sent back through
McpServerController.
This information is sufficient to build a comprehensive wiki page with diagrams and tables as requested. I will structure the page logically, starting with the high-level overview and then diving into the core components, the tool system, the execution flow, and finally security and configuration. I will use Mermaid diagrams to visualize the architecture and flows. I will cite all information from the provided source files.
Relevant source files
The following files were used as context for generating this wiki page: - [Packages/src/Editor/Server/McpServerController.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Server/McpServerController.cs) - [Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs) - [Packages/src/Editor/Api/McpTools/Core/IUnityTool.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Api/McpTools/Core/IUnityTool.cs) - [Packages/src/Editor/Execution/CommandRunner.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Execution/CommandRunner.cs) - [Packages/src/Editor/UI/McpEditorWindow.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/UI/McpEditorWindow.cs) - [Packages/src/ARCHITECTURE.md](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/ARCHITECTURE.md) - [Packages/src/README.md](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/README.md) - [Packages/src/Editor/Compilation/RoslynCompiler.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Compilation/RoslynCompiler.cs) - [Packages/src/Editor/Config/UnityMcpPathResolver.cs](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/Editor/Config/UnityMcpPathResolver.cs) - [Packages/src/TOOL_REFERENCE.md](https://github.com/hatayama/uLoopMCP/blob/main/Packages/src/TOOL_REFERENCE.md)The uLoopMCP Unity (C#) Backend is an integrated TCP server that runs within the Unity Editor. Its primary purpose is to expose Unity's core functionalities—such as compilation, testing, scene manipulation, and dynamic code execution—to external Model Context Protocol (MCP) clients, typically a TypeScript server that bridges communication with LLM-powered tools. This allows AI agents to programmatically control the Unity Editor, enabling autonomous development loops.
The architecture is designed to be modular and extensible, centered around a "Tool" pattern. It features a robust security model to control access to sensitive Unity APIs, schema-driven communication for type safety, and session management resilient to domain reloads. The system is managed through a dedicated Editor window, which provides controls for server state, port configuration, and security settings. For more high-level context, see the TypeScript Server Architecture.
Sources: Packages/src/ARCHITECTURE.md, Packages/src/README.md
System Overview
The Unity C# backend is one of the three main components of the uLoopMCP system. It communicates exclusively with the TypeScript server, which in turn communicates with MCP clients like Cursor or Claude Code.
This diagram illustrates the high-level interaction between the system components.
The communication flow is as follows:
- The TypeScript server sends a JSON-RPC request to the Unity C# backend over a TCP socket.
- The
McpServerControllerreceives the raw data. - The request is passed to the
CommandRunnerfor processing. - The
CommandRunneridentifies the requested tool, validates it against security policies, and executes it. - The tool's response is serialized and sent back to the TypeScript server over the same TCP connection.
Sources: Packages/src/ARCHITECTURE.md, Packages/src/Editor/Server/McpServerController.cs, Packages/src/Editor/Execution/CommandRunner.cs
Core Components
The C# backend is composed of several key classes that manage the server lifecycle, UI, and command execution.
| Component | Description | Source File |
|---|---|---|
McpServerController | The central orchestrator. Manages the TCP server's lifecycle (start, stop, recovery after domain reload), handles client connections, and dispatches incoming requests. | Editor/Server/McpServerController.cs |
McpEditorWindow | Provides the GUI within the Unity Editor (Window > uLoopMCP) for managing the server, configuring settings (port, auto-start), and adjusting security levels. | Editor/UI/McpEditorWindow.cs |
CommandRunner | Receives parsed JSON-RPC requests, finds the corresponding tool via UnityToolRegistry, performs security checks, and executes the tool. | Editor/Execution/CommandRunner.cs |
UnityToolRegistry | Discovers and maintains a collection of all available tools (IUnityTool implementations) using reflection to find classes marked with the [McpTool] attribute. | Editor/Api/McpTools/Core/UnityToolRegistry.cs |
RoslynCompiler | Handles the execute-dynamic-code tool. It compiles and executes C# code snippets at runtime, subject to defined security levels. | Editor/Compilation/RoslynCompiler.cs |
UnityMcpPathResolver | A utility class responsible for resolving all necessary file paths, such as LLM tool configuration files (mcp.json) and the location of the TypeScript server bundle. | Editor/Config/UnityMcpPathResolver.cs |
Sources: Packages/src/Editor/Server/McpServerController.cs, Packages/src/Editor/UI/McpEditorWindow.cs, Packages/src/Editor/Execution/CommandRunner.cs, Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs, Packages/src/Editor/Compilation/RoslynCompiler.cs, Packages/src/Editor/Config/UnityMcpPathResolver.cs
Tool System Architecture
The extensibility of the C# backend is built on a "Tool" pattern. Every command exposed to the MCP client is an implementation of the IUnityTool interface.
Tool Definition
Tools are defined by implementing the IUnityTool interface, typically by inheriting from the generic AbstractUnityTool<TSchema, TResponse> class. This provides a type-safe structure for defining parameters and responses.
This class diagram shows the relationship between the core tool interfaces and a concrete implementation.
Key aspects of the tool system:
IUnityTool: The base interface for all tools, defining theToolNameand a genericExecuteAsyncmethod.AbstractUnityTool<TSchema, TResponse>: A base class that simplifies tool creation with strongly-typed, serializable schema and response classes.[McpTool]Attribute: A class-level attribute that marks a class as a tool, allowingUnityToolRegistryto discover it automatically during startup.- Execution on Main Thread: All tools are executed on Unity's main thread, ensuring safe access to Unity APIs.
Sources: Packages/src/Editor/Api/McpTools/Core/IUnityTool.cs, Packages/src/README.md, Packages/src/Editor/Api/McpTools/Core/UnityToolRegistry.cs
Creating a Custom Tool
Developers can extend uLoopMCP by creating their own tools. This involves creating schema/response classes and a tool class that inherits from AbstractUnityTool.
// 1. Define parameters
public class MyCustomSchema : BaseToolSchema
{
[Description("Parameter description")]
public string MyParameter { get; set; } = "default_value";
}
// 2. Define response
public class MyCustomResponse : BaseToolResponse
{
public string Result { get; set; }
}
// 3. Implement the tool
[McpTool(Description = "Description of my custom tool")]
public class MyCustomTool : AbstractUnityTool<MyCustomSchema, MyCustomResponse>
{
public override string ToolName => "my-custom-tool";
protected override Task<MyCustomResponse> ExecuteAsync(MyCustomSchema parameters, CancellationToken cancellationToken)
{
// Custom logic here...
string result = $"Processed '{parameters.MyParameter}'";
return Task.FromResult(new MyCustomResponse { Result = result });
}
}
Sources: Packages/src/README.md
Request Execution Flow
When a command is sent from an MCP client, it follows a specific sequence within the Unity backend.
This sequence diagram shows the lifecycle of a single tool execution request.
Security Architecture
Security is a critical aspect, especially for tools like execute-dynamic-code that can perform powerful operations. The security model is managed via the McpEditorWindow and settings are persisted in McpEditorSettings.
General Tool Security
The following tools can be enabled or disabled:
- Allow Tests Execution: Enables the
run-teststool. - Allow Menu Item Execution: Enables the
execute-menu-itemtool. - Allow Third Party Tools: Enables custom tools developed for a specific project.
Sources: Packages/src/README.md, Packages/src/Editor/UI/McpEditorWindow.cs
Dynamic Code Execution Security
The execute-dynamic-code tool has a three-tier security model, implemented by the RoslynCompiler and its internal SecurityValidator.
| Level | Name | Description |
|---|---|---|
| 0 | Disabled | No compilation or execution is allowed. This is the safest setting. |
| 1 | Restricted | (Recommended) Allows use of most Unity APIs and standard libraries but blocks security-critical operations like file deletion (File.Delete), network access (HttpClient), and process execution (Process.Start). |
| 2 | FullAccess | No restrictions. All assemblies and APIs are accessible. This poses a security risk and should only be used with fully trusted code. |
The RoslynCompiler initializes its assembly references based on the current security level. In Restricted mode, the SecurityValidator inspects the compiled code's syntax tree for calls to dangerous APIs before execution is permitted.
Sources: Packages/src/README.md, Packages/src/Editor/Compilation/RoslynCompiler.cs
Configuration and Path Management
The UnityMcpPathResolver class is a static utility responsible for locating all relevant configuration files and directories for various LLM tools. This centralization simplifies integration with different development environments.
Path Resolution Logic
The resolver can locate configuration files in different locations depending on the tool and user settings:
- Project-based: For tools like Cursor (
.cursor/mcp.json) and VSCode (.vscode/mcp.json), it looks in the project root. - Home Directory-based: For tools like Windsurf and Codex, it looks in the user's home directory (
~/.codeium/or~/.codex/). - Git Root vs. Project Root: The system can be configured to place configuration files at the Git repository root instead of the Unity project root, which is useful for monorepos.
The resolver also finds the server.bundle.js file for the TypeScript server, searching multiple locations to support both local development and package manager installations.
This flowchart shows the logic for resolving a configuration file path.
Conclusion
The uLoopMCP Unity (C#) Backend provides a powerful and secure bridge between AI agents and the Unity Editor. Its architecture, founded on the principles of modularity and extensibility through the Tool pattern, allows developers to easily add custom functionality. The schema-driven, type-safe communication combined with a multi-level security model ensures both reliability and safety. Centralized components like McpServerController, CommandRunner, and UnityToolRegistry work in concert to create a robust system for automating complex development tasks within Unity.
Sources: Packages/src/ARCHITECTURE.md, Packages/src/README.md