MCP Unity Expert Skill
Complete reference for working with Unity Editor via MCP (Model Context Protocol).
164 tools across 13 categories, integrated chat system, server-side caching.
Version: 1.0.0 | MCP Protocol: 2024-11-05 | Unity: 6000.0+ | Node.js: 18+
1. Architecture Overview
Communication Flow
AI Client (Claude Code, Claude Desktop, etc.)
| MCP via stdio
v
Node.js Bridge (Server~/src/)
| JSON-RPC 2.0 over WebSocket
v
Unity Editor Plugin (Editor/McpServer/)
|
+-- Tool Execution (main thread, queued)
+-- Chat Panel --- Direct HTTP/SSE ---> LLM APIs
Components
| Component |
Language |
Role |
Node.js Bridge (Server~/src/) |
TypeScript |
MCP stdio server, WebSocket client, TTL cache |
Unity Plugin (Editor/McpServer/) |
C# |
WebSocket server, tool execution on main thread |
Chat System (Editor/McpServer/Chat/) |
C# |
Multi-provider LLM chat panel (IMGUI) |
Threading Model
WebSocket messages arrive on background threads. McpBehavior.OnMessage queues them to a
ConcurrentQueue<QueuedMessage>. EditorApplication.update processes up to 10 messages per frame
on the main thread (required for all Unity API calls).
Security
- Path validation: All asset paths must start with
Assets/, .. is blocked (TrySanitizePath)
- WebSocket auth: Optional shared secret via
UNITY_SECRET env var (query parameter on connect)
- Destructive op confirmation: Chat panel shows dialog before dangerous operations
- API keys: Stored in
EditorPrefs (never committed to version control)
- OAuth PKCE: Supported for Anthropic (browser-based flow with auto-refresh)
2. Setup & Configuration
Installation
# Option A: Unity Package Manager (Git URL)
# Window > Package Manager > + > Add package from git URL:
https://github.com/JulianKerignard/mcp-unity.git
# Option B: Local — copy to Packages/com.juliank.mcp-unity/
# Build the bridge
cd Packages/com.juliank.mcp-unity/Server~/
npm install && npm run build
Client Configuration
Claude Code CLI:
claude mcp add mcp-unity -- node /absolute/path/to/Server~/build/index.js
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json macOS):
{
"mcpServers": {
"mcp-unity": {
"command": "node",
"args": ["/absolute/path/to/Server~/build/index.js"],
"env": { "UNITY_PORT": "8090" }
}
}
}
Cursor / Windsurf / other MCP clients: Same config format as Claude Desktop.
Environment Variables
| Variable |
Default |
Description |
UNITY_HOST |
localhost |
Unity WebSocket host |
UNITY_PORT |
8090 |
Unity WebSocket port |
UNITY_SECRET |
— |
Shared secret for WebSocket auth |
DEBUG |
false |
Debug logging (true or 1) |
REQUEST_TIMEOUT |
10000 |
Request timeout (ms) |
RECONNECT_INTERVAL |
3000 |
Reconnect interval (ms) |
MAX_RECONNECT_ATTEMPTS |
3 |
Max reconnection attempts |
McpSettings (Unity-side)
Stored in ProjectSettings/McpUnitySettings.json, auto-saved.
| Setting |
Default |
Description |
| Port |
8090 |
WebSocket server port |
| AutoStartServer |
true |
Start on Editor load |
| ShowNotifications |
true |
Notification popups |
| RequestTimeoutMs |
30000 |
Request timeout |
| LogToConsole |
true |
Mirror logs to Console |
| LogToFile |
false |
Write logs to file |
| MinimumLogLevel |
Info |
Log level filter |
| MaxLogEntries |
500 |
Log buffer size |
| UseCustomServerPath |
false |
Custom bridge path toggle |
| CustomServerPath |
— |
Path to custom index.js |
Starting the Server
In Unity: Tools > MCP Unity > Server Window → click Start Server.
Status indicator turns green when ready. The Setup Wizard (Tools > MCP Unity > Setup Wizard)
guides through initial setup (Node.js check, build, config generation).
3. Tool Categories & Usage
Dynamic Loading (Token Optimization)
MCP Unity uses category-based dynamic loading:
- 47 core tools (incl. 2 meta-tools) always available
- 117 additional tools loaded on demand per category
- Use
unity_list_tool_categories to discover categories
- Use
unity_enable_tool_category to load a category
Meta-Tools
| Tool |
Description |
unity_list_tool_categories |
List categories with status and tool counts |
unity_enable_tool_category |
Enable/disable a category (asset, material, ui, animator, terrain, physics, audio, rendering, build, settings, input, advanced) |
13 Categories Summary
| Category |
Tools |
Always Loaded |
Key Tools |
| Core |
45 |
Yes |
get_editor_state, list_gameobjects, create_gameobject, modify_component_batch |
| Asset |
16 |
No |
search_assets, instantiate_prefab, create_prefab, set_import_settings |
| Material |
3 |
No |
get_material, set_material, create_material |
| UI |
9 |
No |
create_canvas, create_ui_element, set_rect_transform, add_layout_group |
| Animator |
23 |
No |
create_animator_controller, add_animator_state, create_blend_tree |
| Terrain |
17 |
No |
create_terrain, set_terrain_heights_batch, paint_terrain_texture_batch |
| Physics |
8 |
No |
raycast, setup_rigidbody, setup_collider, bake_navmesh |
| Audio |
3 |
No |
setup_audio_source, create_audio_mixer, get_audio_mixer |
| Rendering |
13 |
No |
configure_camera, bake_lighting, set_lightmap_settings |
| Build |
6 |
No |
get_build_settings, switch_platform, add_package |
| Settings |
11 |
No |
set_project_settings, set_quality_level, create_tag, create_layer |
| Input |
3 |
No |
get_input_actions, add_input_action, add_input_binding |
| Advanced |
5 |
No |
set_reference, create_scriptable_object, modify_scriptable_object |
Full tool reference: references/tool-reference-complete.md
Essential Workflows
Session Start (always do this first):
1. unity_get_editor_state → check play mode, compilation status
2. unity_get_project_overview → render pipeline, assets, scenes, packages
3. unity_list_gameobjects (tree mode) → scene hierarchy overview
Scene Modification:
1. unity_list_gameobjects { outputMode: "tree" } → see hierarchy
2. unity_get_component { gameObjectPath, componentType } → inspect
3. unity_modify_component_batch { modifications: [...] } → change (batch!)
4. unity_save_scene → persist
Create Multiple Objects:
unity_create_gameobject_batch {
objects: [
{ name: "Floor", primitiveType: "Plane", position: {x:0,y:0,z:0}, scale: {x:10,y:1,z:10} },
{ name: "Player", primitiveType: "Capsule", position: {x:0,y:1,z:0},
components: [{ type: "Rigidbody" }] },
{ name: "Light", primitiveType: "Empty", position: {x:0,y:3,z:0},
components: [{ type: "Light", properties: { type: 1, intensity: 1.5 } }] }
]
}
Script Workflow:
1. unity_create_script { scriptName, savePath, scriptType, methods }
OR unity_write_script { filePath, content }
2. unity_refresh_and_compile → trigger domain reload
3. unity_add_component { gameObjectPath, componentType: "YourScript" }
Prefab Workflow:
1. Build a GameObject in scene (create + configure)
2. unity_create_prefab { gameObjectPath, savePath }
3. unity_instantiate_prefab { prefabPath, position }
4. Modify instance → unity_apply_prefab_overrides { gameObjectPath }
Batch Operations
Always prefer batch tools over individual calls:
unity_create_gameobject_batch — create 2+ objects in one call, single Undo
unity_modify_component_batch — modify components on multiple objects at once
unity_set_terrain_heights_batch — sculpt entire terrain regions
unity_paint_terrain_texture_batch — paint textures on regions
Resources (Read-Only, No Tool Call Needed)
| URI |
Type |
Content |
unity://project/settings |
JSON |
Project name, version, platform, backend |
unity://scene/hierarchy |
JSON |
Current scene root objects with components |
unity://console/logs |
JSON |
Recent console log entries |
workflows://core |
Markdown |
Core workflow guide + token tips |
workflows://animator |
Markdown |
Animator Controller workflow |
workflows://materials |
Markdown |
Materials + shader workflow |
workflows://prefabs |
Markdown |
Prefab creation/instantiation workflow |
workflows://assets |
Markdown |
Asset search syntax + browser workflow |
workflows://terrain |
Markdown |
Terrain sculpting, painting, brush guide |
4. Performance Optimization
Token Reduction Rules
| Rule |
Savings |
How |
Use outputMode='tree' for lists |
~90% |
unity_list_gameobjects { outputMode: "tree" } |
| Never return base64 screenshots |
~95% |
unity_take_screenshot { returnBase64: false } → file saved, use Read tool |
Use size='small' for previews |
~75% |
unity_get_asset_preview { size: "small", format: "jpg", jpgQuality: 50 } |
| Limit search results |
variable |
unity_search_assets { maxResults: 20 } |
| Keep tool categories disabled |
~70% schema |
Only enable categories you need |
| Use batch operations |
~50% overhead |
One call vs multiple round-trips |
Screenshot Workflow (Token-Safe)
// Step 1: Capture to file (NO base64)
unity_take_screenshot {
view: "Scene",
returnBase64: false,
format: "jpg",
jpgQuality: 60,
width: 640,
height: 360
}
// Returns { savedPath: "Assets/Screenshots/..." }
// Step 2: View with Read tool if needed
Read { file_path: "Assets/Screenshots/screenshot.jpg" }
Asset Preview Workflow
// Step 1: Small preview, jpg format
unity_get_asset_preview {
assetPath: "Assets/Models/Character.fbx",
size: "small", // tiny(32), small(64), medium(128)
format: "jpg",
jpgQuality: 50
}
// Returns savedPath in Assets/Screenshots/
// Step 2: Read if needed
Read { file_path: savedPath }
Cache System
The Node.js bridge caches read-only results with TTL:
| Category |
TTL |
Cached Tools |
editorState |
5s |
get_editor_state |
hierarchy |
30s |
list_gameobjects, get_gameobject |
components |
1 min |
get_component, get_material, get_script_info, memory_* |
assets |
5 min |
search_assets, get_asset_info, list_folders, read_script |
scenes |
5 min |
get_scene_info, list_scenes, get_build_settings, get_render_pipeline_info |
Write operations auto-invalidate relevant cache entries. Max 500 cached entries.
Cleanup runs every 60 seconds.
Full invalidation map: references/cache-invalidation-map.md
Common Component Names
Use exact type names (no namespace prefix needed):
- Transform: always present, never add — use
unity_set_transform
- Physics:
Rigidbody, BoxCollider, SphereCollider, CapsuleCollider, MeshCollider
- Rendering:
MeshRenderer, MeshFilter, Light, Camera
- Audio:
AudioSource, AudioListener
- Animation:
Animator
- UI:
Canvas, CanvasScaler, GraphicRaycaster, Image, Text
Material Property Names
All material properties start with underscore (_):
- Standard/Built-in:
_Color, _MainTex, _Metallic, _Glossiness, _BumpMap, _EmissionColor
- URP/Lit:
_BaseColor, _BaseMap, _Metallic, _Smoothness
- System auto-detects render pipeline. "Standard" maps to "Universal Render Pipeline/Lit" in URP.
5. Chat Panel
Overview
The integrated chat panel runs inside Unity Editor (IMGUI). It calls tools directly via
McpToolRegistry — no Node.js bridge needed.
9 Provider Presets
| Provider |
Models |
Context |
Auth |
Local |
| Anthropic Claude |
Sonnet 4.6, Opus 4.6, Haiku 4.5, Sonnet 4.5 |
200K |
API Key / OAuth PKCE |
No |
| OpenAI |
GPT-4o, GPT-4o Mini, o3 Mini, GPT-4.1, 4.1 Mini, 4.1 Nano |
128K |
API Key |
No |
| Google Gemini |
2.5 Pro, 2.5 Flash, 2.0 Flash |
1M |
API Key |
No |
| DeepSeek |
Chat V3.2, Reasoner R1 |
128K |
API Key |
No |
| Groq |
Llama 3.3 70B, Llama 3.1 8B, Llama 4 Maverick, Qwen3 32B |
131K |
API Key |
No |
| Mistral AI |
Large 3, Small 3.2, Codestral, Magistral Medium |
128K |
API Key |
No |
| Ollama |
Llama 3.3, Qwen3, Qwen 2.5 Coder, DeepSeek R1, Gemma 3 |
131K |
None |
Yes |
| LM Studio |
Any local model |
131K |
None |
Yes |
| Custom |
Any OpenAI-compatible endpoint |
128K |
API Key |
— |
Full provider details: references/provider-configs.md
Tool Execution Loop
- AI response arrives via SSE streaming
- Parser detects
tool_use content blocks
- Each tool executed on main thread via
McpToolRegistry
- Results added to conversation → follow-up request
- Loop continues until no tool calls or max 10 iterations
Destructive Operation Confirmation
These tools trigger a confirmation dialog in chat before execution:
- Destructive:
delete_gameobject, delete_asset, clear_baked_data, clear_navmesh, clear_occlusion, remove_terrain_trees, remove_terrain_detail
- Scripts:
write_script, create_script, update_script
- Dangerous:
execute_menu_item, unpack_prefab
- Long/Irreversible:
switch_platform, bake_lighting, bake_lighting_async, bake_navmesh, bake_occlusion
User denial returns "Operation denied by user" error; AI continues without that op.
Features
- Drag & drop: Drag assets/GameObjects into input →
@Name mention + full context on send
- Export: Markdown, JSON, Plain Text, or clipboard (toolbar
⇩ button)
- Context bar: Shows token usage vs. model context window
- Markdown rendering: Code blocks, headers, tables, blockquotes, links, lists
EditorPrefs Keys
Per-provider settings stored in EditorPrefs:
McpUnity_ActiveProvider — active provider ID
McpUnity_ProviderKey_{id} — API key
McpUnity_ProviderModel_{id} — selected model
McpUnity_ProviderMaxTokens_{id} — max tokens
McpUnity_ProviderEndpoint_{id} — custom endpoint
McpUnity_ProviderTemp_{id} — temperature
6. Troubleshooting
Connection Issues
| Problem |
Solution |
| Bridge won't connect |
Ensure Unity running + MCP server started (green indicator) |
| Port already in use |
Change port in Settings tab → Server Settings |
| Tools return "not connected" |
Bridge connects async — wait a few seconds after Editor starts |
| WebSocket timeout |
Increase REQUEST_TIMEOUT env var (default 10s) |
| Node.js not found |
Run Setup Wizard: Tools > MCP Unity > Setup Wizard |
Tool Issues
| Problem |
Solution |
GameObject not found: X |
Use unity_list_gameobjects to verify path; tool searches inactive too |
Required parameter 'X' is missing |
Check tool's inputSchema.required fields |
Tool 'X' category 'Y' not enabled |
Call unity_enable_tool_category with category name |
Invalid asset path |
Paths must start with Assets/, no .. allowed |
JsonUtility returns {} |
Use JsonHelper.ToJson() for Dictionary serialization |
Performance Issues
| Problem |
Solution |
| Compilation errors after edit |
unity_refresh_and_compile to trigger domain reload |
| Cache returns stale data |
Verify tool is in cacheInvalidators in cache.ts |
| Context fills too fast |
Disable unused tool categories; use outputMode='tree'; avoid base64 |
| Slow tool responses |
Check request monitor in Diagnostics tab for bottlenecks |
Chat Issues
| Problem |
Solution |
| "No API key" |
Enter key in Settings → Provider Settings |
| Tool not in chat |
Check Settings → Tool Categories (may be disabled) |
| Streaming stops |
Check network; press Escape then retry; context may be full |
| OAuth login fails |
Ensure browser reaches Anthropic auth; disable popup blockers |
| Drag & drop fails |
Drop on input field area, not message area |
7. Advanced Patterns
Custom Tool Development
Full guide: references/custom-tool-guide.md
Quick summary:
- C#: Register in
Editor/McpServer/Tools/ (partial class, McpToolDefinition)
- TypeScript: Add to
Server~/src/tools.ts with defer_loading: true
- Cache: Add invalidation in
Server~/src/cache.ts if tool writes state
- Build:
npm run build in Server~/
Conventions
| Rule |
Detail |
| Tool naming |
unity_ prefix + snake_case |
| Required args |
RequireArg(args, "key") → (value, error) |
| Find GameObject |
RequireGameObject(args, "key") → (go, path, error) |
| Path security |
TrySanitizePath(raw, "label") → blocks .., enforces Assets/ |
| Serialization |
JsonHelper.ToJson() — never JsonUtility.ToJson() on Dictionaries |
| Response |
McpResponse.Success(data) or McpToolResult.Error(message) |
| Descriptions |
Keep under 80 chars (token budget: ~1200 total for all descriptions) |
Key Source Files
Editor/McpServer/
├── McpUnityServer.cs # Main partial class — lifecycle, queue, helpers
├── McpJsonRpc.cs # JSON-RPC 2.0 dispatcher + JSON parser
├── McpToolRegistry.cs # Tool registration, categories, execution
├── McpResourceRegistry.cs # Resource registration
├── McpProtocol.cs # Protocol data classes
├── McpSettings.cs # Persistent settings + shared secret
├── Tools/ # 164 tool implementations (43 files, partial classes)
├── Chat/ # AI chat panel (McpChatWindow, ApiClient, OAuth)
├── Helpers/ # ArgumentParser, ColorParser, GameObjectHelpers
├── Models/ # LogEntry, QueuedMessage, MemoryCacheData
└── Utils/ # McpConstants, PathValidator, TypeConverter
Server~/src/
├── index.ts # MCP stdio server, request handlers
├── UnityBridge.ts # WebSocket client + secret auth + reconnect
├── tools.ts # 47 core tool definitions (meta + core)
├── resources.ts # Resource definitions + workflow docs
├── cache.ts # TTL cache + invalidation map
└── types.ts # Zod schemas, error codes, BridgeConfig
Editor Window Tabs
| Tab |
Content |
| Chat |
Multi-provider LLM chat with SSE streaming, tool execution, drag & drop |
| Settings |
Provider config, tool categories, server settings, advanced options |
| Diagnostics |
Request monitor, logs (color-coded), Claude config generator |
| Toolbar |
Scene view overlay with server status + start/stop button |
1---2name: mcp-unity3description: MCP Unity Expert Skill4---5# MCP Unity Expert Skill67> Complete reference for working with Unity Editor via MCP (Model Context Protocol).8> 164 tools across 13 categories, integrated chat system, server-side caching.910**Version**: 1.0.0 | **MCP Protocol**: 2024-11-05 | **Unity**: 6000.0+ | **Node.js**: 18+1112---1314## 1. Architecture Overview1516### Communication Flow1718```19AI Client (Claude Code, Claude Desktop, etc.)20 | MCP via stdio21 v22Node.js Bridge (Server~/src/)23 | JSON-RPC 2.0 over WebSocket24 v25Unity Editor Plugin (Editor/McpServer/)26 |27 +-- Tool Execution (main thread, queued)28 +-- Chat Panel --- Direct HTTP/SSE ---> LLM APIs29```3031### Components3233| Component | Language | Role |34|-----------|----------|------|35| **Node.js Bridge** (`Server~/src/`) | TypeScript | MCP stdio server, WebSocket client, TTL cache |36| **Unity Plugin** (`Editor/McpServer/`) | C# | WebSocket server, tool execution on main thread |37| **Chat System** (`Editor/McpServer/Chat/`) | C# | Multi-provider LLM chat panel (IMGUI) |3839### Threading Model4041WebSocket messages arrive on background threads. `McpBehavior.OnMessage` queues them to a42`ConcurrentQueue<QueuedMessage>`. `EditorApplication.update` processes up to **10 messages per frame**43on the main thread (required for all Unity API calls).4445### Security4647- **Path validation**: All asset paths must start with `Assets/`, `..` is blocked (`TrySanitizePath`)48- **WebSocket auth**: Optional shared secret via `UNITY_SECRET` env var (query parameter on connect)49- **Destructive op confirmation**: Chat panel shows dialog before dangerous operations50- **API keys**: Stored in `EditorPrefs` (never committed to version control)51- **OAuth PKCE**: Supported for Anthropic (browser-based flow with auto-refresh)5253---5455## 2. Setup & Configuration5657### Installation5859```bash60# Option A: Unity Package Manager (Git URL)61# Window > Package Manager > + > Add package from git URL:62https://github.com/JulianKerignard/mcp-unity.git6364# Option B: Local — copy to Packages/com.juliank.mcp-unity/6566# Build the bridge67cd Packages/com.juliank.mcp-unity/Server~/68npm install && npm run build69```7071### Client Configuration7273**Claude Code CLI:**74```bash75claude mcp add mcp-unity -- node /absolute/path/to/Server~/build/index.js76```7778**Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json` macOS):79```json80{81 "mcpServers": {82 "mcp-unity": {83 "command": "node",84 "args": ["/absolute/path/to/Server~/build/index.js"],85 "env": { "UNITY_PORT": "8090" }86 }87 }88}89```9091**Cursor / Windsurf / other MCP clients**: Same config format as Claude Desktop.9293### Environment Variables9495| Variable | Default | Description |96|----------|---------|-------------|97| `UNITY_HOST` | `localhost` | Unity WebSocket host |98| `UNITY_PORT` | `8090` | Unity WebSocket port |99| `UNITY_SECRET` | — | Shared secret for WebSocket auth |100| `DEBUG` | `false` | Debug logging (`true` or `1`) |101| `REQUEST_TIMEOUT` | `10000` | Request timeout (ms) |102| `RECONNECT_INTERVAL` | `3000` | Reconnect interval (ms) |103| `MAX_RECONNECT_ATTEMPTS` | `3` | Max reconnection attempts |104105### McpSettings (Unity-side)106107Stored in `ProjectSettings/McpUnitySettings.json`, auto-saved.108109| Setting | Default | Description |110|---------|---------|-------------|111| Port | 8090 | WebSocket server port |112| AutoStartServer | true | Start on Editor load |113| ShowNotifications | true | Notification popups |114| RequestTimeoutMs | 30000 | Request timeout |115| LogToConsole | true | Mirror logs to Console |116| LogToFile | false | Write logs to file |117| MinimumLogLevel | Info | Log level filter |118| MaxLogEntries | 500 | Log buffer size |119| UseCustomServerPath | false | Custom bridge path toggle |120| CustomServerPath | — | Path to custom `index.js` |121122### Starting the Server123124In Unity: **Tools > MCP Unity > Server Window** → click **Start Server**.125Status indicator turns **green** when ready. The Setup Wizard (`Tools > MCP Unity > Setup Wizard`)126guides through initial setup (Node.js check, build, config generation).127128---129130## 3. Tool Categories & Usage131132### Dynamic Loading (Token Optimization)133134MCP Unity uses **category-based dynamic loading**:135- **47 core tools** (incl. 2 meta-tools) always available136- **117 additional tools** loaded on demand per category137- Use `unity_list_tool_categories` to discover categories138- Use `unity_enable_tool_category` to load a category139140### Meta-Tools141142| Tool | Description |143|------|-------------|144| `unity_list_tool_categories` | List categories with status and tool counts |145| `unity_enable_tool_category` | Enable/disable a category (asset, material, ui, animator, terrain, physics, audio, rendering, build, settings, input, advanced) |146147### 13 Categories Summary148149| Category | Tools | Always Loaded | Key Tools |150|----------|-------|---------------|-----------|151| **Core** | 45 | Yes | `get_editor_state`, `list_gameobjects`, `create_gameobject`, `modify_component_batch` |152| **Asset** | 16 | No | `search_assets`, `instantiate_prefab`, `create_prefab`, `set_import_settings` |153| **Material** | 3 | No | `get_material`, `set_material`, `create_material` |154| **UI** | 9 | No | `create_canvas`, `create_ui_element`, `set_rect_transform`, `add_layout_group` |155| **Animator** | 23 | No | `create_animator_controller`, `add_animator_state`, `create_blend_tree` |156| **Terrain** | 17 | No | `create_terrain`, `set_terrain_heights_batch`, `paint_terrain_texture_batch` |157| **Physics** | 8 | No | `raycast`, `setup_rigidbody`, `setup_collider`, `bake_navmesh` |158| **Audio** | 3 | No | `setup_audio_source`, `create_audio_mixer`, `get_audio_mixer` |159| **Rendering** | 13 | No | `configure_camera`, `bake_lighting`, `set_lightmap_settings` |160| **Build** | 6 | No | `get_build_settings`, `switch_platform`, `add_package` |161| **Settings** | 11 | No | `set_project_settings`, `set_quality_level`, `create_tag`, `create_layer` |162| **Input** | 3 | No | `get_input_actions`, `add_input_action`, `add_input_binding` |163| **Advanced** | 5 | No | `set_reference`, `create_scriptable_object`, `modify_scriptable_object` |164165> Full tool reference: [references/tool-reference-complete.md](references/tool-reference-complete.md)166167### Essential Workflows168169**Session Start (always do this first):**170```1711. unity_get_editor_state → check play mode, compilation status1722. unity_get_project_overview → render pipeline, assets, scenes, packages1733. unity_list_gameobjects (tree mode) → scene hierarchy overview174```175176**Scene Modification:**177```1781. unity_list_gameobjects { outputMode: "tree" } → see hierarchy1792. unity_get_component { gameObjectPath, componentType } → inspect1803. unity_modify_component_batch { modifications: [...] } → change (batch!)1814. unity_save_scene → persist182```183184**Create Multiple Objects:**185```186unity_create_gameobject_batch {187 objects: [188 { name: "Floor", primitiveType: "Plane", position: {x:0,y:0,z:0}, scale: {x:10,y:1,z:10} },189 { name: "Player", primitiveType: "Capsule", position: {x:0,y:1,z:0},190 components: [{ type: "Rigidbody" }] },191 { name: "Light", primitiveType: "Empty", position: {x:0,y:3,z:0},192 components: [{ type: "Light", properties: { type: 1, intensity: 1.5 } }] }193 ]194}195```196197**Script Workflow:**198```1991. unity_create_script { scriptName, savePath, scriptType, methods }200 OR unity_write_script { filePath, content }2012. unity_refresh_and_compile → trigger domain reload2023. unity_add_component { gameObjectPath, componentType: "YourScript" }203```204205**Prefab Workflow:**206```2071. Build a GameObject in scene (create + configure)2082. unity_create_prefab { gameObjectPath, savePath }2093. unity_instantiate_prefab { prefabPath, position }2104. Modify instance → unity_apply_prefab_overrides { gameObjectPath }211```212213### Batch Operations214215Always prefer batch tools over individual calls:216- `unity_create_gameobject_batch` — create 2+ objects in one call, single Undo217- `unity_modify_component_batch` — modify components on multiple objects at once218- `unity_set_terrain_heights_batch` — sculpt entire terrain regions219- `unity_paint_terrain_texture_batch` — paint textures on regions220221### Resources (Read-Only, No Tool Call Needed)222223| URI | Type | Content |224|-----|------|---------|225| `unity://project/settings` | JSON | Project name, version, platform, backend |226| `unity://scene/hierarchy` | JSON | Current scene root objects with components |227| `unity://console/logs` | JSON | Recent console log entries |228| `workflows://core` | Markdown | Core workflow guide + token tips |229| `workflows://animator` | Markdown | Animator Controller workflow |230| `workflows://materials` | Markdown | Materials + shader workflow |231| `workflows://prefabs` | Markdown | Prefab creation/instantiation workflow |232| `workflows://assets` | Markdown | Asset search syntax + browser workflow |233| `workflows://terrain` | Markdown | Terrain sculpting, painting, brush guide |234235---236237## 4. Performance Optimization238239### Token Reduction Rules240241| Rule | Savings | How |242|------|---------|-----|243| Use `outputMode='tree'` for lists | ~90% | `unity_list_gameobjects { outputMode: "tree" }` |244| Never return base64 screenshots | ~95% | `unity_take_screenshot { returnBase64: false }` → file saved, use Read tool |245| Use `size='small'` for previews | ~75% | `unity_get_asset_preview { size: "small", format: "jpg", jpgQuality: 50 }` |246| Limit search results | variable | `unity_search_assets { maxResults: 20 }` |247| Keep tool categories disabled | ~70% schema | Only enable categories you need |248| Use batch operations | ~50% overhead | One call vs multiple round-trips |249250### Screenshot Workflow (Token-Safe)251252```javascript253// Step 1: Capture to file (NO base64)254unity_take_screenshot {255 view: "Scene",256 returnBase64: false,257 format: "jpg",258 jpgQuality: 60,259 width: 640,260 height: 360261}262// Returns { savedPath: "Assets/Screenshots/..." }263264// Step 2: View with Read tool if needed265Read { file_path: "Assets/Screenshots/screenshot.jpg" }266```267268### Asset Preview Workflow269270```javascript271// Step 1: Small preview, jpg format272unity_get_asset_preview {273 assetPath: "Assets/Models/Character.fbx",274 size: "small", // tiny(32), small(64), medium(128)275 format: "jpg",276 jpgQuality: 50277}278// Returns savedPath in Assets/Screenshots/279280// Step 2: Read if needed281Read { file_path: savedPath }282```283284### Cache System285286The Node.js bridge caches read-only results with TTL:287288| Category | TTL | Cached Tools |289|----------|-----|--------------|290| `editorState` | 5s | `get_editor_state` |291| `hierarchy` | 30s | `list_gameobjects`, `get_gameobject` |292| `components` | 1 min | `get_component`, `get_material`, `get_script_info`, `memory_*` |293| `assets` | 5 min | `search_assets`, `get_asset_info`, `list_folders`, `read_script` |294| `scenes` | 5 min | `get_scene_info`, `list_scenes`, `get_build_settings`, `get_render_pipeline_info` |295296Write operations auto-invalidate relevant cache entries. Max 500 cached entries.297Cleanup runs every 60 seconds.298299> Full invalidation map: [references/cache-invalidation-map.md](references/cache-invalidation-map.md)300301### Common Component Names302303Use exact type names (no namespace prefix needed):304- **Transform**: always present, never add — use `unity_set_transform`305- **Physics**: `Rigidbody`, `BoxCollider`, `SphereCollider`, `CapsuleCollider`, `MeshCollider`306- **Rendering**: `MeshRenderer`, `MeshFilter`, `Light`, `Camera`307- **Audio**: `AudioSource`, `AudioListener`308- **Animation**: `Animator`309- **UI**: `Canvas`, `CanvasScaler`, `GraphicRaycaster`, `Image`, `Text`310311### Material Property Names312313All material properties start with underscore (`_`):314- **Standard/Built-in**: `_Color`, `_MainTex`, `_Metallic`, `_Glossiness`, `_BumpMap`, `_EmissionColor`315- **URP/Lit**: `_BaseColor`, `_BaseMap`, `_Metallic`, `_Smoothness`316- System auto-detects render pipeline. "Standard" maps to "Universal Render Pipeline/Lit" in URP.317318---319320## 5. Chat Panel321322### Overview323324The integrated chat panel runs inside Unity Editor (IMGUI). It calls tools directly via325`McpToolRegistry` — no Node.js bridge needed.326327### 9 Provider Presets328329| Provider | Models | Context | Auth | Local |330|----------|--------|---------|------|-------|331| **Anthropic Claude** | Sonnet 4.6, Opus 4.6, Haiku 4.5, Sonnet 4.5 | 200K | API Key / OAuth PKCE | No |332| **OpenAI** | GPT-4o, GPT-4o Mini, o3 Mini, GPT-4.1, 4.1 Mini, 4.1 Nano | 128K | API Key | No |333| **Google Gemini** | 2.5 Pro, 2.5 Flash, 2.0 Flash | 1M | API Key | No |334| **DeepSeek** | Chat V3.2, Reasoner R1 | 128K | API Key | No |335| **Groq** | Llama 3.3 70B, Llama 3.1 8B, Llama 4 Maverick, Qwen3 32B | 131K | API Key | No |336| **Mistral AI** | Large 3, Small 3.2, Codestral, Magistral Medium | 128K | API Key | No |337| **Ollama** | Llama 3.3, Qwen3, Qwen 2.5 Coder, DeepSeek R1, Gemma 3 | 131K | None | Yes |338| **LM Studio** | Any local model | 131K | None | Yes |339| **Custom** | Any OpenAI-compatible endpoint | 128K | API Key | — |340341> Full provider details: [references/provider-configs.md](references/provider-configs.md)342343### Tool Execution Loop3443451. AI response arrives via SSE streaming3462. Parser detects `tool_use` content blocks3473. Each tool executed on main thread via `McpToolRegistry`3484. Results added to conversation → follow-up request3495. Loop continues until no tool calls or max 10 iterations350351### Destructive Operation Confirmation352353These tools trigger a confirmation dialog in chat before execution:354355- **Destructive**: `delete_gameobject`, `delete_asset`, `clear_baked_data`, `clear_navmesh`, `clear_occlusion`, `remove_terrain_trees`, `remove_terrain_detail`356- **Scripts**: `write_script`, `create_script`, `update_script`357- **Dangerous**: `execute_menu_item`, `unpack_prefab`358- **Long/Irreversible**: `switch_platform`, `bake_lighting`, `bake_lighting_async`, `bake_navmesh`, `bake_occlusion`359360User denial returns "Operation denied by user" error; AI continues without that op.361362### Features363364- **Drag & drop**: Drag assets/GameObjects into input → `@Name` mention + full context on send365- **Export**: Markdown, JSON, Plain Text, or clipboard (toolbar `⇩` button)366- **Context bar**: Shows token usage vs. model context window367- **Markdown rendering**: Code blocks, headers, tables, blockquotes, links, lists368369### EditorPrefs Keys370371Per-provider settings stored in `EditorPrefs`:372- `McpUnity_ActiveProvider` — active provider ID373- `McpUnity_ProviderKey_{id}` — API key374- `McpUnity_ProviderModel_{id}` — selected model375- `McpUnity_ProviderMaxTokens_{id}` — max tokens376- `McpUnity_ProviderEndpoint_{id}` — custom endpoint377- `McpUnity_ProviderTemp_{id}` — temperature378379---380381## 6. Troubleshooting382383### Connection Issues384385| Problem | Solution |386|---------|----------|387| Bridge won't connect | Ensure Unity running + MCP server started (green indicator) |388| Port already in use | Change port in Settings tab → Server Settings |389| Tools return "not connected" | Bridge connects async — wait a few seconds after Editor starts |390| WebSocket timeout | Increase `REQUEST_TIMEOUT` env var (default 10s) |391| Node.js not found | Run Setup Wizard: Tools > MCP Unity > Setup Wizard |392393### Tool Issues394395| Problem | Solution |396|---------|----------|397| `GameObject not found: X` | Use `unity_list_gameobjects` to verify path; tool searches inactive too |398| `Required parameter 'X' is missing` | Check tool's `inputSchema.required` fields |399| `Tool 'X' category 'Y' not enabled` | Call `unity_enable_tool_category` with category name |400| `Invalid asset path` | Paths must start with `Assets/`, no `..` allowed |401| `JsonUtility` returns `{}` | Use `JsonHelper.ToJson()` for Dictionary serialization |402403### Performance Issues404405| Problem | Solution |406|---------|----------|407| Compilation errors after edit | `unity_refresh_and_compile` to trigger domain reload |408| Cache returns stale data | Verify tool is in `cacheInvalidators` in `cache.ts` |409| Context fills too fast | Disable unused tool categories; use `outputMode='tree'`; avoid base64 |410| Slow tool responses | Check request monitor in Diagnostics tab for bottlenecks |411412### Chat Issues413414| Problem | Solution |415|---------|----------|416| "No API key" | Enter key in Settings → Provider Settings |417| Tool not in chat | Check Settings → Tool Categories (may be disabled) |418| Streaming stops | Check network; press Escape then retry; context may be full |419| OAuth login fails | Ensure browser reaches Anthropic auth; disable popup blockers |420| Drag & drop fails | Drop on input field area, not message area |421422---423424## 7. Advanced Patterns425426### Custom Tool Development427428> Full guide: [references/custom-tool-guide.md](references/custom-tool-guide.md)429430Quick summary:4311. **C#**: Register in `Editor/McpServer/Tools/` (partial class, `McpToolDefinition`)4322. **TypeScript**: Add to `Server~/src/tools.ts` with `defer_loading: true`4333. **Cache**: Add invalidation in `Server~/src/cache.ts` if tool writes state4344. **Build**: `npm run build` in `Server~/`435436### Conventions437438| Rule | Detail |439|------|--------|440| Tool naming | `unity_` prefix + `snake_case` |441| Required args | `RequireArg(args, "key")` → `(value, error)` |442| Find GameObject | `RequireGameObject(args, "key")` → `(go, path, error)` |443| Path security | `TrySanitizePath(raw, "label")` → blocks `..`, enforces `Assets/` |444| Serialization | `JsonHelper.ToJson()` — never `JsonUtility.ToJson()` on Dictionaries |445| Response | `McpResponse.Success(data)` or `McpToolResult.Error(message)` |446| Descriptions | Keep under 80 chars (token budget: ~1200 total for all descriptions) |447448### Key Source Files449450```451Editor/McpServer/452├── McpUnityServer.cs # Main partial class — lifecycle, queue, helpers453├── McpJsonRpc.cs # JSON-RPC 2.0 dispatcher + JSON parser454├── McpToolRegistry.cs # Tool registration, categories, execution455├── McpResourceRegistry.cs # Resource registration456├── McpProtocol.cs # Protocol data classes457├── McpSettings.cs # Persistent settings + shared secret458├── Tools/ # 164 tool implementations (43 files, partial classes)459├── Chat/ # AI chat panel (McpChatWindow, ApiClient, OAuth)460├── Helpers/ # ArgumentParser, ColorParser, GameObjectHelpers461├── Models/ # LogEntry, QueuedMessage, MemoryCacheData462└── Utils/ # McpConstants, PathValidator, TypeConverter463464Server~/src/465├── index.ts # MCP stdio server, request handlers466├── UnityBridge.ts # WebSocket client + secret auth + reconnect467├── tools.ts # 47 core tool definitions (meta + core)468├── resources.ts # Resource definitions + workflow docs469├── cache.ts # TTL cache + invalidation map470└── types.ts # Zod schemas, error codes, BridgeConfig471```472473### Editor Window Tabs474475| Tab | Content |476|-----|---------|477| **Chat** | Multi-provider LLM chat with SSE streaming, tool execution, drag & drop |478| **Settings** | Provider config, tool categories, server settings, advanced options |479| **Diagnostics** | Request monitor, logs (color-coded), Claude config generator |480| **Toolbar** | Scene view overlay with server status + start/stop button |