Skip to content
ClaudeUnreal
GitHub

Architecture

This content is not available in your language yet.

ClaudeUnreal exposes Unreal Engine to AI agents through a hybrid surface: a small typed MCP layer for the hot path, plus a Bash CLI (cu) for the long tail. Both share the same TCP bridge into the editor.

Eager-loading 370 MCP tool schemas at session start costs ~144K tokens — about 72% of an Opus 4.7 context window before the user types a word. The hybrid split keeps the always-loaded surface tiny while preserving every capability behind a one-step lookup.

MetricBeforeAfter
MCP schema at session start (chars)~504K~25K
Eager-load context cost (tokens)~144K~7K
Tools always typed~37017
┌──────────────────────────────────┐
│ AI agent (e.g. Claude Code) │
└──────────────────────────────────┘
│ │
MCP stdio ────────┘ └──── Bash subprocess
│ │
▼ ▼
┌──────────────────────────────┐ ┌──────────────────────────┐
│ Python MCP server │ │ cu CLI │
│ (claude_unreal_server.py) │ │ (Resources/MCP/cli/ │
│ 17 typed tools │ │ cu.py) │
│ │ │ 362 long-tail commands │
└──────────────────────────────┘ └──────────────────────────┘
│ │
└────────────┬───────────────────┘
TCP / JSON
127.0.0.1:55557
┌──────────────────────────────────────┐
│ UClaudeUnrealBridge (C++) │
│ DispatchSingleCommand │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ Per-category handlers (C++) │
│ FClaudeUnrealEditorCommands etc. │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ UE5 engine APIs │
│ UEditorActorSubsystem, FBlueprint- │
│ EditorUtils, UAssetRegistry, ... │
└──────────────────────────────────────┘

The bridge is unchanged from the original architecture — both MCP and CLI clients send the same JSON to the same TCP port. The split lives entirely on the client side.

Common operations that appear in nearly every session, kept as typed MCP tools so the AI client’s schema-aware tool calling stays accurate:

ping, get_actors_in_level, get_selected_actors, find_actors_by_name, spawn_actor, delete_actor, get_actor_properties, set_actor_transform, set_actor_property, set_actor_component_property, take_screenshot, focus_viewport, exec_console_command.

The bridge into the long-tail surface:

  • unreal_categories() — landscape view of all 20 categories.
  • unreal_search(query, category?, limit?) — keyword-rank search of the manifest.
  • unreal_doc(command) — full reference for a single command.
  • unreal_session_brief() — one-call session bootstrap (current level + selected actors).

The other ~362 commands (Blueprint nodes, UMG widgets, Niagara modules, PCG graphs, sequencer keys, …) are not loaded as MCP tools. They live in the cu CLI and the bundled manifest.json. To run one:

  1. unreal_search("<keyword>") — find candidates.
  2. unreal_doc("<command>") — read params and example.
  3. Bash: cu exec <command> --params-json '<json>'.

See the Discovery flow walkthrough for a concrete example.

A small alias map (CommandAliases in ClaudeUnrealBridge.cpp) routes diverged MCP function names to original handlers — e.g. start_play_in_editorstart_pie. Keeps cu exec <python-name> working without renaming engine-side handlers.

Three layers as before, plus the manifest:

  1. C++ handler — declare in Source/ClaudeUnreal/Public/Commands/...h, implement in Private/Commands/...cpp.
  2. C++ routing — add the command string to ClaudeUnrealBridge.cpp’s DispatchSingleCommand.
  3. Python tool — register in Resources/MCP/tools/<module>.py with @mcp.tool().
  4. Manifestpython3 web/scripts/extract-tools.py regenerates tools.generated.ts. CI’s lint_manifest.py enforces consistency between bridge and manifest.

If the tool belongs in the hot path, also add its name to Resources/MCP/tools/_hot_path_names.json.