Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM python:3.13-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
git \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

RUN pip install uv

COPY . /app

RUN uv sync

CMD ["uv", "run", "server.py"]
157 changes: 157 additions & 0 deletions Server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# MCP for Unity Server

[![MCP](https://badge.mcpx.dev?status=on 'MCP Enabled')](https://modelcontextprotocol.io/introduction)
[![python](https://img.shields.io/badge/Python-3.11+-3776AB.svg?style=flat&logo=python&logoColor=white)](https://www.python.org)
[![License](https://img.shields.io/badge/License-MIT-red.svg 'MIT License')](https://opensource.org/licenses/MIT)
[![Discord](https://img.shields.io/badge/discord-join-red.svg?logo=discord&logoColor=white)](https://discord.gg/y4p8KfzrN4)

Model Context Protocol server for Unity Editor integration. Control Unity through natural language using AI assistants like Claude, Cursor, and more.

**Maintained by [Coplay](https://www.coplay.dev/?ref=unity-mcp)** - This project is not affiliated with Unity Technologies.

💬 **Join our community:** [Discord Server](https://discord.gg/y4p8KfzrN4)

**Required:** Install the [Unity MCP Plugin](https://github.com/CoplayDev/unity-mcp?tab=readme-ov-file#-step-1-install-the-unity-package) to connect Unity Editor with this MCP server.

---

## Installation

### Option 1: Using uvx (Recommended)

Run directly from GitHub without installation:

```bash
uvx --from git+https://github.com/CoplayDev/unity-mcp@v6.3.0#subdirectory=Server mcp-for-unity
```

**MCP Client Configuration:**

```json
{
"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:

```bash
# 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:**
```json
{
"mcpServers": {
"UnityMCP": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\path\\to\\unity-mcp\\Server",
"server.py"
]
}
}
}
```

**macOS/Linux:**
```json
{
"mcpServers": {
"UnityMCP": {
"command": "uv",
"args": [
"run",
"--directory",
"/path/to/unity-mcp/Server",
"server.py"
]
}
}
}
```

### Option 3: Using Docker

```bash
docker build -t unity-mcp-server .
docker run unity-mcp-server
```

**MCP Client Configuration:**

```json
{
"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 analytics
- `LOG_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:

📖 **[Full Documentation](https://github.com/CoplayDev/unity-mcp#readme)**

---

## Requirements

- **Python:** 3.11 or newer
- **Unity Editor:** 2021.3 LTS or newer
- **uv:** Python package manager ([Installation Guide](https://docs.astral.sh/uv/getting-started/installation/))

---

## License

MIT License - See [LICENSE](https://github.com/CoplayDev/unity-mcp/blob/main/LICENSE)
Empty file added Server/__init__.py
Empty file.
47 changes: 47 additions & 0 deletions Server/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""
Configuration settings for the MCP for Unity Server.
This file contains all configurable parameters for the server.
"""

from dataclasses import dataclass


@dataclass
class ServerConfig:
"""Main configuration class for the MCP server."""

# Network settings
unity_host: str = "localhost"
unity_port: int = 6400
mcp_port: int = 6500

# Connection settings
connection_timeout: float = 30.0
buffer_size: int = 16 * 1024 * 1024 # 16MB buffer
# Framed receive behavior
# max seconds to wait while consuming heartbeats only
framed_receive_timeout: float = 2.0
# cap heartbeat frames consumed before giving up
max_heartbeat_frames: int = 16

# Logging settings
log_level: str = "INFO"
log_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

# Server settings
max_retries: int = 5
retry_delay: float = 0.25
# Backoff hint returned to clients when Unity is reloading (milliseconds)
reload_retry_ms: int = 250
# Number of polite retries when Unity reports reloading
# 40 × 250ms ≈ 10s default window
reload_max_retries: int = 40

# Telemetry settings
telemetry_enabled: bool = True
# Align with telemetry.py default Cloud Run endpoint
telemetry_endpoint: str = "https://api-prod.coplay.dev/telemetry/events"


# Create a global config instance
config = ServerConfig()
9 changes: 9 additions & 0 deletions Server/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from typing import Any
from pydantic import BaseModel


class MCPResponse(BaseModel):
success: bool
message: str | None = None
error: str | None = None
data: Any | None = None
55 changes: 55 additions & 0 deletions Server/module_discovery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
Shared module discovery utilities for auto-registering tools and resources.
"""
import importlib
import logging
from pathlib import Path
import pkgutil
from typing import Generator

logger = logging.getLogger("mcp-for-unity-server")


def discover_modules(base_dir: Path, package_name: str) -> Generator[str, None, None]:
"""
Discover and import all Python modules in a directory and its subdirectories.

Args:
base_dir: The base directory to search for modules
package_name: The package name to use for relative imports (e.g., 'tools' or 'resources')

Yields:
Full module names that were successfully imported
"""
# Discover modules in the top level
for _, module_name, _ in pkgutil.iter_modules([str(base_dir)]):
# Skip private modules and __init__
if module_name.startswith('_'):
continue

try:
full_module_name = f'.{module_name}'
importlib.import_module(full_module_name, package_name)
yield full_module_name
except Exception as e:
logger.warning(f"Failed to import module {module_name}: {e}")

# Discover modules in subdirectories (one level deep)
for subdir in base_dir.iterdir():
if not subdir.is_dir() or subdir.name.startswith('_') or subdir.name.startswith('.'):
continue

# Check if subdirectory contains Python modules
for _, module_name, _ in pkgutil.iter_modules([str(subdir)]):
# Skip private modules and __init__
if module_name.startswith('_'):
continue

try:
# Import as package.subdirname.modulename
full_module_name = f'.{subdir.name}.{module_name}'
importlib.import_module(full_module_name, package_name)
yield full_module_name
except Exception as e:
logger.warning(
f"Failed to import module {subdir.name}.{module_name}: {e}")
Loading