Skip to main content
Glama
irsjofka-alt

IRSofka Unreal Engine MCP

by irsjofka-alt
README.md
# IRSofka Unreal Engine MCP

Station-side MCP bridge for the **IRSofkaStationCore** Unreal Engine 5.8 plugin.

Licenced under the **Business Source License 1.1** by **PT IRSofka Data Teknologi**
(NIB (OSS) 1258 0003 4132 6 · D&B DUNS 5645 3618 4 · admin@irsofka.co.id · irsofka.co.id).
"Unreal Engine" is a trademark of Epic Games and is used here descriptively: no Epic code is
contained in this repository — the transport is ours, written against our own plugin.

## Why this repository exists

The project owner's instruction of 2026-10-15 15:26:
one ai-station repository becomes three — **IRSofka Blender MCP**, **IRSofka ComfyUI MCP**,
**IRSofka Unreal Engine MCP** — because the Unreal bridge "will be changed completely and adapted",
and a repository that is going to be rewritten must be able to carry its own version, licence and
tests.

## Architecture: the plugin is the receiver, the station is the caller

Stated by the project owner on 2026-10-15 15:02, implemented as two measurable states:

| condition | behaviour |
|---|---|
| plugin listener present on `127.0.0.1:9877` | the bridge is live: domain calls are executed on Unreal's GameThread by `IRSofkaStationCore` and results come back as one JSON line |
| plugin **not** detected | the plugin does what a normal plugin does — nothing is broken, nothing is simulated. Every MCP tool answers `status: UNAVAILABLE` with the reason, and `ue_station_status()` says `detected: false` |

`ue_station_status()` measures rather than remembers: it opens the socket now, so "engine not
started", "plugin not loaded" and "bridge alive" remain three different facts in the log instead of
collapsing into one word for failure.

```
AI engine (Qoder / Antigravity)
        │  MCP over stdio — 7 tools: ue_station_status + the 6 master domains
        │  (ue_world, ue_blueprint, ue_material, ue_media, ue_vision, ue_pipeline)
        ▼
server.py ──► bridge.py ── TCP 127.0.0.1:9877, one JSON line per call ──► IRSofkaStationCore (C++)
                                                                              └─ GameThread task runner,
                                                                                 transaction rollback
```

## Files

| file | owns |
|---|---|
| `server.py` | the published MCP surface (tools + docstrings the engines display) |
| `bridge.py` | the transport: framing, `station_status`, atomic pipeline with Partial Success |
| `tests/test_bridge.py` | the two-state proof, against a simulated listener on a free port — 10/10, no engine required |

## Install

```jsonc
{
  "mcpServers": {
    "irsofka-unreal-mcp": {
      "command": "python3",
      "args": ["$HOME/Apps/mcp/irsofka-unreal-mcp/server.py"]
    }
  }
}
```

Requires Python ≥ 3.10 and the `mcp` package. The plugin itself is installed separately as
`Engine/Plugins/Marketplace/IRSofkaStationCore`; its source repository is
`~/Documents/ai-workstation/projects/IRSofka-UE-AIStation-Core`, and the plugin directory is a
**build artefact**, not the source.

## What is not finished here — stated, not implied

1. **The plugin holds the two states; a given editor may not have that build yet.**
   `FIRSofkaStationPresence` lives in the plugin's source (`Source/IRSofkaCore/`) and is compiled by
   `RunUAT BuildPlugin` from that repository. Loading it into a running editor means a module rebuild
   or Live Coding in somebody's live session, which is that person's call, not a run's. Until an
   editor has the new binary, `ue_station_status()` reports `standalone_listener` — the receiver is
   alive but does not yet decide its own state. That is a measured fact about the installed build, not
   a failure of this server.
2. **The engine-side transform defects have code, not a live measurement.** A bare class name is no
   longer silently replaced by `AActor`, and `set_transform` now answers the transform that actually
   landed, inside a transaction. Both changes compile; proving them needs an editor listening on
   9877 and a mutating round trip, so until that run exists this claim is "compiled", not "measured".
3. **No remote is configured.** Publication shape and timing belong to the project owner; creating a
   repository is outward-facing and does not happen as a side effect of a task.