# Unity MCP setup — Claude (WSL) driving the Unity Editor (Windows)

**Goal:** let Claude Code (running in WSL) control the Unity Editor (running on the Windows host) via MCP — the same pattern our UE projects already use (nwiro / ChiR24): the MCP server runs **host-side over HTTP**, and Claude in WSL connects across the WSL↔Windows boundary by its host IP.

**Server:** [CoplayDev/unity-mcp](https://github.com/CoplayDev/unity-mcp) ("MCP for Unity", MIT, ~12k★). Chosen because it's the most popular/maintained and — critically — supports an **HTTP transport** (`url: http://host:8080/mcp`), which bridges the WSL boundary cleanly instead of a same-machine stdio assumption.

> The in-editor **"Configure All Detected Clients"** button will *not* find WSL's `claude` (it looks on Windows), so we configure Claude manually via the committed `.mcp.json` (already in this repo) pointed at the Windows host IP.

## Current values (this machine)

**✅ WORKING CONFIG (verified 2026-07-10, mcp-for-unity-server v3.4.4):**
- **Windows host IP as seen from WSL:** `172.27.208.1` (the WSL default gateway; confirm with `ip route show default`). Can change across WSL restarts — if MCP stops connecting, re-check it and update `.mcp.json`.
- **MCP server:** binds `127.0.0.1:8067` (set the port in the *MCP for Unity* window; HTTP transport). **Do NOT use 8080** — see gotcha below.
- **WSL bridge:** Windows `netsh portproxy` `0.0.0.0:8068 → 127.0.0.1:8067` (+ firewall allow on 8068). A **distinct** listen port (8068) is required — a proxy on `0.0.0.0:8067` would collide with the server's `127.0.0.1:8067` bind.
- **`.mcp.json`** (committed) → `{"unity": {"type":"http","url":"http://172.27.208.1:8068/mcp"}}`
- **`.claude/settings.local.json`** (local) pre-enables the `unity` server.
- **Verify from WSL:** `curl -s -X POST http://172.27.208.1:8068/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}'` → should return an `initialize` result naming `mcp-for-unity-server`.

**⚠️ Gotcha — the port 8080 trap (why this took a few tries):** binding `8080` failed with Windows `[Errno 13] ... forbidden by its access permissions` (WSAEACCES). That's because **WSL2 runs on Hyper-V/WinNAT, which reserves large TCP port ranges**, and 8080 fell inside one. The server silently started then shut down; the "open 8080" was only the dead portproxy accepting + resetting. Fix = pick a port **outside** the reserved ranges (check `netsh interface ipv4 show excludedportrange protocol=tcp`) — we used `8067`. Bridge with a *different* proxy port (`8068`) to avoid the loopback/all-interfaces bind collision.

**Bridge commands (admin PowerShell), for reference / re-setup:**
```powershell
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8068 connectaddress=127.0.0.1 connectport=8067
New-NetFirewallRule -DisplayName "Unity MCP 8068" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8068
netsh interface portproxy show all
```

## One-time setup (do on Windows, in the Unity Editor)

1. **Create/open the Unity project** at `F:\jankenstein` (Unity LTS). This repo already lives there — Unity will add `Assets/`, `Packages/`, `ProjectSettings/` alongside the existing files.
2. **Install the package:** `Window → Package Manager → + → Add package from git URL…`
   ```
   https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#main
   ```
3. **Open** `Window → MCP for Unity`. Switch the transport to **HTTP** and **Start** the server (listens on `:8080`). Note the exact port shown.
4. **Make it reachable from WSL.** The HTTP server binds loopback by default, so pick one:
   - **(a)** If the panel exposes a non-loopback / `0.0.0.0` / "listen on all interfaces" option, enable it. Then WSL reaches it directly at `http://172.27.208.1:8080/mcp`.
   - **(b)** Otherwise add a Windows port-proxy + firewall rule (admin PowerShell) — same trick pair-o-dox uses for nwiro:
     ```powershell
     netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8080 connectaddress=127.0.0.1 connectport=8080
     New-NetFirewallRule -DisplayName "Unity MCP 8080" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8080
     ```
     Remove later with `netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=8080`.

## Connect from WSL (Claude Code)

1. Make sure the Unity Editor is **running with the project open** and the MCP server is **Started** (step 3 above) — the tools only work while the editor is live.
2. Run Claude from this folder (`/mnt/f/jankenstein`, or the symlink `~/claude/projects/jankenstein`). The committed `.mcp.json` + `.claude/settings.local.json` register/enable the `unity` server.
3. **Restart the Claude session** after any transport or `.mcp.json` change so it re-reads the config.
4. **Verify:** Claude should see `mcp__unity__*` tools. Quick smoke test: ask it to read the open scene / list GameObjects. If it fails:
   - `curl -s http://172.27.208.1:8080/mcp` from WSL — no response ⇒ the bridge (step 4) isn't up or the IP changed.
   - Confirm the editor is open and the server Started.
   - Re-check the gateway IP (`ip route show default`).

## Gotchas

- **Editor must be open** with the project loaded — MCP drives the live editor, it doesn't launch it.
- **IP drift:** the WSL gateway IP (`172.27.208.1`) can change on WSL restart; update `.mcp.json` if so.
- **HTTP↔stdio toggling** in the Unity panel requires a Claude restart to pick up.
- This is **editor tooling**, unrelated to the game's own netcode (NGO + Relay) — different layer entirely.
