Skip to main content
Glama
README.md
<h1 align="center">Unity MCP</h1>

<p align="center">
  An MCP server that lives inside the Unity Editor.<br>
  One package, pure C#, nothing else to install.
</p>

<p align="center">
  <a href="LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-2f7f9e"></a>
  <img alt="Unity 2021.3+" src="https://img.shields.io/badge/Unity-2021.3%2B-0d2430">
  <img alt="MCP 2025-06-18" src="https://img.shields.io/badge/MCP-2025--06--18-f1d9a6">
</p>

<p align="center"><img src="docs~/hero.png" alt="A lighthouse island in Unity, built entirely by an agent through Unity MCP tool calls, next to the log of those calls" width="100%"></p>

Add the package, and your editor serves MCP at `http://127.0.0.1:8765/mcp`. Point Claude Code, Cursor, VS Code, Codex or any other MCP client at it. The agent can then compile your code and read the errors, build and change scenes, look at screenshots of what it made, and run your tests.

There is no Python server, no Node process, no `uv`, no bridge to keep alive. The server is a few C# files in an editor assembly, and it starts when Unity starts.

## Install

**Package Manager → + → Add package from git URL**, then paste:

```
https://github.com/siiplasplas/unity-mcp.git
```

Or add it to `Packages/manifest.json`, pinned to a release:

```json
"com.mirven.unity-mcp": "https://github.com/siiplasplas/unity-mcp.git#v0.1.0"
```

When Unity finishes importing, the server is running. **Window → Unity MCP** shows its status, the URL and the calls it has handled.

## Connect your agent

**Claude Code**

```bash
claude mcp add --transport http unity http://127.0.0.1:8765/mcp
```

**Cursor**, in `.cursor/mcp.json`

```json
{ "mcpServers": { "unity": { "url": "http://127.0.0.1:8765/mcp" } } }
```

**VS Code**, in `.vscode/mcp.json`

```json
{ "servers": { "unity": { "type": "http", "url": "http://127.0.0.1:8765/mcp" } } }
```

**Codex**, in `~/.codex/config.toml`

```toml
[mcp_servers.unity]
url = "http://127.0.0.1:8765/mcp"
```

