Skip to main content
Glama
README.md
# Unity MCP Server

A Model Context Protocol (MCP) server plugin for Unity Editor that exposes project context to AI coding agents like Claude, Cursor, Copilot, and others.

## Features

### Read Operations
- **Full Scene Hierarchy Access**: Query GameObjects, their components, and properties
- **Component Inspection**: Read all serialized fields with values, types, and tooltips
- **Script Analysis**: List and read MonoBehaviour/ScriptableObject scripts with field and method information
- **Project Settings**: Access PlayerSettings, QualitySettings, Physics, Tags/Layers, Input, Graphics, and Build settings
- **Asset Database**: Search and query assets by type, folder, or name with type-specific metadata
- **Asset Dependencies**: Inspect dependency graphs for any asset
- **Folder Structure**: Browse the project folder hierarchy
- **Package Manager**: List all installed UPM packages
- **Animation Inspection**: Read animation clips (curves, keyframes, events) and animator controllers (layers, states, transitions, parameters)
- **Project Info**: Query runtime project information (product name, Unity version, platform, etc.)

### Write Operations (Opt-in)
- **GameObject Manipulation**: Create, delete, rename, move, duplicate GameObjects
- **Component Management**: Add, remove, enable/disable components
- **Property Editing**: Modify component properties and serialized fields
- **Object Reference Assignment**: Programmatic drag-and-drop equivalent for Inspector fields
- **Transform Control**: Set position, rotation, scale
- **Prefab Operations**: Create prefabs from GameObjects, instantiate prefabs
- **Scene Management**: Save scenes
- **Animation Authoring**: Create/edit animation clips, curves, keyframes, and events
- **Animator Controller Authoring**: Create controllers, add states, transitions, parameters, and layers
- **Editor Commands**: Execute safe C# expressions (sandboxed)

All mutations support Unity's Undo system (Ctrl+Z).

## Project Structure

```
com.unityai.mcp/
├── Editor/
│   ├── Handlers/
│   │   ├── AnimationHandler.cs      # Animation clip & animator controller tools
│   │   ├── AssetHandler.cs          # Asset search, packages, dependencies, folders
│   │   ├── ComponentHandler.cs      # Component serialization & inspection
│   │   ├── EditorCommandHandler.cs  # Sandboxed C# expression execution
│   │   ├── HierarchyHandler.cs      # Scene hierarchy & GameObject queries
│   │   ├── MutationHandler.cs       # All write operations (GameObjects, components, prefabs)
│   │   ├── ProjectSettingsHandler.cs# Unity project settings reader
│   │   └── ScriptHandler.cs         # Script listing & source reading
│   ├── Transport/
│   │   ├── HttpTransport.cs         # HTTP/SSE server & JSON-RPC transport
│   │   └── StdioTransport.cs        # Stdio transport & JSON-RPC message types
│   ├── Utils/
│   │   └── SerializationHelper.cs   # Unity type serialization & JSON parser
│   ├── UnityMCPServer.cs            # Main server, MCP protocol, tool routing
│   ├── UnityMCPEditorWindow.cs      # Editor UI (Window > Unity MCP)
│   └── com.unityai.mcp.Editor.asmdef
├── package.json
├── mcp_config.json
├── CHANGELOG.md
└── README.md
```

## Requirements

- Unity 2022.3 LTS or newer (including Unity 6.x)
- Windows, macOS, or Linux

## Installation

### Option 1: Git URL (Recommended)

1. Open Unity Package Manager (Window > Package Manager)
2. Click the "+" button and select "Add package from git URL..."
3. Enter: `https://github.com/coolmew/Unity-MCP.git`

### Option 2: Local Package

1. Clone or download this repository
2. Copy the `com.unityai.mcp` folder to your project's `Packages/` directory
3. Unity will automatically detect and import the package

### Option 3: Embedded Package

1. Copy the entire `com.unityai.mcp` folder into your project's `Packages/` folder
2. The package will be embedded in your project

## Quick Start

