unity-mcp/Server
Marcus Sanatan 664a43b76c
Remote server auth (#644)
* Disable the gloabl default to first session when hosting remotely

* Remove calls to /plugin/sessions

The newer /api/instances covers that data, and we want to remove these "expose all" endpoints

* Disable CLI routes when running in remote hosted mode

* Update server README

* feat: add API key authentication support for remote-hosted HTTP transport

- Add API key field to connection UI (visible only in HTTP Remote mode)
- Add "Get API Key" and "Clear" buttons with login URL retrieval
- Include X-API-Key header in WebSocket connections when configured
- Add API key to CLI commands (mcp add, claude mcp add) when set
- Update config.json generation to include headers with API key
- Add API key validation service with caching and configurable endpoints
- Add /api/auth/login-url endpoint

* feat: add environment variable support for HTTP remote hosted mode

- Add UNITY_MCP_HTTP_REMOTE_HOSTED environment variable as alternative to --http-remote-hosted flag
- Accept "true", "1", or "yes" values (case-insensitive)
- Update CLI help text to document environment variable option

* feat: add user isolation enforcement for remote-hosted mode session listing

- Raise ValueError when list_sessions() called without user_id in remote-hosted mode
- Add comprehensive integration tests for multi-user session isolation
- Add unit tests for PluginRegistry user-scoped session filtering
- Verify cross-user isolation with same project hash
- Test unity_instances resource and set_active_instance user filtering

* feat: add comprehensive integration tests for API key authentication

- Add ApiKeyService tests covering validation, caching, retries, and singleton lifecycle
- Add startup config validation tests for remote-hosted mode requirements
- Test cache hit/miss scenarios, TTL expiration, and manual invalidation
- Test transient failure handling (5xx, timeouts, connection errors) with retry logic
- Test service token header injection and empty key fast-path validation
- Test startup validation requiring

* test: add autouse fixture to restore config state after startup validation tests

Ensures test isolation for config-dependent integration tests

* feat: skip user_id resolution in non-remote-hosted mode

Prevents unnecessary API key validation when not in remote-hosted mode

* test: add missing mock attributes to instance routing tests

- Add client_id to test context mock in set_active_instance test
- Add get_state mock to context in global instance routing test

* Fix broken telemetry test

* Add comprehensive API key authentication documentation

- Add user guide covering configuration, setup, and troubleshooting
- Add architecture reference documenting internal design and request flows

* Add remote-hosted mode and API key authentication documentation to server README

* Update reference doc for Docker Hub

* Specify exception being caught

* Ensure caplog handler cleanup in telemetry queue worker test

* Use NoUnitySessionError instead of RuntimeError in session isolation test

* Remove unusued monkeypatch arg

* Use more obviously fake API keys

* Reject connections when ApiKeyService is not initialized in remote-hosted mode

- Validate that user_id is present after successful key validation
- Expand transient error detection to include timeout and service errors
- Use consistent 1013 status code for retryable auth failures

* Accept "on" for UNITY_MCP_HTTP_REMOTE_HOSTED env var

Consistent with repo

* Invalidate cached login URL when HTTP base URL changes

* Pass API key as parameter instead of reading from EditorPrefs in RegisterWithCapturedValues

* Cache API key in field instead of reading from EditorPrefs on each reconnection

* Align markdown table formatting in remote server auth documentation

* Minor fixes

* security: Sanitize API key values in shell commands and fix minor issues

Add SanitizeShellHeaderValue() method to escape special shell characters (", \, `, $, !) in API keys before including them in shell command arguments. Apply sanitization to all three locations where API keys are embedded in shell commands (two in RegisterWithCapturedValues, one in GetManualInstructions).

Also fix deprecated passwordCharacter property (now maskChar) and improve exception logging in _resolve_user_id_from_request

* Consolidate duplicate instance selection error messages into InstanceSelectionRequiredError class

Add InstanceSelectionRequiredError exception class with centralized error messages (_SELECTION_REQUIRED and _MULTIPLE_INSTANCES). Replace 4 duplicate RuntimeError raises with new exception type. Update tests to catch InstanceSelectionRequiredError instead of RuntimeError.

* Replace hardcoded "X-API-Key" strings with AuthConstants.ApiKeyHeader constant across C# and Python codebases

Add AuthConstants class in C# and API_KEY_HEADER constant in Python to centralize the API key header name definition. Update all 8 locations where "X-API-Key" was hardcoded (4 in C#, 4 in Python) to use the new constants instead.

* Fix imports

* Filter session listing by user_id in all code paths to prevent cross-user session access

Remove conditional logic that only filtered sessions by user_id in remote-hosted mode. Now all session listings are filtered by user_id regardless of hosting mode, ensuring users can only see and interact with their own sessions.

* Consolidate get_session_id_by_hash methods into single method with optional user_id parameter

Merge get_session_id_by_hash and get_session_id_by_user_hash into a single method that accepts an optional user_id parameter. Update all call sites to use the unified method signature with user_id as the second parameter. Update tests and documentation to reflect the simplified API.

* Add environment variable support for project-scoped-tools flag [skip ci]

Support UNITY_MCP_PROJECT_SCOPED_TOOLS environment variable as alternative to --project-scoped-tools command line flag. Accept "true", "1", "yes", or "on" as truthy values (case-insensitive). Update help text to document the environment variable option.

* Fix Python tests

* Update validation logic to only require API key validation URL when both http_remote_hosted is enabled AND transport mode is "http", preventing false validation errors in stdio mode.

* Update Server/src/main.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Refactor HTTP transport configuration to support separate local and remote URLs

Split HTTP transport into HttpLocal and HttpRemote modes with separate EditorPrefs storage (HttpBaseUrl and HttpRemoteBaseUrl).

Add HttpEndpointUtility methods to get/save local and remote URLs independently, and introduce IsRemoteScope() and GetCurrentServerTransport() helpers to centralize 3-way transport determination (Stdio/Http/HttpRemote). Update all client configuration code to distinguish between local and remote HTTP

* Only include API key headers in HTTP/WebSocket configuration when in remote-hosted mode

Update all locations where API key headers are added to HTTP/WebSocket configurations to check HttpEndpointUtility.IsRemoteScope() or serverTransport == HttpRemote before including the API key. This prevents local HTTP mode from unnecessarily including API key headers in shell commands, config JSON, and WebSocket connections.

* Hide Manual Server Launch foldout when not in HTTP Local mode

* Fix failing test

* Improve error messaging and API key validation for HTTP Remote transport

Add detailed error messages to WebSocket connection failures that guide users to check server URL, server status, and API key validity. Store error state in TransportState for propagation to UI. Disable "Start Session" button when HTTP Remote mode is selected without an API key, with tooltip explaining requirement. Display error dialog on connection failure with specific error message from transport state. Update connection

* Add missing .meta file

* Store transport mode in ServerConfig instead of environment variable

* Add autouse fixture to restore global config state between tests

Add restore_global_config fixture in conftest.py that automatically saves and restores global config attributes and UNITY_MCP_TRANSPORT environment variable between tests. Update integration tests to use monkeypatch.setattr on config.transport_mode instead of monkeypatch.setenv to prevent test pollution and ensure clean state isolation.

* Fix startup

* Replace _current_transport() calls with direct config.transport_mode access

* Minor cleanup

* Add integration tests for HTTP transport authentication behavior

Verify that HTTP local mode allows requests without user_id while HTTP remote-hosted mode rejects them with auth_required error.

* Add smoke tests for transport routing paths across HTTP local, HTTP remote, and stdio modes

Verify that HTTP local routes through PluginHub without user_id, HTTP remote routes through PluginHub with user_id, and stdio calls legacy send function with instance_id. Each test uses monkeypatch to configure transport mode and mock appropriate transport layer functions.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-30 18:39:21 -04:00
..
src Remote server auth (#644) 2026-01-30 18:39:21 -04:00
tests Remote server auth (#644) 2026-01-30 18:39:21 -04:00
DOCKER_OVERVIEW.md Remote server auth (#644) 2026-01-30 18:39:21 -04:00
Dockerfile Docker mcp gateway (#603) 2026-01-21 16:00:11 -04:00
LICENSE Publish to pypi (#466) 2025-12-19 16:43:44 -04:00
README.md Remote server auth (#644) 2026-01-30 18:39:21 -04:00
__init__.py Copy the MCP server to the top level (#354) 2025-10-25 00:53:53 -04:00
pyproject.toml chore: bump version to 9.2.0 2026-01-23 05:34:19 +00:00
pyrightconfig.json Copy the MCP server to the top level (#354) 2025-10-25 00:53:53 -04:00
uv.lock [FEATURE] Procedural Texture2D/Sprite Generation (#621) 2026-01-24 17:09:07 -05:00

README.md

MCP for Unity Server

MCP python License Discord

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. You also need uvx (requires uv) to run the server.


Installation

Option 1: PyPI

Install and run directly from PyPI using uvx.

Run Server (HTTP):

uvx --from mcpforunityserver mcp-for-unity --transport http --http-url http://localhost:8080

MCP Client Configuration (HTTP):

{
  "mcpServers": {
    "UnityMCP": {
      "url": "http://localhost:8080/mcp"
    }
  }
}

MCP Client Configuration (stdio):

{
  "mcpServers": {
    "UnityMCP": {
      "command": "uvx",
      "args": [
        "--from",
        "mcpforunityserver",
        "mcp-for-unity",
        "--transport",
        "stdio"
      ]
    }
  }
}

Option 2: From GitHub Source

Use this to run the latest released version from the repository. Change the version to main to run the latest unreleased changes from the repository.

{
  "mcpServers": {
    "UnityMCP": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/CoplayDev/unity-mcp@v9.2.0#subdirectory=Server",
        "mcp-for-unity",
        "--transport",
        "stdio"
      ]
    }
  }
}

Option 3: Docker

Use Pre-built Image:

docker run -p 8080:8080 msanatan/mcp-for-unity-server:latest --transport http --http-url http://0.0.0.0:8080

Build Locally:

docker build -t unity-mcp-server .
docker run -p 8080:8080 unity-mcp-server --transport http --http-url http://0.0.0.0:8080

Configure your MCP client with "url": "http://localhost:8080/mcp".

Option 4: Local Development

For contributing or modifying the server code:

# Clone the repository
git clone https://github.com/CoplayDev/unity-mcp.git
cd unity-mcp/Server

# Run with uv
uv run src/main.py --transport stdio

Configuration

The server connects to Unity Editor automatically when both are running. Most users do not need to change any settings.

CLI options

These options apply to the mcp-for-unity command (whether run via uvx, Docker, or python src/main.py).

  • --transport {stdio,http} - Transport protocol (default: stdio)
  • --http-url URL - Base URL used to derive host/port defaults (default: http://localhost:8080)
  • --http-host HOST - Override HTTP bind host (overrides URL host)
  • --http-port PORT - Override HTTP bind port (overrides URL port)
  • --http-remote-hosted - Treat HTTP transport as remotely hosted
    • Requires API key authentication (see below)
    • Disables local/CLI-only HTTP routes (/api/command, /api/instances, /api/custom-tools)
    • Forces explicit Unity instance selection for MCP tool/resource calls
    • Isolates Unity sessions per user
  • --api-key-validation-url URL - External endpoint to validate API keys (required when --http-remote-hosted is set)
  • --api-key-login-url URL - URL where users can obtain/manage API keys (served by /api/auth/login-url)
  • --api-key-cache-ttl SECONDS - Cache duration for validated keys (default: 300)
  • --api-key-service-token-header HEADER - Header name for server-to-auth-service authentication (e.g. X-Service-Token)
  • --api-key-service-token TOKEN - Token value sent to the auth service for server authentication
  • --default-instance INSTANCE - Default Unity instance to target (project name, hash, or Name@hash)
  • --project-scoped-tools - Keep custom tools scoped to the active Unity project and enable the custom tools resource
  • --unity-instance-token TOKEN - Optional per-launch token set by Unity for deterministic lifecycle management
  • --pidfile PATH - Optional path where the server writes its PID on startup (used by Unity-managed terminal launches)

Environment variables

  • UNITY_MCP_TRANSPORT - Transport protocol: stdio or http
  • UNITY_MCP_HTTP_URL - HTTP server URL (default: http://localhost:8080)
  • UNITY_MCP_HTTP_HOST - HTTP bind host (overrides URL host)
  • UNITY_MCP_HTTP_PORT - HTTP bind port (overrides URL port)
  • UNITY_MCP_HTTP_REMOTE_HOSTED - Enable remote-hosted mode (true, 1, or yes)
  • UNITY_MCP_DEFAULT_INSTANCE - Default Unity instance to target (project name, hash, or Name@hash)
  • UNITY_MCP_SKIP_STARTUP_CONNECT=1 - Skip initial Unity connection attempt on startup

API key authentication (remote-hosted mode):

  • UNITY_MCP_API_KEY_VALIDATION_URL - External endpoint to validate API keys
  • UNITY_MCP_API_KEY_LOGIN_URL - URL where users can obtain/manage API keys
  • UNITY_MCP_API_KEY_CACHE_TTL - Cache TTL for validated keys in seconds (default: 300)
  • UNITY_MCP_API_KEY_SERVICE_TOKEN_HEADER - Header name for server-to-auth-service authentication
  • UNITY_MCP_API_KEY_SERVICE_TOKEN - Token value sent to the auth service for server authentication

Telemetry:

  • DISABLE_TELEMETRY=1 - Disable anonymous telemetry (opt-out)
  • UNITY_MCP_DISABLE_TELEMETRY=1 - Same as DISABLE_TELEMETRY
  • MCP_DISABLE_TELEMETRY=1 - Same as DISABLE_TELEMETRY
  • UNITY_MCP_TELEMETRY_ENDPOINT - Override telemetry endpoint URL
  • UNITY_MCP_TELEMETRY_TIMEOUT - Override telemetry request timeout (seconds)

Examples

Stdio (default):

uvx --from mcpforunityserver mcp-for-unity --transport stdio

HTTP (local):

uvx --from mcpforunityserver mcp-for-unity --transport http --http-host 127.0.0.1 --http-port 8080

HTTP (remote-hosted with API key auth):

uvx --from mcpforunityserver mcp-for-unity \
  --transport http \
  --http-host 0.0.0.0 \
  --http-port 8080 \
  --http-remote-hosted \
  --api-key-validation-url https://auth.example.com/api/validate-key \
  --api-key-login-url https://app.example.com/api-keys

Disable telemetry:

DISABLE_TELEMETRY=1 uvx --from mcpforunityserver mcp-for-unity --transport stdio

Remote-Hosted Mode

When deploying the server as a shared remote service (e.g. for a team or Asset Store users), enable --http-remote-hosted to activate API key authentication and per-user session isolation.

Requirements:

  • An external HTTP endpoint that validates API keys. The server POSTs {"api_key": "..."} and expects {"valid": true, "user_id": "..."} or {"valid": false} in response.
  • --api-key-validation-url must be provided (or UNITY_MCP_API_KEY_VALIDATION_URL). The server exits with code 1 if this is missing.

What changes in remote-hosted mode:

  • All MCP tool/resource calls and Unity plugin WebSocket connections require a valid X-API-Key header.
  • Each user only sees Unity instances that connected with their API key (session isolation).
  • Auto-selection of a sole Unity instance is disabled; users must explicitly call set_active_instance.
  • CLI REST routes (/api/command, /api/instances, /api/custom-tools) are disabled.
  • /health and /api/auth/login-url remain accessible without authentication.

MCP client config with API key:

{
  "mcpServers": {
    "UnityMCP": {
      "url": "http://remote-server:8080/mcp",
      "headers": {
        "X-API-Key": "<your-api-key>"
      }
    }
  }
}

For full details, see Remote Server Auth Guide and Architecture Reference.


MCP Resources

The server provides read-only MCP resources for querying Unity Editor state. Resources provide up-to-date information about your Unity project without modifying it.

Accessing Resources:

Resources are accessed by their URI (not their name). Always use ListMcpResources to get the correct URI format.

Example URIs:

  • mcpforunity://editor/state - Editor readiness snapshot
  • mcpforunity://project/tags - All project tags
  • mcpforunity://scene/gameobject/{instance_id} - GameObject details by ID
  • mcpforunity://prefab/{encoded_path} - Prefab info by asset path

Important: Resource names use underscores (e.g., editor_state) but URIs use slashes/hyphens (e.g., mcpforunity://editor/state). Always use the URI from ListMcpResources() when reading resources.

All resource descriptions now include their URI for easy reference. List available resources to see the complete catalog with URIs.


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:

📖 Full Documentation


Requirements

  • Python: 3.10 or newer
  • Unity Editor: 2021.3 LTS or newer
  • uv: Python package manager (Installation Guide)

License

MIT License - See LICENSE