**Claude Desktop**, which only speaks stdio, through [mcp-remote](https://www.npmjs.com/package/mcp-remote)

```json
{ "mcpServers": { "unity": { "command": "npx", "args": ["mcp-remote", "http://127.0.0.1:8765/mcp"] } } }
```

The Unity MCP window has all of these with a copy button, already filled in with your port.

## What the agent sees

The island at the top was built in an empty scene by 55 tool calls: materials, primitives, a point light, a parented cottage and a boat. [`tools~/demo.py`](tools~/demo.py) replays them, so you can build it yourself.

<p align="center"><img src="docs~/build.gif" alt="The island scene appearing step by step: sea and sand, rocks, lighthouse, lamp, cottage, trees, boat" width="720"></p>

Screenshots come back as images, not file paths. A model that can see can check its own work: whether the roof sits on the walls, whether the camera frames the object, whether the light is on.

## The loop: edit, compile, test, fix

`compile` waits for Unity to finish and returns the errors with file, line and column. `run_tests` waits for the Test Runner and returns each failure's message and the line it came from. Here is the output of one session, unedited:

<p align="center"><img src="docs~/loop.png" alt="Transcript: compile fails with CS1002, the agent fixes it, compile succeeds, a test reports the boat sank, the agent raises the boat, both tests pass" width="720"></p>

## Tools

21 tools. Every tool that changes the project is a single Undo step, so you can take back anything the agent did with Ctrl+Z, or ask it to call `undo`.

| Area | Tool | What it does |
|---|---|---|
| Editor | `editor_state` | Unity version, project, render pipeline, play and compile state, open scenes, selection, console counts |
| | `compile` | Import changed files, compile, wait, and return errors and warnings with `file(line,col)` |
| | `console` | Recent Console entries, errors and warnings by default |
| | `play` | Enter, exit, pause, resume or step play mode |
| | `menu` | Run any menu item by path |
| | `undo` | Undo or redo the last changes |
| | `select` | Select objects or assets and frame them, so you see what the agent means |
| Scene | `hierarchy` | Compact tree of the open scenes, or of one object |
| | `scene` | List, open, save, create or save-as. Refuses to drop unsaved changes unless asked |
| | `inspect` | Transform and every component's serialized properties, with paths for `set_property` |
| | `create_object` | Primitive, empty or prefab instance, with transform, components and material in one call |
| | `modify_object` | Name, parent, transform, active, tag, layer, static flag, on one or many objects |
| | `delete_object` | Delete objects and their children |
| | `add_component` | Add a built-in component or your own script, and set its fields |
| | `remove_component` | Remove a component |
| | `set_property` | Set serialized properties on components, materials or ScriptableObjects. References take asset or scene paths |
| | `save_prefab` | Save a scene object as a prefab and connect it |
| Assets | `find_assets` | Search like the Project window: `t:Material red`, `l:Enemy` |
| | `create_material` | Create or update a material with the project's render pipeline shader |
| Seeing | `screenshot` | Render the scene, one object, a scene camera or the Scene view, and return the image |
| Testing | `run_tests` | Run EditMode tests and return counts and failures. Appears when the Test Framework package is installed |

Writing scripts is left to the agent's own file tools, which every client already has and which are better at it. `compile` closes the loop.

## How it compares

Most Unity MCP servers are a bridge: a Python or Node server that the client talks to, plus a Unity plugin that it relays to over a socket. Those projects cover more ground than this one, with tools for ProBuilder, VFX, shaders, asset generation and more. If you need that breadth, use them.

Unity MCP takes the other trade.

| | Unity MCP | Bridge-based servers |
|---|---|---|
| Install | One Unity package | Unity package, plus a Python or Node runtime and its server |
| Processes | Just Unity | Unity, the server, and the connection between them |
| Transport | Streamable HTTP, straight into the editor | stdio or HTTP to the server, then a socket to Unity |
| Updating | Package Manager | The package and the server, kept in step |

What you also get here:

- Every write is one Undo step.
- Screenshots go back to the model as images.
- `compile` and `run_tests` wait for the result and return it in the same call.
- One toggle makes the whole server read-only.
- It runs in `-batchmode`, with no editor window.

## Settings

**Window → Unity MCP**

- **Server enabled** starts and stops the server.
- **Read-only** hides every tool that changes the project. The agent can still read the scene, the console and screenshots. Use it for reviews, or on a project you don't want touched.
- **Port** defaults to `8765`. Each Unity instance needs its own. The `UNITY_MCP_PORT` environment variable overrides it, which is handy for CI or for running several editors.

## Running headless

The server works in batch mode, so an agent can drive a project on a build machine or in CI without a window:

```bash
Unity -batchmode -projectPath path/to/project -logFile editor.log
```

Leave out `-quit` and Unity keeps serving until you stop it. After a compile in batch mode the server loads the new scripts right away, instead of waiting for the next import.

## Security

- The server binds to `127.0.0.1` and `localhost` only. Nothing on your network can reach it.
- Requests with a browser `Origin` that is not local get `403`, so a web page you visit cannot call your editor.
- There is no authentication beyond that. Any program running as you on your machine can call it, the same as it could edit your project files. Turn on **Read-only** or disable the server when you don't need it.

## Checking it works

[`tools~/smoke.py`](tools~/smoke.py) needs only Python's standard library. It checks the protocol (initialize, notifications, batches, errors, the Origin check) and calls every read-only tool:

```bash
python smoke.py                 # all checks, prints PASS / FAIL
python smoke.py list            # list the tools
python smoke.py call hierarchy "{\"depth\": 2}"
python smoke.py call screenshot "{}" --out shot.png
```

The `~` at the end of `tools~` and `docs~` tells Unity not to import those folders.

## Requirements

- Unity 2021.3 or later. Developed and tested on Unity 6 (6000.4). Reports from older versions are welcome.
- Any MCP client that supports Streamable HTTP, or stdio through `mcp-remote`.
- `run_tests` needs `com.unity.test-framework`, which new projects include.

## License

[MIT](LICENSE). Made by [Mirven](https://mirven.app).