Skip to main content
Glama
IRSofka Unreal Engine MCP

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 — 12 tools total:
        │  • Diagnostic: ue_station_status
        │  • 6 Master Domains: ue_world, ue_blueprint, ue_material, ue_media, ue_vision, ue_pipeline
        │  • Extended Native Automation: ue_importer, ue_landscape, ue_cmd, ue_python, ue_level
        ▼
server.py ──► bridge.py ── TCP 127.0.0.1:9877, one JSON line per call ──► IRSofkaStationCore (C++)
                                                                              └─ GameThread task runner,
                                                                                 transaction rollback
```

## Tools & Verification Status

| Tool | Category | Status | Notes |
|---|---|---|---|
| `ue_station_status` | Diagnostics | **Verified** | Socket probe verifies offline/online listener states (10/10 test_bridge) |
| `ue_world` | Master Domain | **Verified** | Spawning, transforms, folder hierarchy, actor deletion, level streaming |
| `ue_cmd` | Automation | **Verified** | Direct console command execution on GameThread |
| `ue_python` | Automation | **Verified** | Python execution & REPL on GameThread |
| `ue_level` | Management | **Verified** | Level create, open, save, and inspector |
| `ue_vision` | Master Domain | **Verified** | Viewport capture to disk / artifact folder and camera framing |
| `ue_pipeline` | Master Domain | **Verified** | Multi-step transaction pipeline with Partial Success isolation |
| `ue_blueprint` | Master Domain | **Compiled / Bridge Tested** | Node graph & fuzzy pin connection; pending live editor deep test |
| `ue_material` | Master Domain | **Compiled / Bridge Tested** | Parameter assignment & inspection; pending live editor deep test |
| `ue_media` | Master Domain | **Compiled / Bridge Tested** | Sound & Niagara trigger; pending live editor deep test |
| `ue_importer` | Automation | **Compiled / Bridge Tested** | Batch FBX & PNG/TGA ingestion avoiding Wayland dialogs |
| `ue_landscape` | Automation | **Compiled / Bridge Tested** | Native ALandscape 16-bit heightmap ingestion |

## Roadmap: Addressing Tooling Gaps (Glama Analysis)

The following capabilities are tracked for upcoming releases:
1. **Blueprint Authoring**: Dynamic component additions and custom event graph node generation.
2. **Material Graph**: Material graph expression node creation/deletion beyond parameter assignment.
3. **Sequencer**: Track and keyframe automation for cinematic Level Sequences.

## 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 the private
`IRSofka-UE-AIStation-Core` repository, 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.