* 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> |
||
|---|---|---|
| .. | ||
| registry | ||
| resources | ||
| tools | ||
| Dockerfile | ||
| README.md | ||
| __init__.py | ||
| config.py | ||
| models.py | ||
| module_discovery.py | ||
| port_discovery.py | ||
| pyproject.toml | ||
| pyrightconfig.json | ||
| reload_sentinel.py | ||
| server.py | ||
| server_version.txt | ||
| telemetry.py | ||
| telemetry_decorator.py | ||
| test_telemetry.py | ||
| unity_connection.py | ||
| unity_instance_middleware.py | ||
| uv.lock | ||
README.md
MCP for Unity Server
Model Context Protocol server for Unity Editor integration. Control Unity through natural language using AI assistants like Claude, Cursor, and more.
Maintained by Coplay - This project is not affiliated with Unity Technologies.
💬 Join our community: Discord Server
Required: Install the Unity MCP Plugin to connect Unity Editor with this MCP server.
Installation
Option 1: Using uvx (Recommended)
Run directly from GitHub without installation:
uvx --from git+https://github.com/CoplayDev/unity-mcp@v6.3.0#subdirectory=Server mcp-for-unity
MCP Client Configuration:
{
"mcpServers": {
"UnityMCP": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/CoplayDev/unity-mcp@v6.3.0#subdirectory=Server",
"mcp-for-unity"
]
}
}
}
Option 2: Using uv (Local Installation)
For local development or custom installations:
# Clone the repository
git clone https://github.com/CoplayDev/unity-mcp.git
cd unity-mcp/Server
# Run with uv
uv run server.py
MCP Client Configuration:
Windows:
{
"mcpServers": {
"UnityMCP": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\path\\to\\unity-mcp\\Server",
"server.py"
]
}
}
}
macOS/Linux:
{
"mcpServers": {
"UnityMCP": {
"command": "uv",
"args": [
"run",
"--directory",
"/path/to/unity-mcp/Server",
"server.py"
]
}
}
}
Option 3: Using Docker
docker build -t unity-mcp-server .
docker run unity-mcp-server
MCP Client Configuration:
{
"mcpServers": {
"UnityMCP": {
"command": "docker",
"args": ["run", "-i", "unity-mcp-server"]
}
}
}
Configuration
The server connects to Unity Editor automatically when both are running. No additional configuration needed.
Environment Variables:
DISABLE_TELEMETRY=true- Opt out of anonymous usage analyticsLOG_LEVEL=DEBUG- Enable detailed logging (default: INFO)
Example Prompts
Once connected, try these commands in your AI assistant:
- "Create a 3D player controller with WASD movement"
- "Add a rotating cube to the scene with a red material"
- "Create a simple platformer level with obstacles"
- "Generate a shader that creates a holographic effect"
- "List all GameObjects in the current scene"
Documentation
For complete documentation, troubleshooting, and advanced usage:
Requirements
- Python: 3.11 or newer
- Unity Editor: 2021.3 LTS or newer
- uv: Python package manager (Installation Guide)
License
MIT License - See LICENSE