Content
# Unity MCP Integration Framework
[](https://opensource.org/licenses/MIT)




[English Version](./README.en.md)
This is a Unity Editor extension framework that integrates with the Model Context Protocol (MCP). It allows direct operation of the Unity Editor from AI language models like Claude or CLI (curl) via HTTP.
## 🌟 Features (v2.1)
- **HTTP + UDP Architecture**: Each Unity Editor has an HTTP server and uses UDP broadcast for automatic discovery
- **Supports both MCP and HTTP**: Supports MCP tools from Claude Desktop/Code and direct HTTP requests from scripts/CI
- **Multi-Editor Support**: Supports multiple Unity Editors with `target` parameter or proxy for named routing
- **Domain Reload Tolerance**: Persists port with `SessionState` and automatically rebinds on reload
- **Editor Panel Capture** *(Windows)*: Captures screenshots of Inspector/Hierarchy/Project/Console and other EditorWindows
- **Built-in Code Execution**: Includes HTTP `/execute_code` and MCP tool `unity_execute_code` (using Roslyn)
- **Extensible Plugin Architecture**: Implementing `IMcpCommandHandler`/`IMcpResourceHandler`/`BasePromptHandler` allows for automatic registration via reflection
- **Unified Response Envelope**: Returns success/error/paging in a consistent format with `{status, result?, error?, truncated?, next?}`
- **Context Economy**: Allows response filtering with `limit`/`offset`/`fields`/`detail` parameters
- **Idempotency Classification**: Declares `Safe`/`Unsafe` per-action and controls retry based on `err.cause.code`
## 📋 Requirements
- Unity 2022.3 or later (supports Unity 6000 series)
- Confirmed to work with 2022.3.22f1, 2023.2.19f1, 6000.0.35f1, 6000.1.17f1
- .NET/C# 9.0
- Node.js 18.0.0 or later (for TypeScript MCP server)
- [Node.js Official Website](https://nodejs.org/)
## 🚀 Getting Started
### Installation
1. Open Window > Package Manager in Unity
2. Click "+" > "Add package from git URL..."
3. Enter `https://github.com/isuzu-shiranui/UnityMCP.git?path=jp.shiranui-isuzu.unity-mcp`
### Quick Setup
1. Launch Unity Editor, and `McpEditorInitializer` will automatically start the HTTP server (127.0.0.1:27182, with fallback to 27182-27199)
2. Check settings in Edit > Preferences > Unity MCP
3. Verify functionality with `curl http://127.0.0.1:27182/health`
### Integration with Claude Desktop/Claude Code
#### Using Installer
1. Open Edit > Preferences > Unity MCP in Unity Editor
2. Click "Open Installer Window"
3. Follow installer instructions to download TypeScript client after confirming Node.js presence
4. Copy JSON from "Configuration Preview" section to clipboard
5. Paste and save in Claude Desktop's Settings > Developer > Edit Config
6. Restart Claude Desktop
> 💡 **For macOS users**: v2.1 supports detection of Homebrew-installed Node (`/opt/homebrew/bin/node`, `/usr/local/bin/node`). Unity launched from Finder will now work properly (#7).
#### Manual Installation
1. Clone or download `unity-mcp-ts` repository or release ZIP
2. Run `npm install && npm run build` to generate `build/index.js`
3. Add to Claude Desktop's `claude_desktop_config.json`:
```json
{
"mcpServers": {
"unity-mcp": {
"command": "node",
"args": ["/absolute/path/to/unity-mcp-ts/build/index.js"]
}
}
}
```
Use forward slashes for paths on Windows.
### CLI (curl) Usage
No TypeScript server required; can operate directly via HTTP:
```bash
# Health check
curl http://127.0.0.1:27182/health
# Execute C# code
curl -X POST http://127.0.0.1:27182/execute_code \
-H "Content-Type: application/json" \
-d '{"code":"return GameObject.FindObjectsByType<Transform>(FindObjectsSortMode.None).Length;"}'
# Capture Inspector screenshot (Windows)
curl -X POST http://127.0.0.1:27182/capture_screenshot \
-H "Content-Type: application/json" \
-d '{"view":"inspector","maxSize":1024}'
```
Example with proxy for multi-Editor:
```bash
# Discover projects if multiple Unity Editors are running
curl http://127.0.0.1:27180/projects
# Forward request with project name
curl -X POST http://127.0.0.1:27180/proxy/MyProject/health
```
Includes curl workflow collection as a skill in `~/.claude/skills/unity-mcp/`.
## 🔌 Architecture (v2.1)
```
MCP client (Claude)
│ stdio (MCP protocol)
▼
unity-mcp-ts (Node)
├── HandlerAdapter / HandlerDiscovery (MCP tools / prompts / resources)
├── UnityConnection (HTTP fetch + retryableFetch)
│ ├── sendRequest(cmd, params) → POST /command
│ └── sendToEndpoint(path, body) → POST <path> (e.g. /execute_code)
├── ProjectRegistry (UDP :27183, state machine)
└── ProjectApi :27180-27189 (/projects, /proxy/:name/*)
│ HTTP
▼
Unity Editor(s) — McpHttpServer :27182-27199
├── HttpListener + main-thread execution queue
├── Built-in shortcuts + plugin handlers
└── UDP broadcast (27183) every 30s
```
### Unity C# Plugins
- **McpHttpServer**: HTTP listener + UDP broadcaster + main-thread execution queue
- **IMcpCommandHandler** / **IMcpResourceHandler**: Plugin extension interfaces (with idempotency)
- **McpIdempotency**: `Safe` / `Unsafe` enum
- **ListResponseBuilder**: Common utility for processing `limit` / `offset` / `fields`
- **McpEditorInitializer**: `InitializeOnLoad` + `AssemblyReloadEvents` for port restoration via SessionState
- **McpHandlerDiscovery**: Automatic handler registration via reflection
### TypeScript MCP Server
- **HandlerAdapter**: Registers tools/prompts/resources with MCP SDK
- **HandlerDiscovery**: Automatically registers `ICommandHandler` / `IPromptHandler` / `IResourceHandler` by scanning `src/handlers/`
- **UnityConnection**: HTTP client (with retry + idempotency + target resolution)
- **ProjectRegistry**: UDP receiver + 3-state state machine (healthy / reloading / unhealthy)
- **ProjectApi**: `/projects` + `/proxy/:name/*` on ports 27180-27189
- **retryableFetch**: Retries based on `err.cause.code` for Unsafe actions pre-handshake
## 📄 MCP Handler Types
| Type | Purpose | MCP Control | Implementation Interface |
|---|---|---|---|
| Tools (Command) | Execute actions | Model control | `IMcpCommandHandler` (C#) / `BaseCommandHandler` (TS) |
| Resources | Provide data | App control | `IMcpResourceHandler` (C#) / `BaseResourceHandler` (TS) |
| Prompts | Templates/workflows | User control | `BasePromptHandler` (TS only) |
## 📚 Built-in Handlers
### HTTP Endpoints (Editor-side, built-in)
| Endpoint | Idempotency | Summary |
|---|---|---|
| `GET /health` | Safe | Version, handler list, uptime |
| `POST /execute_code` | Unsafe | Dynamically compile and execute C# with Roslyn |
| `POST /browse_hierarchy` | Safe | Get scene hierarchy with filtering (limit/offset/fields) |
| `POST /inspect` | read/list: Safe, write: Unsafe | Read/write GameObject/Component properties |
| `POST /capture_screenshot` | Safe | Capture Game/Scene/Editor panel screenshots (inspector/hierarchy/project/console/`window:<title>`) |
| `POST /read_logs` | Safe | Get Console logs (limit/offset/fields/type) |
| `POST /play_mode` | status: Safe, others: Unsafe | Play Mode control (status/play/stop/pause/unpause/step) |
| `GET /resource` | Safe | Assemblies/packages information |
| `POST /command` | per-command | Plugin commands (`menu.execute`, `console.*`) |
### MCP Tools (TS-side, built-in)
`unity_listClients`, `unity_setActiveClient`, `unity_connectToProject`, `unity_getActiveClient`, `unity_execute_code`, `console_getLogs`, `console_getCount`, `console_clear`, `console_setFilter`, `menu_execute`
### MCP Prompts (TS-side, built-in)
- `code_execute`: C# code template for `unity_execute_code`
All tools/endpoints can optionally take a `target` parameter (projectName or clientId) for explicit routing in multi-Editor environments.
## 🛠️ Creating Custom Handlers
### Command Handler (C#)
```csharp
using Newtonsoft.Json.Linq;
using UnityMCP.Editor.Core;
namespace YourNamespace.Handlers
{
internal sealed class YourCommandHandler : IMcpCommandHandler
{
public string CommandPrefix => "yourprefix";
public string Description => "Handler description";
public McpIdempotency Idempotency => McpIdempotency.Safe; // Mark as Unsafe if needed
public JObject Execute(string action, JObject parameters)
{
if (action == "yourAction")
{
return new JObject { ["result"] = "..." };
}
// Automatically promoted to error envelope by response side
return new JObject { ["error"] = $"Unknown action: {action}" };
}
}
}
```
### Command Handler (TypeScript)
```typescript
import { BaseCommandHandler } from "../core/BaseCommandHandler.js";
import { IMcpToolDefinition } from "../core/interfaces/ICommandHandler.js";
import { JObject } from "../types/index.js";
import { z } from "zod";
export class YourCommandHandler extends BaseCommandHandler {
public get commandPrefix(): string { return "yourprefix"; }
public get description(): string { return "Handler description"; }
public getToolDefinitions(): Map<string, IMcpToolDefinition> {
const tools = new Map();
tools.set("yourprefix_yourAction", {
description: "Action description",
parameterSchema: { param1: z.string() }
});
return tools;
}
protected async executeCommand(action: string, parameters: JObject): Promise<JObject> {
return this.sendUnityRequest(`${this.commandPrefix}.${action}`, parameters);
}
}
```
### Prompt Handler (TypeScript)
```typescript
import { BasePromptHandler } from "../core/BasePromptHandler.js";
import { IMcpPromptDefinition } from "../core/interfaces/IPromptHandler.js";
export class YourPromptHandler extends BasePromptHandler {
public get promptName(): string { return "yourprompt"; }
public get description(): string { return "Prompt description"; }
public getPromptDefinitions(): Map<string, IMcpPromptDefinition> {
const prompts = new Map();
prompts.set("your-template", {
description: "Template description",
template: "Please analyze the following code:\n{code}"
});
return prompts;
}
}
```
> 💡 C# handlers can be placed anywhere in the project and will be automatically discovered by `McpHandlerDiscovery`. For TS, place them in `unity-mcp-ts/src/handlers/` for automatic registration by `HandlerDiscovery`.
## ⚙️ Settings
### Unity Editor Settings
Edit > Preferences > Unity MCP:
- **HTTP Port**: Server start port (default 27182, 27182-27199 with first-come-first-served fallback)
- **Auto-start on Launch**: Automatic start on Editor launch
- **UDP Discovery**: Enable UDP broadcast (port 27183, default 30-second interval)
- **Broadcast Interval**: UDP send interval
- **Port Persistence**: Maintain the same port across domain reloads
- **Reload Retry Max MS**: Hint for TS/CLI-side retry limit
- **Detailed Logs**: Debug log output toggle
- **Handler / Resource Enabled States**: Per-handler enablement toggle
> ⚠️ In v2.1, **`Auto-restart on Play Mode Change` was removed**. Play Mode transitions will stop/start the server only if accompanied by a domain reload, and automatically restore via `AssemblyReloadEvents`.
### TypeScript Server Environment Variables
| Variable | Default | Description |
|---|---|---|
| `MCP_RELOAD_RETRY_MAX_MS` | 15000 | Maximum retry time during domain reload (ms) |
| `MCP_UNHEALTHY_COOLDOWN_MS` | 60000 | Cooldown from reloading to unhealthy promotion |
| `MCP_PROJECT_API_PORT` | 27180 | ProjectApi start port (27180-27189 fallback) |
| `MCP_UDP_PORT` | 27183 | UDP announce receive port |
| `MCP_HEALTH_INTERVAL` | 10000 | Health polling interval (ms) |
## 🧪 Testing
- **Unity (EditMode)**: `Editor/Tests/` — 23 cases (ListResponseBuilder / Envelope / Idempotency / ScreenshotCapture)
- **TS (Jest)**: `unity-mcp-ts/src/__tests__/` — 68 cases (UnityConnection / ProjectRegistry / ProjectApi / retry / cache)
```bash
cd unity-mcp-ts
npm test # Jest 68/68 pass expected
```
## 🔍 Troubleshooting
| Symptom | Solution |
|---|---|
| Cannot connect to `/health` | Verify Unity Editor is running, MCP package is imported, and 27182-27199 is listening |
| `target_required` error | Multiple Unity instances running + `target` not specified. Use `unity_setActiveClient` or `target` parameter explicitly |
| Disconnection after domain reload | v2.1 automatically rebinds. Check Unity logs if `SessionState` is not functioning |
| C# handler not registered | Verify Editor assembly is internal/public, implements `IMcpCommandHandler`, and has no compilation errors |
| Node not detected (Mac) | v2.1 falls back to Homebrew path. Use the latest version (#7) |
See detailed error codes in `unity-mcp-ts/README.md` or [Skill api-reference.md](~/.claude/skills/unity-mcp/references/api-reference.md).
## 🔒 Security
- **`/execute_code` can execute arbitrary C# code**. Disable it from McpSettings or restrict listeners to loopback only in environments with public access (v2.x binds to 127.0.0.1 by default).
- **External network not publicly accessible**: HTTP/UDP are limited to loopback only. LAN exposure is not supported.
## 📖 External Resources
- [Model Context Protocol (MCP) specification](https://modelcontextprotocol.io/introduction)
- [unity-mcp-ts README](./unity-mcp-ts/README.md) (TS server details)
- [Unity package README](./jp.shiranui-isuzu.unity-mcp/README.md) (Editor-side details)
- [CHANGELOG](./jp.shiranui-isuzu.unity-mcp/CHANGELOG.md)
## 📄 License
MIT License — See the repository's license file for details.
---
Shiranui-Isuzu
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.