1. After installation, the MCP server starts automatically with Unity
2. Open **Window > Unity MCP** to see the server status and settings
3. Copy the MCP configuration to your AI client
4. Start querying your Unity project!

## Connecting AI Clients

### Claude Desktop

Add to your Claude Desktop configuration file:

**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "unity": {
      "url": "http://localhost:6400/mcp",
      "transport": "http"
    }
  }
}
```

### Cursor / Windsurf

Add to your MCP settings:

```json
{
  "mcpServers": {
    "unity": {
      "url": "http://localhost:6400/mcp",
      "transport": "http"
    }
  }
}
```

### Custom HTTP Client

Send JSON-RPC 2.0 requests to `http://localhost:6400/rpc`:

```bash
curl -X POST http://localhost:6400/rpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

---

## Available Tools

### Read Tools

#### getSceneHierarchy

Returns the full scene hierarchy with all GameObjects.

**Parameters:**
- `maxDepth` (int, optional): Maximum depth to traverse (default: 8)
- `includeInactive` (bool, optional): Include inactive GameObjects (default: true)

**Response:**
```json
{
  "scenes": [{
    "name": "SampleScene",
    "rootGameObjects": [{
      "name": "Main Camera",
      "instanceID": 12345,
      "tag": "MainCamera",
      "layer": 0,
      "activeSelf": true,
      "children": []
    }]
  }]
}
```

#### getGameObject

Returns detailed information about a specific GameObject.

**Parameters (one required):**
- `instanceID` (int): Instance ID of the GameObject
- `path` (string): Hierarchy path (e.g., "/Canvas/Panel/Button")
- `name` (string): Name of the GameObject

**Response:**
```json
{
  "name": "Player",
  "instanceID": 12345,
  "tag": "Player",
  "layer": 0,
  "transform": {
    "position": {"x": 0, "y": 1, "z": 0},
    "rotation": {"x": 0, "y": 0, "z": 0, "w": 1},
    "localScale": {"x": 1, "y": 1, "z": 1}
  },
  "components": [...]
}
```

#### getComponent

Returns all serialized fields of a component.

**Parameters:**
- `instanceID` (int, required): Instance ID of the GameObject
- `componentType` (string, required): Type name of the component

**Response:**
```json
{
  "type": "Rigidbody",
  "enabled": true,
  "fields": {
    "m_Mass": {"name": "m_Mass", "value": 1.0, "type": "float"},
    "m_Drag": {"name": "m_Drag", "value": 0.0, "type": "float"}
  }
}
```

#### findGameObjects

Searches for GameObjects matching filters.

**Parameters:**
- `nameFilter` (string, optional): Filter by name (partial match)
- `tagFilter` (string, optional): Filter by tag (exact match)
- `componentFilter` (string, optional): Filter by component type
- `layerFilter` (int, optional): Filter by layer index
- `offset` (int, optional): Pagination offset
- `limit` (int, optional): Max results (default: 100, max: 500)

#### getScripts

Returns all MonoBehaviour and ScriptableObject scripts.

**Parameters:**
- `nameFilter` (string, optional): Filter by script name
- `namespaceFilter` (string, optional): Filter by namespace
- `offset` (int, optional): Pagination offset
- `limit` (int, optional): Max results (default: 100)

**Response:**
```json
{
  "scripts": [{
    "name": "PlayerController",
    "path": "Assets/Scripts/PlayerController.cs",
    "namespace": "Game",
    "fields": [{"name": "speed", "type": "float"}],
    "methods": [{"name": "Move", "returnType": "void"}]
  }]
}
```

#### readScript

Returns the full source code of a script with parsed structure (usings, classes, methods, fields).

**Parameters:**
- `scriptPath` (string, required): Path to the script (e.g., "Assets/Scripts/Player.cs")

#### getProjectSettings

Returns Unity project settings.

**Parameters:**
- `sections` (array, optional): Specific sections to include
  - Valid values: `"player"`, `"quality"`, `"physics"`, `"physics2d"`, `"tags"`, `"layers"`, `"input"`, `"graphics"`, `"build"`, `"time"`, `"audio"`

**Response includes:**
- PlayerSettings (company, product, version, scripting backend, etc.)
- QualitySettings (current level, vSync, shadows, etc.)
- PhysicsSettings (gravity, contact offset, etc.)
- Physics2DSettings (gravity, iterations, etc.)
- TagsAndLayers (all tags, layer names, sorting layers)
- InputManager (axes definitions)
- GraphicsSettings (render pipeline, tier settings)
- BuildSettings (active target, scenes in build)
- TimeSettings (fixed delta time, time scale, etc.)
- AudioSettings (speaker mode, sample rate, etc.)

#### getAssets

Searches for assets in the project. Returns type-specific metadata (texture dimensions, audio length, mesh vertex count, material shader, etc.).

**Parameters:**
- `type` (string, optional): Asset type (e.g., "Texture2D", "Material", "Prefab", "AudioClip", "AnimationClip")
- `folder` (string, optional): Folder path (e.g., "Assets/Textures")
- `nameFilter` (string, optional): Filter by name
- `labelFilter` (string, optional): Filter by asset label
- `offset` (int, optional): Pagination offset
- `limit` (int, optional): Max results (default: 100)

#### getPackages

Returns all installed UPM packages.

**Response:**
```json
{
  "packages": [{
    "name": "com.unity.textmeshpro",
    "displayName": "TextMeshPro",
    "version": "3.0.6",
    "source": "registry"
  }]
}
```

#### getAssetDependencies

Returns the dependency graph for a specific asset.

**Parameters:**
- `path` (string, required): Asset path (e.g., "Assets/Prefabs/Player.prefab")
- `recursive` (bool, optional): Include transitive dependencies (default: false)

#### getFolderStructure

Returns the folder hierarchy of the project.

**Parameters:**
- `path` (string, optional): Root path (default: "Assets")
- `maxDepth` (int, optional): Maximum depth to traverse (default: 3)

#### getProjectInfo

Returns basic Unity project information (product name, company, Unity version, platform, play mode state, etc.). No parameters.

#### getAvailableCommands

Returns the list of supported editor command expressions grouped by category. No parameters.

#### getAnimationClipInfo

Returns full information about an animation clip including all curves, keyframes, and events.

**Parameters:**
- `clipPath` (string, required): Path to the `.anim` asset

#### getAnimatorControllerInfo

Returns full information about an animator controller including layers, states, parameters, and transitions.

**Parameters:**
- `controllerPath` (string, required): Path to the `.controller` asset

#### runEditorCommand

Executes a C# expression (requires opt-in).

**⚠️ Security Note:** This tool is disabled by default. Enable it in Window > Unity MCP settings only if you trust the connecting AI agents.

**Parameters:**
- `code` (string, required): C# expression to execute

**Supported expressions:**
- `Selection.activeGameObject`, `Selection.gameObjects.Length`
- `EditorApplication.isPlaying`, `EditorApplication.isCompiling`
- `SceneManager.GetActiveScene().name`
- `Debug.Log("message")`
- `GameObject.Find("name")`
- `AssetDatabase.FindAssets("filter")`, `AssetDatabase.Refresh()`

---

### Mutation Tools (Write Operations)

**⚠️ All mutation tools require "Enable Mutations" to be turned on in Window > Unity MCP settings.**

All mutations support Unity's Undo system — press Ctrl+Z (Cmd+Z on Mac) to undo any changes made by AI agents.

#### GameObject Operations

##### createGameObject

Creates a new GameObject in the scene.

**Parameters:**
- `name` (string, optional): Name of the GameObject
- `parentInstanceID` (int, optional): Parent GameObject instance ID
- `parentPath` (string, optional): Parent GameObject hierarchy path
- `position` (object, optional): Local position `{x, y, z}`
- `rotation` (object, optional): Local euler rotation `{x, y, z}`
- `scale` (object, optional): Local scale `{x, y, z}`
- `tag` (string, optional): GameObject tag
- `layer` (int, optional): GameObject layer
- `primitive` (string, optional): Create primitive mesh: `"cube"`, `"sphere"`, `"capsule"`, `"cylinder"`, `"plane"`, `"quad"`

##### deleteGameObject

Deletes a GameObject from the scene.

**Parameters (one required):**
- `instanceID` (int): GameObject instance ID
- `path` (string): GameObject hierarchy path
- `name` (string): GameObject name

##### renameGameObject

Renames a GameObject.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `newName` (string, required): New name

##### moveGameObject

Moves a GameObject to a new parent or changes its sibling index.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `newParentInstanceID` (int, optional): New parent instance ID (null for root)
- `newParentPath` (string, optional): New parent hierarchy path
- `siblingIndex` (int, optional): Sibling index position

##### duplicateGameObject

Duplicates a GameObject.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `newName` (string, optional): Name for the duplicate

##### setGameObjectActive

Sets a GameObject's active state.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `active` (bool, required): Active state

#### Transform Operations

##### setTransform

Sets a GameObject's transform (position, rotation, scale).

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `position` (object, optional): Position `{x, y, z}`
- `rotation` (object, optional): Euler rotation `{x, y, z}`
- `scale` (object, optional): Scale `{x, y, z}`
- `local` (bool, optional): Use local space (default: true)

#### Component Operations

##### addComponent

Adds a component to a GameObject.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `componentType` (string, required): Component type name (e.g., "Rigidbody", "BoxCollider", "AudioSource")

##### removeComponent

Removes a component from a GameObject.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `componentType` (string, required): Component type name

##### setComponentEnabled

Enables or disables a component.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `componentType` (string, required): Component type name
- `enabled` (bool, required): Enabled state

#### Property Operations

##### setComponentProperty

Sets a single property/field value on a component.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `componentType` (string, required): Component type name
- `propertyName` (string, required): Property/field name (e.g., "m_Mass" for Rigidbody)
- `value` (required): New value (type depends on property)

**Example:**
```json
{
  "path": "/Player",
  "componentType": "Rigidbody",
  "propertyName": "m_Mass",
  "value": 2.5
}
```

##### setMultipleProperties

Sets multiple properties on a component at once.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `componentType` (string, required): Component type name
- `properties` (object, required): Dictionary of property names to values

**Example:**
```json
{
  "path": "/Player",
  "componentType": "Rigidbody",
  "properties": {
    "m_Mass": 2.5,
    "m_Drag": 0.5,
    "m_UseGravity": true
  }
}
```

##### assignObjectReference

Assigns a scene object (GameObject, component) or asset to a component's serialized object-reference field. This is the programmatic equivalent of drag-and-drop in the Inspector.

**Parameters:**
- `targetInstanceID` or `targetPath` or `targetName` (required): Target GameObject (the one with the field)
- `componentType` (string, required): Component type on the target
- `propertyName` (string, required): Serialized field name to assign to
- **Source** (one required):
  - `sourceInstanceID` (int): Instance ID of the source object
  - `sourcePath` (string): Source GameObject hierarchy path
  - `sourceName` (string): Source GameObject name
  - `assetPath` (string): Asset path (e.g., "Assets/Materials/MyMat.mat")
  - `clear` (bool): Set to `true` to null the reference
- `sourceComponentType` (string, optional): Get a specific component from the source GameObject instead of the GameObject itself

#### Scene & Prefab Operations

##### saveScene

Saves the current or specified scene.

**Parameters:**
- `scenePath` (string, optional): Scene path (saves active scene if not specified)

##### createPrefab

Creates a prefab from a GameObject.

**Parameters:**
- `instanceID` or `path` (required): GameObject identifier
- `path` (string, optional): Prefab save path (e.g., "Assets/Prefabs/MyPrefab.prefab")

##### instantiatePrefab

Instantiates a prefab into the scene.

**Parameters:**
- `prefabPath` (string, required): Path to the prefab asset
- `parentInstanceID` (int, optional): Parent GameObject instance ID
- `position` (object, optional): World position `{x, y, z}`

#### Animation Clip Operations

##### createAnimationClip

Creates a new AnimationClip asset.

**Parameters:**
- `name` (string, optional): Clip name (default: "New Animation")
- `savePath` (string, optional): Save path (e.g., "Assets/Animations/Walk.anim")
- `loop` (bool, optional): Loop the animation
- `frameRate` (number, optional): Frame rate (default: 60)
- `wrapMode` (string, optional): `"loop"`, `"pingpong"`, `"clampforever"`, `"once"`

##### setAnimationCurve

Sets or replaces an entire animation curve on a clip.

**Parameters:**
- `clipPath` (string, required): Path to the `.anim` asset
- `propertyName` (string, required): Property name (e.g., "localPosition.x")
- `type` (string, required): Component type (e.g., "Transform", "SpriteRenderer")
- `keyframes` (array, required): Array of `{time, value, inTangent?, outTangent?}`
- `relativePath` (string, optional): Relative path to child (empty for root)

##### removeAnimationCurve

Removes an animation curve from a clip.

**Parameters:**
- `clipPath` (string, required): Path to the `.anim` asset
- `propertyName` (string, required): Property name to remove
- `type` (string, required): Component type
- `relativePath` (string, optional): Relative path to child

##### addAnimationKeyframe

Adds a single keyframe to an existing or new curve.

**Parameters:**
- `clipPath` (string, required): Path to the `.anim` asset
- `propertyName` (string, required): Property name
- `type` (string, required): Component type
- `time` (number, required): Keyframe time in seconds
- `value` (number, required): Keyframe value
- `inTangent` (number, optional): In tangent
- `outTangent` (number, optional): Out tangent
- `relativePath` (string, optional): Relative path to child

##### addAnimationEvent

Adds an animation event that calls a function at a specific time.

**Parameters:**
- `clipPath` (string, required): Path to the `.anim` asset
- `functionName` (string, required): Function to call
- `time` (number, required): Event time in seconds
- `intParameter` (int, optional): Int parameter
- `floatParameter` (number, optional): Float parameter
- `stringParameter` (string, optional): String parameter

##### setClipSettings

Modifies animation clip settings.

**Parameters:**
- `clipPath` (string, required): Path to the `.anim` asset
- `loopTime` (bool, optional): Enable looping
- `loopBlend` (bool, optional): Loop pose
- `cycleOffset` (number, optional): Cycle offset
- `frameRate` (number, optional): Frame rate
- `startTime` (number, optional): Start time
- `stopTime` (number, optional): Stop time

#### Animator Controller Operations

##### createAnimatorController

Creates a new Animator Controller asset.

**Parameters:**
- `name` (string, optional): Controller name
- `savePath` (string, optional): Save path (e.g., "Assets/Animations/Player.controller")

##### addAnimatorParameter

Adds a parameter to an animator controller.

**Parameters:**
- `controllerPath` (string, required): Path to the `.controller` asset
- `parameterName` (string, required): Parameter name
- `parameterType` (string, optional): `"float"`, `"int"`, `"bool"`, `"trigger"` (default: "float")
- `defaultValue` (optional): Default value for the parameter

##### addAnimatorState

Adds a state to an animator controller layer.

**Parameters:**
- `controllerPath` (string, required): Path to the `.controller` asset
- `stateName` (string, required): State name
- `layerIndex` (int, optional): Layer index (default: 0)
- `clipPath` (string, optional): Animation clip to assign as motion
- `speed` (number, optional): Playback speed (default: 1)
- `tag` (string, optional): State tag
- `isDefault` (bool, optional): Set as default state

##### addAnimatorTransition

Adds a transition between two states with optional conditions.

**Parameters:**
- `controllerPath` (string, required): Path to the `.controller` asset
- `sourceState` (string, required): Source state name
- `destinationState` (string, required): Destination state name
- `layerIndex` (int, optional): Layer index (default: 0)
- `hasExitTime` (bool, optional): Has exit time
- `exitTime` (number, optional): Exit time (0–1)
- `duration` (number, optional): Transition duration
- `conditions` (array, optional): Array of `{parameter, mode, threshold}` — mode: `"greater"`, `"less"`, `"equals"`, `"notequal"`, `"if"`, `"ifnot"`

##### addAnimatorLayer

Adds a new layer to an animator controller.

**Parameters:**
- `controllerPath` (string, required): Path to the `.controller` asset
- `layerName` (string, required): Layer name
- `defaultWeight` (number, optional): Default weight (0–1)

##### assignAnimator

Assigns an Animator Controller to a GameObject's Animator component (adds Animator if missing).

**Parameters:**
- `instanceID` or `path` or `name` (required): GameObject identifier
- `controllerPath` (string, optional): Path to the `.controller` asset
- `avatarPath` (string, optional): Path to avatar asset
- `applyRootMotion` (bool, optional): Apply root motion

---

## Editor Window

Open **Window > Unity MCP** to access:

- **Server Status**: View running state, port, and endpoint URLs
- **Settings**: Configure auto-start, port, stdio transport, and security options
- **MCP Config**: Copy HTTP or SSE configuration for AI clients
- **Request Log**: View incoming requests and responses with auto-scroll

## Security

- The server only listens on localhost (127.0.0.1)
- **Mutations are disabled by default** — must be explicitly enabled in settings
- **Editor commands are disabled by default** — requires explicit opt-in with a confirmation dialog
- Code execution is sandboxed with namespace whitelisting
- Dangerous operations (file deletion, process spawning, assembly loading) are blocked
- All mutations use Unity's Undo system for easy rollback

## Performance

- Hierarchy snapshots are cached per-frame and invalidated on scene/hierarchy changes
- Script metadata is cached for 30 seconds
- Large results support pagination with `offset` and `limit`
- All Unity API calls run on the main thread via `EditorApplication.update`

## Troubleshooting

### Server won't start
- Check if port 6400 is already in use
- Try changing the port in Window > Unity MCP settings

### AI client can't connect
- Ensure Unity is running and the server is started
- Check firewall settings for localhost connections
- Verify the MCP configuration URL matches the server port

### Missing data in responses
- Some data requires the scene to be loaded
- Package list may show "loading" on first request — retry after a moment
- Script cache refreshes every 30 seconds; new scripts appear on the next refresh

## API Reference

### JSON-RPC 2.0 Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/rpc` | POST | JSON-RPC 2.0 requests |
| `/message` | POST | Alias for `/rpc` |
| `/mcp` | GET | Server capabilities |
| `/mcp` | POST | MCP protocol requests (JSON-RPC) |
| `/sse` | GET | Server-Sent Events stream |
| `/health` | GET | Health check |

### MCP Protocol

The server implements MCP protocol version `2024-11-05` with support for:
- `initialize` — returns server info and capabilities
- `tools/list` — returns all available tool definitions
- `tools/call` — invokes a tool by name with arguments
- `resources/list` — returns available resources

### Error Codes

| Code | Description |
|------|-------------|
| -32700 | Parse error |
| -32600 | Invalid request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal error |
| -32000 | Unity runtime error |
| -32001 | Security error (mutations/commands disabled) |
| -32002 | Not found error |

## License

MIT License — see LICENSE file for details.

## Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for the full release history.

### 1.0.1
- Added complete Animation system (14 tools): clip creation, curve/keyframe editing, events, animator controllers, states, transitions, layers
- Added `assignObjectReference` tool for programmatic Inspector drag-and-drop
- Added `getAssetDependencies`, `getFolderStructure`, `getProjectInfo`, `getAvailableCommands` tools
- Added Unity 6.x compatibility with conditional compilation for removed APIs
- Updated README to document all tools and project structure

### 1.0.0
- Initial release
- Full MCP protocol support
- HTTP and SSE transports
- Complete Unity Editor integration