Install
$ agentstack add mcp-najemwehbe-unreal-ai-connection ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Unreal AI Connection
Drive Unreal Engine 5.7 from any MCP-compliant client over a local TCP socket.
151 tools total. Zero pixel-clicking. ~50ms round-trip.
[](https://github.com/NAJEMWEHBE/unreal-ai-connection/actions/workflows/tests.yml) [](LICENSE) [-313131?logo=unrealengine)](docs/PHASE-H-COMPAT.md) [](https://www.python.org/) [](https://modelcontextprotocol.io/) [](tests/) [](docs/TOOLS.md) [](CHANGELOG.md) [](#contributing)
Live capture — an MCP client builds the scene, places Niagara FX (spawn_niagara_at_location), and orbits a camera, entirely over the local TCP socket. Reproduce with [scripts/capture_demo_gif.py](scripts/capturedemogif.py).
Native C++ handlers — not Python Remote Execution. ~50 ms round-trips across 149 tools · 637 tests · MIT · works with any MCP-compliant client (Claude Code, Cursor, Cline, Codex, Gemini, Continue, Windsurf, Zed, …).
The suite now spans inspection and authoring — read existing assets and create them: actors, levels, data tables/assets, Blueprints (incl. K2 graph nodes), material graphs, Niagara FX, Level Sequence cinematics (camera cuts, audio, visibility), and Movie Render Queue renders — all over the same socket.
⭐ If this saves you time, a star helps other devs find it.
Authoring high-quality assets: see [docs/ASSET-PIPELINE-BLENDER.md](docs/ASSET-PIPELINE-BLENDER.md).
Install (one paste, any client)
> Every route below only wires the stdio bridge. You must separately install the UE 5.7 plugin into your project's Plugins/ folder and launch the editor (it binds 127.0.0.1:18888). See [docs/setup/README.md](docs/setup/README.md) for the prerequisite, and [docs/DISTRIBUTION.md](docs/DISTRIBUTION.md) for how this is published.
Claude Code — paste the owner/repo, no clone needed:
/plugin marketplace add NAJEMWEHBE/unreal-ai-connection
/plugin install unreal-ai-connection@unreal-ai-connection
Cursor — one-click deeplink. Base64-encode your machine's bridge path into this template:
cursor://anysphere.cursor-deeplink/mcp/install?name=unreal-ai-connection&config=
where ` is base64 of {"command":"python3","args":["/ABSOLUTE/PATH/TO/bridge/unrealaiconnection_bridge.py"]} (on Windows use "command":"py" if python3 is not on PATH). Manual fallback — .cursor/mcp.json`:
{ "mcpServers": { "unreal-ai-connection": { "command": "python3", "args": ["/ABSOLUTE/PATH/TO/bridge/unreal_ai_connection_bridge.py"] } } }
VS Code — install deeplink (URL-encode the JSON for your path):
vscode:mcp/install?
> Windows: all snippets use python3; if that's not on PATH use the py launcher instead ("command": "py"). The .claude-plugin/mcp-config.json marketplace path uses python3 for cross-platform consistency — Windows users without python3 should use the manual per-client recipe in docs/setup/ with py.
Every other client — copy-paste recipe per client:
| Client | Route | Recipe | |---|---|---| | Claude Code | /plugin marketplace add NAJEMWEHBE/unreal-ai-connection | [docs/setup/claude-code.md](docs/setup/claude-code.md) | | Claude Desktop | edit claude_desktop_config.json | [docs/setup/claude-desktop.md](docs/setup/claude-desktop.md) | | Cursor | deeplink / .cursor/mcp.json | [docs/setup/cursor.md](docs/setup/cursor.md) | | Codex CLI | codex mcp add unreal-ai-connection -- … | [docs/setup/codex-cli.md](docs/setup/codex-cli.md) | | Windsurf | mcp_config.json | [docs/setup/windsurf.md](docs/setup/windsurf.md) | | Continue | ~/.continue/config.yaml | [docs/setup/continue.md](docs/setup/continue.md) | | Cline | MCP Marketplace tab / settings | [docs/setup/cline.md](docs/setup/cline.md) | | Zed | ~/.config/zed/settings.json | [docs/setup/zed.md](docs/setup/zed.md) | | Gemini CLI | ~/.gemini/settings.json | [docs/setup/gemini-cli.md](docs/setup/gemini-cli.md) | | VS Code Copilot | .vscode/mcp.json | [docs/setup/vscode-copilot.md](docs/setup/vscode-copilot.md) |
Also discoverable in the official MCP Registry as io.github.najemwehbe/unreal-ai-connection (feeds the VS Code MCP gallery, mcp.so, PulseMCP) and submittable to the Cline marketplace via [llms-install.md](llms-install.md).
Jump to
- [How it fits together](#how-it-fits-together) — architecture diagram + per-call sequence
- [Why it exists](#why-it-exists) — the UE 5.7 Python dead-ends this plugin sidesteps
- [Why MCP specifically](#why-mcp-specifically) — one protocol, every conforming client
- [Tools](#tools) — 147 tools grouped into 15 expandable categories
- [Quick start](#quick-start) — copy-paste path to a running editor with the plugin live
- [What's in the box](#whats-in-the-box) — directory tree
- [Status](#status) — release / test / build state
- [Contributing](#contributing) — house rules + how to add a tool
- [License](#license)
How it fits together
graph LR
A[Any MCP client] -->|stdio MCP| B[Python Bridge]
B -->|TCP 127.0.0.1:18888| C[UnrealAIConnection pluginUE editor module]
C -->|native C++ API| D[Unreal Editor 5.7]
Per-call sequence — click to see exactly what fires on a single tool call
sequenceDiagram
participant User
participant Client as MCP client(e.g. Claude Code)
participant Bridge as Python bridge
participant Plugin as UE plugin module
participant Editor as Unreal Editor 5.7
User->>Client: "Spawn a Cube at origin"
Client->>Bridge: stdio MCP — tools/call spawn_actor
Bridge->>Plugin: TCP 127.0.0.1:18888JSON-RPC framed
Plugin->>Editor: GEditor->SpawnActor()
Editor-->>Plugin: success + actor ref
Plugin-->>Bridge: JSON-RPC result
Bridge-->>Client: MCP envelope
Client-->>User: rendered confirmation(~50ms total)
You ask Claude Code: "Take a screenshot of my level and tell me what's there." — Claude resolves the request to a tool call, the bridge forwards it as JSON-RPC to the running editor, the plugin captures the viewport, and Claude renders the image inline. Same flow works for spawning actors, inspecting Blueprints, mutating Widget Trees, executing arbitrary unreal.* Python, listing actors, focusing the viewport, loading levels, taking high-res screenshots.
The plugin binds to 127.0.0.1 only — your running editor is never reachable across the network.
Why it exists
UE 5.7's Python reflection has known dead-ends. Most painfully: EditorUtilityWidgetBlueprint.WidgetTree is a UPROPERTY() without EditAnywhere, so neither get_editor_property nor direct attribute access can reach it. This blocks "let an LLM build me an editor utility panel" workflows entirely.
The plugin sidesteps these limits by calling UE's native C++ APIs directly inside the editor process. It's also dramatically faster than driving UE's GUI with screenshot pixel-clicks — ~50ms round-trip vs. minutes of GUI fiddling.
Why MCP specifically
MCP (Model Context Protocol) is a vendor-neutral I/O protocol designed for LLM tool-use. Because this plugin speaks MCP rather than baking in any one client, every conforming client gets all 151 tools for free: Claude Code, Codex CLI, Cursor, Gemini CLI, Continue, Zed, Cline, and any future entrant. Switch clients without changing the plugin or the bridge.
The wire format is stdio MCP between client and bridge, then a tight length-prefixed JSON-RPC over TCP 127.0.0.1:18888 between bridge and the running UE editor. Either side can be reimplemented in another language; the contract is the JSON.
Tools
151 tools total. 114 are native C++ handlers registered by the plugin at editor startup; 37 are bridge-side synthetic tools (wait_for_events, get_camera_transform, set_camera_transform, screenshot_actor, compile_mod_pak, compile_mod_pak_direct, bulk_delete_assets, bulk_move_assets, bulk_rename_assets, bulk_duplicate_assets, bulk_inspect_assets, inspect_data_asset, inspect_sound_class, inspect_sound_submix, inspect_audio_bus, inspect_material_function, inspect_metasound, find_unused_assets, get_reference_chain, bulk_compile_blueprints, audit_blueprint_compile_status, find_actors_by_class, bulk_focus_actors, bulk_screenshot_actors, bulk_set_actor_property, compare_assets, bulk_set_console_variables, inspect_dependency_graph, bulk_fix_redirectors, marketplace_search, marketplace_import, convert_hdri_to_cubemap, sequencer_add_transform_keyframe, import_mesh, material_auto_remap, batch_capture_cameras, batch_spawn_from_csv) that compose existing handlers without a dedicated UE round-trip (or, for compile_mod_pak and compile_mod_pak_direct, shell out to RunUAT or UnrealPak entirely outside the UE process) — see bridge/unreal_ai_connection_bridge.py's SYNTHETIC_TOOLS. Per-tool JSON schemas and examples live in [docs/TOOLS.md](docs/TOOLS.md). Grouped overview:
> Progressive tool disclosure (opt-in). Advertising all 147 schemas up front is a lot of context — past ~30–50 tools, model tool-selection accuracy and token cost both degrade (Anthropic Tool Search Tool, MCP discussion #532). Set the environment variable UCMCP_TOOL_MODE=progressive on the bridge and tools/list returns only a small core set (get_project_summary, list_tools, get_actors_in_level, execute_unreal_python, take_high_res_screenshot, get_viewport_screenshot, poll_events) plus a single search_tools discovery tool. The model calls search_tools(query="add a camera keyframe", category="sequencer") to pull the schemas of just the tools it needs, on demand. Every one of the 147 tools stays directly callable via tools/call in both modes — progressive mode changes only what is advertised, never what is dispatchable, so existing clients keep working. Default (unset / all) is the legacy expose-everything behaviour. search_tools runs entirely bridge-side (no UE round-trip), validates its input, and fails closed.
Python execution (5 tools)
Python execution — click to expand the tool table
| Tool | Purpose | |---|---| | execute_unreal_python | Universal escape hatch — run arbitrary unreal.* Python in the editor's interpreter. Multi-line scripts work. | | run_python_file | Execute a .py file from disk in the editor's Python interpreter. | | apply_python_to_selection | Run a Python snippet with the editor's current selection bound as actors / assets. | | exec_python_persistent | Persistent Python session — variables defined in one call survive into the next. | | reset_python_state | Wipe the persistent session's globals. |
Project / asset registry (10 tools)
Project / asset registry — click to expand the tool table
| Tool | Purpose | |---|---| | get_project_summary | Project name, engine version, enabled plugins, asset count. | | find_assets | Query the asset registry by class + path + name. | | inspect_asset | Class, tags, dependencies, referencers, on-disk size. | | move_asset | Move an asset to a different folder; UE creates a redirector at the source path. | | rename_asset | Change an asset's leaf name in place; UE creates a redirector at the old name. | | duplicate_asset | Copy an asset to a new path. | | delete_asset | Delete an asset; refuses if referenced by other packages unless force=true. | | fix_up_redirectors | Resolve all object redirectors under a folder. | | create_data_table | Create a new UDataTable asset whose rows conform to a given row UScriptStruct. | | create_data_asset | Create a new UDataAsset (or subclass) asset from a UDataAsset subclass path. |
Blueprint / widget / animation — introspection + authoring (20 tools)
Blueprint / widget / animation — introspection + authoring — click to expand the tool table
| Tool | Purpose | |---|---| | inspect_blueprint | Variables, function/event graphs, parent class of any Blueprint asset. | | compile_blueprint | Recompile a Blueprint asset and report errors. | | inspect_widget_tree | Read the widget hierarchy of a UWidgetBlueprint or EUW (the thing UE Python can't do). | | inspect_widget_blueprint | Widget-BP-specific surface: animations, delegate bindings, palette category, inherited named slots, property-binding count, blueprint compile status. Pairs with inspect_blueprint + inspect_widget_tree. | | edit_widget_tree | Mutate the tree: set_root / add_child / set_property. Solves the EUW WidgetTree blocker. | | inspect_anim_blueprint | Read variables and state machines of an Animation Blueprint. | | inspect_anim_montage | Read sections, slots, and notify tracks of an UAnimMontage. | | inspect_static_mesh | LODs, materials, collision, bounds for a UStaticMesh. | | inspect_skeletal_mesh | LODs, materials, sockets, skeleton info for a USkeletalMesh. | | inspect_physics_asset | Body setups (one per simulated bone), constraint setups (joints between bodies), bounds-bodies subset, named physical-animation + constraint profiles. Cross-links to inspect_skeletal_mesh via preview_skeletal_mesh. | | inspect_niagara_system | Emitters and exposed user parameters of a Niagara system. | | inspect_landscape | Components, layers, and material info for a landscape actor. | | inspect_data_table | RowStruct identity, sorted row names, per-property name+type for every FProperty on the row struct, plus client-strip / ignore-extra/missing-fields flags. | | inspect_curve | UCurveBase channel layout (1ch UCurveFloat / 4ch UCurveLinearColor / 3ch UCurveVector), per-channel name + key count + per-channel + global time/value range. | | create_blueprint | Create a new UBlueprint asset under /Game/ from a parent class (default /Script/Engine.Actor). | | add_blueprint_variable | Add a typed member variable (bool/int/float/string/name/vector/rotator/transform/object) to an existing UBlueprint. | | add_blueprint_function | Add a new empty function graph to an existing UBlueprint. | | add_blueprint_node | Add a K2 node (call_function / variable_get / variable_set / branch) to a Blueprint event or function graph; returns the new node's GUID + pins. | | connect_blueprint_pins | Wire two pins (exec or data) between nodes by GUID + pin name, via the schema-validated UEdGraphSchema_K2::TryCreateConnection. | | set_blueprint_node_pin_default | Set a literal or object default on an input pin (verified by read-back). |
Materials (6 tools)
Materials — click to expand the tool table
| Tool | Purpose | |---|---| | create_material_instance | Create a UMaterialInstanceConstant asset with a parent material set. | | set_mi_parameter | Override a scalar/vector/texture parameter on a material instance. Type discriminator picks value shape. | | inspect_material | List parameter names declared by a UMaterial or UMaterialInstance (scalar/vector/texture/static-switch). | | inspect_material_instance | Read a material instance's parent + currently-overridden parameter values. | | add_material_expression | Create a UMaterialExpression node inside an existing UMaterial's graph, then recompile the material. | | connect_material_expression | Wire an expression's output to a material property input (property:BaseColor) or another expression's input (node::), then recompile. |
Textures (3 tools)
Textures — click to expand the tool table
| Tool | Purpose | |---|---| | import_texture | Bring an image file (PNG / JPG / EXR / TGA / BMP / HDR) from disk into the project as a UTexture2D asset via UE's canonical import path. | | configure_texture | Adjust SRGB / compression / LOD group / filter on an existing texture asset. | | inspect_texture | Texture class, surface dimensions, sRGB, compression, filter, LOD group,
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: NAJEMWEHBE
- Source: NAJEMWEHBE/unreal-ai-connection
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.