Go to file
dsarno f667582505
Feature/session based instance routing (#369)
* Add support for multiple Unity instances

* fix port detection

* add missing unity_instance parameter

* add instance params for resources

* Fix CodeRabbit review feedback

- Fix partial framed response handling in port discovery
  Add _recv_exact() helper to ensure complete frame reading
  Prevents healthy Unity instances from being misidentified as offline

- Remove unused default_conn variables in server.py (2 files)
  Fixes Ruff F841 lint error that would block CI/CD

- Preserve sync/async nature of resources in wrapper
  Check if original function is coroutine before wrapping
  Prevents 'dict object is not awaitable' runtime errors

- Fix reconnection to preserve instance_id
  Add instance_id tracking to UnityConnection dataclass
  Reconnection now targets the same Unity instance instead of any available one
  Prevents operations from being applied to wrong project

- Add instance logging to manage_asset for debugging
  Helps troubleshoot multi-instance scenarios

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>

* Fix CodeRabbit feedback: reconnection fallback and annotations safety

Address 3 CodeRabbit review comments:

1. Critical: Guard reconnection fallback to prevent wrong instance routing
   - When instance_id is set but rediscovery fails, now raises ConnectionError
   - Added 'from e' to preserve exception chain for better debugging
   - Prevents silently connecting to different Unity instance
   - Ensures multi-instance routing integrity

2. Minor: Guard __annotations__ access in resource registration
   - Use getattr(func, '__annotations__', {}) instead of direct access
   - Prevents AttributeError for functions without type hints

3. Minor: Remove unused get_type_hints import
   - Clean up unused import in resources/__init__.py

All changes applied to both Server/ and MCPForUnity/ directories.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix instance sorting and logging issues

- Fix sorting logic for instances without heartbeat data: use epoch timestamp instead of current time to properly deprioritize instances with None last_heartbeat
- Use logger.exception() instead of logger.error() in disconnect_all() to include stack traces for better debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* update uv.lock to prepare for merging into main

* Restore Python 3.10 lockfiles and package list_unity_instances tool

* Deduplicate Unity instance discovery by port

* Scope status-file reload checks to the active instance

* refactor: implement FastMCP middleware for session-based instance routing

Replaces module-level session_state.py with UnityInstanceMiddleware class
that follows FastMCP best practices. Middleware intercepts all tool calls
via on_call_tool hook and injects active Unity instance into request state.

Key changes:
- Add UnityInstanceMiddleware class with on_call_tool hook
- Tools now use ctx.get_state("unity_instance") instead of direct session_state calls
- Remove unity_instance parameter from all tool schemas to prevent LLM hallucination
- Convert list_unity_instances tool to unity_instances resource (read-only data)
- Update error messages to reference unity://instances resource
- Add set_state/get_state methods to DummyContext test helper
- All 67 tests passing (55 passed, 5 skipped, 7 xpassed)

Architecture benefits:
- Centralized session management in middleware
- Standard FastMCP patterns (middleware + request state)
- Cleaner separation of concerns
- Prevents AI hallucination of invalid instance IDs

* fix: convert resource templates to static resources for discoverability

Convert MCP resources from URI templates with query parameters to static
resources to fix discoverability in MCP clients like Claude Code.

Changes:
- Remove {?force_refresh} from unity://instances
- Remove {?unity_instance} from mcpforunity://menu-items
- Remove {?unity_instance} from mcpforunity://tests
- Keep {mode} path parameter in mcpforunity://tests/{mode} (legitimate)

Root cause: Query parameters {?param} trigger ResourceTemplate registration,
which are listed via resources/templates/list instead of resources/list.
Claude Code's ListMcpResourcesTool only queries resources/list, making
templates undiscoverable.

Solution: Remove optional query parameters from URIs. Instance routing is
handled by middleware/context, and force_refresh was cache control that
doesn't belong in resource identity.

Impact: Resources now discoverable via standard resources/list endpoint and
work with all MCP clients including Claude Code and Cursor.

Requires FastMCP >=2.13.0 for proper RFC 6570 query parameter support.

* feat: improve material properties and sync Server resources

Material Property Improvements (ManageAsset.cs):
- Add GetMainColorPropertyName() helper that auto-detects shader color properties
- Tries _BaseColor (URP), _Color (Standard), _MainColor, _Tint, _TintColor
- Update both named and array color property handling to use auto-detection
- Add warning messages when color properties don't exist on materials
- Split HasProperty check from SetColor to enable error reporting

This fixes the issue where simple color array format [r,g,b,a] defaulted to
_Color property, causing silent failures with URP Lit shader which uses _BaseColor.

Server Resource Sync:
- Sync Server/resources with MCPForUnity/UnityMcpServer~/src/resources
- Remove query parameters from resource URIs for discoverability
- Use session-based instance routing via get_unity_instance_from_context()

* fix: repair instance routing and simplify get_unity_instance_from_context

PROBLEM:
Instance routing was failing - scripts went to wrong Unity instances.
Script1 (intended: ramble) -> went to UnityMCPTests 
Script2 (intended: UnityMCPTests) -> went to ramble 

ROOT CAUSE:
Two incompatible approaches for accessing active instance:
1. Middleware: ctx.set_state() / ctx.get_state() - used by most tools
2. Legacy: ctx.request_context.meta - used by script tools
Script tools were reading from wrong location, middleware had no effect.

FIX:
1. Updated get_unity_instance_from_context() to read from ctx.get_state()
2. Removed legacy request_context.meta code path (98 lines removed)
3. Single source of truth: middleware state only

TESTING:
- Added comprehensive test suite (21 tests) covering all scenarios
- Tests middleware state management, session isolation, race conditions
- Tests reproduce exact 4-script failure scenario
- All 88 tests pass (76 passed + 5 skipped + 7 xpassed)
- Verified fix with live 4-script test: 100% success rate

Files changed:
- Server/tools/__init__.py: Simplified from 75 lines to 15 lines
- MCPForUnity/UnityMcpServer~/src/tools/__init__.py: Same simplification
- tests/test_instance_routing_comprehensive.py: New comprehensive test suite

* refactor: standardize instance extraction and remove dead imports

- Standardize all 18 tools to use get_unity_instance_from_context() helper
  instead of direct ctx.get_state() calls for consistency
- Remove dead session_state imports from with_unity_instance decorator
  that would cause ModuleNotFoundError at runtime
- Update README.md with concise instance routing documentation

* fix: critical timezone and import bugs from code review

- Remove incorrect port safety check that treated reclaimed ports as errors
  (GetPortWithFallback may legitimately return same port if it became available)
- Fix timezone-aware vs naive datetime mixing in unity_connection.py sorting
  (use timestamp() for comparison to avoid TypeError)
- Normalize all datetime comparisons in port_discovery.py to UTC
  (file_mtime and last_heartbeat now consistently timezone-aware)
- Add missing send_with_unity_instance import in Server/tools/manage_script.py
  (was causing NameError at runtime on lines 108 and 488)

All 88 tests pass (76 passed + 5 skipped + 7 xpassed)

---------

Co-authored-by: Sakura <sakurachan@qq.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-05 09:43:36 -08:00
.claude Improved ci prompt testing suite (#270) 2025-09-07 15:47:56 -07:00
.github fix: JSON material property handling + tests (manage_asset) #90 (#349) 2025-10-24 11:43:26 -07:00
MCPForUnity Feature/session based instance routing (#369) 2025-11-05 09:43:36 -08:00
Server Feature/session based instance routing (#369) 2025-11-05 09:43:36 -08:00
TestProjects/UnityMCPTests tests(editmode): pre-create texture asset in texture assignment test for CI stability (#352) 2025-10-24 11:57:18 -07:00
docs Remove old UI and do lots of cleanup (#340) 2025-10-24 00:50:29 -04:00
scripts Improved ci prompt testing suite (#270) 2025-09-07 15:47:56 -07:00
tests Feature/session based instance routing (#369) 2025-11-05 09:43:36 -08:00
tools docs: replace "Unity MCP" with "MCP for Unity" in all text strings (#314) 2025-10-11 04:01:51 -04:00
.gitignore test: Consolidate pytest suite to MCPForUnity and improve test infrastructure (#332) 2025-10-21 10:42:55 -07:00
LICENSE chore: update package metadata and license to CoplayDev organization 2025-08-08 15:54:43 -04:00
README-zh.md feat: lower minimum Python requirement to 3.10+ (#362) 2025-10-31 15:44:10 -04:00
README.md Feature/session based instance routing (#369) 2025-11-05 09:43:36 -08:00
deploy-dev.bat Update .Bat file and Bug fix on ManageScript (#355) 2025-10-25 12:27:07 -04:00
mcp_source.py Fix/replace pytest anyio with pytest asyncio (#333) 2025-10-21 13:56:59 -07:00
prune_tool_results.py Rename plugin folder to MCPForUnity (#303) 2025-10-03 20:23:28 -04:00
pytest.ini test: Consolidate pytest suite to MCPForUnity and improve test infrastructure (#332) 2025-10-21 10:42:55 -07:00
restore-dev.bat Update .Bat file and Bug fix on ManageScript (#355) 2025-10-25 12:27:07 -04:00
test_unity_socket_framing.py Autoformat (#297) 2025-09-30 16:25:33 -04:00

README.md

MCP for Unity
English 简体中文

Proudly sponsored and maintained by Coplay -- the best AI assistant for Unity.

Discord python GitHub commit activity GitHub Issues or Pull Requests

Create your Unity apps with LLMs!

MCP for Unity acts as a bridge, allowing AI assistants (like Claude, Cursor) to interact directly with your Unity Editor via a local MCP (Model Context Protocol) Client. Give your LLM tools to manage assets, control scenes, edit scripts, and automate tasks within Unity.

MCP for Unity screenshot

💬 Join Our Discord

Get help, share ideas, and collaborate with other MCP for Unity developers!


Key Features 🚀

  • 🗣️ Natural Language Control: Instruct your LLM to perform Unity tasks.
  • 🛠️ Powerful Tools: Manage assets, scenes, materials, scripts, and editor functions.
  • 🤖 Automation: Automate repetitive Unity workflows.
  • 🧩 Extensible: Designed to work with various MCP Clients.
Tools

Your LLM can use functions like:

  • read_console: Gets messages from or clears the console.
  • manage_script: Manages C# scripts (create, read, update, delete).
  • manage_editor: Controls and queries the editor's state and settings.
  • manage_scene: Manages scenes (load, save, create, get hierarchy, etc.).
  • manage_asset: Performs asset operations (import, create, modify, delete, etc.).
  • manage_shader: Performs shader CRUD operations (create, read, modify, delete).
  • manage_gameobject: Manages GameObjects: create, modify, delete, find, and component operations.
  • execute_menu_item: Executes Unity Editor menu items (e.g., "File/Save Project").
  • apply_text_edits: Precise text edits with precondition hashes and atomic multi-edit batches.
  • script_apply_edits: Structured C# method/class edits (insert/replace/delete) with safer boundaries.
  • validate_script: Fast validation (basic/standard) to catch syntax/structure issues before/after writes.
  • run_test: Runs a tests in the Unity Editor.
  • set_active_instance: Routes subsequent tool calls to a specific Unity instance (when multiple are running).
Resources

Your LLM can retrieve the following resources:

  • unity_instances: Lists all running Unity Editor instances with their details (name, path, port, status).
  • menu_items: Retrieves all available menu items in the Unity Editor.
  • tests: Retrieves all available tests in the Unity Editor. Can select tests of a specific type (e.g., "EditMode", "PlayMode").
---

How It Works

MCP for Unity connects your tools using two components:

  1. MCP for Unity Bridge: A Unity package running inside the Editor. (Installed via Package Manager).
  2. MCP for Unity Server: A Python server that runs locally, communicating between the Unity Bridge and your MCP Client. (Installed automatically by the package on first run or via Auto-Setup; manual setup is available as a fallback).
image

Installation ⚙️

Prerequisites

  • Python: Version 3.10 or newer. Download Python

  • Unity Hub & Editor: Version 2021.3 LTS or newer. Download Unity

  • uv (Python toolchain manager):

    # macOS / Linux
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
    # Windows (PowerShell)
    winget install --id=astral-sh.uv  -e
    
    # Docs: https://docs.astral.sh/uv/getting-started/installation/
    
  • An MCP Client: : Claude Desktop | Claude Code | Cursor | Visual Studio Code Copilot | Windsurf | Others work with manual config

  • [Optional] Roslyn for Advanced Script Validation
    For **Strict** validation level that catches undefined namespaces, types, and methods: 
    
    **Method 1: NuGet for Unity (Recommended)**
    1. Install [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity)
    2. Go to `Window > NuGet Package Manager`
    3. Search for `Microsoft.CodeAnalysis`, select version 4.14.0, and install the package
    4. Also install package `SQLitePCLRaw.core` and `SQLitePCLRaw.bundle_e_sqlite3`.
    5. Go to `Player Settings > Scripting Define Symbols`
    6. Add `USE_ROSLYN`
    7. Restart Unity
    
    **Method 2: Manual DLL Installation**
    1. Download Microsoft.CodeAnalysis.CSharp.dll and dependencies from [NuGet](https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/)
    2. Place DLLs in `Assets/Plugins/` folder
    3. Ensure .NET compatibility settings are correct
    4. Add `USE_ROSLYN` to Scripting Define Symbols
    5. Restart Unity
    
    **Note:** Without Roslyn, script validation falls back to basic structural checks. Roslyn enables full C# compiler diagnostics with precise error reporting.</details>
    

🌟 Step 1: Install the Unity Package

To install via Git URL

  1. Open your Unity project.
  2. Go to Window > Package Manager.
  3. Click + -> Add package from git URL....
  4. Enter:
    https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity
    
  5. Click Add.

To install via OpenUPM

  1. Install the OpenUPM CLI
  2. Open a terminal (PowerShell, Terminal, etc.) and navigate to your Unity project directory
  3. Run openupm add com.coplaydev.unity-mcp

Note: If you installed the MCP Server before Coplay's maintenance, you will need to uninstall the old package before re-installing the new one.

🛠️ Step 2: Configure Your MCP Client

Connect your MCP Client (Claude, Cursor, etc.) to the Python server set up in Step 1 (auto) or via Manual Configuration (below).

Option A: Auto-Setup (Recommended for Claude/Cursor/VSC Copilot)

  1. In Unity, go to Window > MCP for Unity.
  2. Click Auto-Setup.
  3. Look for a green status indicator 🟢 and "Connected ✓". (This attempts to modify the MCP Client's config file automatically).
Client-specific troubleshooting
  • VSCode: uses Code/User/mcp.json with top-level servers.unityMCP and "type": "stdio". On Windows, MCP for Unity writes an absolute uv.exe (prefers WinGet Links shim) to avoid PATH issues.
  • Cursor / Windsurf (help link): if uv is missing, the MCP for Unity window shows "uv Not Found" with a quick [HELP] link and a "Choose uv Install Location" button.
  • Claude Code (help link): if claude isn't found, the window shows "Claude Not Found" with [HELP] and a "Choose Claude Location" button. Unregister now updates the UI immediately.

Option B: Manual Configuration

If Auto-Setup fails or you use a different client:

  1. Find your MCP Client's configuration file. (Check client documentation).
    • Claude Example (macOS): ~/Library/Application Support/Claude/claude_desktop_config.json
    • Claude Example (Windows): %APPDATA%\Claude\claude_desktop_config.json
  2. Edit the file to add/update the mcpServers section, using the exact paths from Step 1.
Click for Client-Specific JSON Configuration Snippets...

Claude Code

If you're using Claude Code, you can register the MCP server using the below commands:

macOS:

claude mcp add --scope user UnityMCP -- uv --directory /Users/USERNAME/Library/AppSupport/UnityMCP/UnityMcpServer/src run server.py

Windows:

claude mcp add --scope user UnityMCP -- "C:/Users/USERNAME/AppData/Local/Microsoft/WinGet/Links/uv.exe" --directory "C:/Users/USERNAME/AppData/Local/UnityMCP/UnityMcpServer/src" run server.py

VSCode (all OS)

{
  "servers": {
    "unityMCP": {
      "command": "uv",
      "args": ["--directory","<ABSOLUTE_PATH_TO>/UnityMcpServer/src","run","server.py"],
      "type": "stdio"
    }
  }
}

On Windows, set command to the absolute shim, e.g. C:\\Users\\YOU\\AppData\\Local\\Microsoft\\WinGet\\Links\\uv.exe.

Windows:

{
  "mcpServers": {
    "UnityMCP": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "C:\\Users\\YOUR_USERNAME\\AppData\\Local\\UnityMCP\\UnityMcpServer\\src",
        "server.py"
      ]
    }
    // ... other servers might be here ...
  }
}

(Remember to replace YOUR_USERNAME and use double backslashes \)

macOS:

{
  "mcpServers": {
    "UnityMCP": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/Users/YOUR_USERNAME/Library/AppSupport/UnityMCP/UnityMcpServer/src",
        "server.py"
      ]
    }
    // ... other servers might be here ...
  }
}

(Replace YOUR_USERNAME. Note: AppSupport is a symlink to "Application Support" to avoid quoting issues)

Linux:

{
  "mcpServers": {
    "UnityMCP": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/home/YOUR_USERNAME/.local/share/UnityMCP/UnityMcpServer/src",
        "server.py"
      ]
    }
    // ... other servers might be here ...
  }
}

(Replace YOUR_USERNAME)


Usage ▶️

  1. Open your Unity Project. The MCP for Unity package should connect automatically. Check status via Window > MCP for Unity.

  2. Start your MCP Client (Claude, Cursor, etc.). It should automatically launch the MCP for Unity Server (Python) using the configuration from Installation Step 2.

  3. Interact! Unity tools should now be available in your MCP Client.

    Example Prompt: Create a 3D player controller, Create a tic-tac-toe game in 3D, Create a cool shader and apply to a cube.

Working with Multiple Unity Instances

MCP for Unity supports multiple Unity Editor instances simultaneously. Each instance is isolated per MCP client session.

To direct tool calls to a specific instance:

  1. List available instances: Ask your LLM to check the unity_instances resource
  2. Set the active instance: Use set_active_instance with the instance name (e.g., MyProject@abc123)
  3. All subsequent tools route to that instance until changed

Example:

User: "List all Unity instances"
LLM: [Shows ProjectA@abc123 and ProjectB@def456]

User: "Set active instance to ProjectA@abc123"
LLM: [Calls set_active_instance("ProjectA@abc123")]

User: "Create a red cube"
LLM: [Creates cube in ProjectA]

Development & Contributing 🛠️

Development Setup and Guidelines

See README-DEV.md for complete development setup and workflow documentation.

Adding Custom Tools

MCP for Unity uses a Python MCP Server tied with Unity's C# scripts for tools. If you'd like to extend the functionality with your own tools, learn how to do so in CUSTOM_TOOLS.md.

How to Contribute

  1. Fork the main repository.
  2. Create an issue to discuss your idea or bug.
  3. Create a branch (feature/your-idea or bugfix/your-fix).
  4. Make changes.
  5. Commit (feat: Add cool new feature).
  6. Push your branch.
  7. Open a Pull Request against the main branch, referencing the issue you created earlier.

📊 Telemetry & Privacy

MCP for Unity includes privacy-focused, anonymous telemetry to help us improve the product. We collect usage analytics and performance data, but never your code, project names, or personal information.

  • 🔒 Anonymous: Random UUIDs only, no personal data
  • 🚫 Easy opt-out: Set DISABLE_TELEMETRY=true environment variable
  • 📖 Transparent: See TELEMETRY.md for full details

Your privacy matters to us. All telemetry is optional and designed to respect your workflow.


Troubleshooting

Click to view common issues and fixes...
  • Unity Bridge Not Running/Connecting:
    • Ensure Unity Editor is open.
    • Check the status window: Window > MCP for Unity.
    • Restart Unity.
  • MCP Client Not Connecting / Server Not Starting:
    • Verify Server Path: Double-check the --directory path in your MCP Client's JSON config. It must exactly match the installation location:
      • Windows: %USERPROFILE%\AppData\Local\UnityMCP\UnityMcpServer\src
      • macOS: ~/Library/AppSupport/UnityMCP/UnityMcpServer\src
      • Linux: ~/.local/share/UnityMCP/UnityMcpServer\src
    • Verify uv: Make sure uv is installed and working (uv --version).
    • Run Manually: Try running the server directly from the terminal to see errors:
      cd /path/to/your/UnityMCP/UnityMcpServer/src
      uv run server.py
      
  • Configuration Failed:
    • Use the Manual Configuration steps. The plugin may lack permissions to write to the MCP client's config file.

Still stuck? Open an Issue or Join the Discord!


License 📜

MIT License. See LICENSE file.


Star History

Star History Chart

Unity AI Tools by Coplay

Coplay offers 2 AI tools for Unity

  • MCP for Unity is available freely under the MIT license.
  • Coplay is a premium Unity AI assistant that sits within Unity and is more than the MCP for Unity.

(These tools have different tech stacks. See this blog post comparing Coplay to MCP for Unity.)

Coplay

Disclaimer

This project is a free and open-source tool for the Unity Editor, and is not affiliated with Unity Technologies.