MCP (Model Context Protocol) bridge for Unreal Engine 5 — lets AI assistants control the UE5 editor
Project description
UnrealMCP — Model Context Protocol Bridge for Unreal Engine 5
UnrealMCP exposes the Unreal Engine 5 editor to AI coding assistants (Claude Code, Cursor, Windsurf, etc.) through the Model Context Protocol. Drop it into any UE5 project's Plugins/ folder and let your AI assistant create materials, blueprints, spawn actors, manage data tables, profile performance, and more — all without leaving your terminal.
How It Works
UnrealMCP has two halves:
- C++ Editor Plugin (
UnrealMCPBridgemodule) — runs inside the UE5 editor as a TCP server. It receives JSON commands and executes them in-editor using Unreal's C++ API. - Python MCP Server (
pip install unrealmcp) — runs as a stdio process spawned by your AI tool. It translates MCP tool calls into TCP commands sent to the C++ bridge.
┌─────────────┐ stdio ┌──────────────────┐ TCP/JSON ┌──────────────────┐
│ Claude Code │ ────────► │ Python MCP │ ────────────► │ C++ Bridge │
│ / Cursor │ ◄──────── │ Server │ ◄──────────── │ (in UE5 Editor) │
└─────────────┘ └──────────────────┘ └──────────────────┘
The C++ bridge writes its TCP port to Saved/UnrealMCP/port.txt on startup. The Python server reads that file automatically — no manual port configuration needed.
Requirements
- Unreal Engine 5.7 (tested on 5.7, may work on earlier 5.x versions)
- Python 3.10+
- UE5 Plugins (enabled automatically by the
.uplugin):PythonScriptPluginEditorScriptingUtilitiesEnhancedInput
Setup
There are two parts to UnrealMCP:
- C++ Plugin — lives inside your project or engine
Plugins/folder. You get this by cloning the repo. - Python MCP Server — a global
pippackage. Install once, works everywhere.
Step 1: Clone the Plugin
# Into your project
git clone https://github.com/aadeshrao123/Unreal-MCP.git Plugins/UnrealMCP
# OR into your engine (shared across all projects using this engine version)
git clone https://github.com/aadeshrao123/Unreal-MCP.git "C:/Program Files/Epic Games/UE_5.5/Engine/Plugins/Marketplace/UnrealMCP"
Step 2: Run the Setup Script
The setup script installs the unrealmcp pip package and creates the MCP config for your AI tool.
Windows:
cd Plugins\UnrealMCP
install.bat
macOS / Linux:
cd Plugins/UnrealMCP
bash install.sh
You can run the script from anywhere inside your project — it automatically detects the project root by searching upward for the .uproject file.
How Scope Works
The setup script asks where to create the MCP config:
| Scope | What it does | When to use |
|---|---|---|
| Project | Creates config in your project root (e.g., .mcp.json next to your .uproject) |
You only want UnrealMCP in this one project |
| Global | Creates config in your user folder (e.g., ~/.claude.json) |
You want UnrealMCP available in all projects |
If you run the script from inside an engine folder (e.g., Engine/Plugins/...), it only offers global scope — because engine-level plugins are shared across projects, so project-scope config doesn't make sense there.
If you run it from inside a project (anywhere under a folder with a .uproject), you get to choose between project scope and global scope.
Manual Setup (Without the Script)
If you prefer to set things up yourself:
# Install the MCP server globally
pip install unrealmcp
# Add to your AI tool's config (example for Claude Code .mcp.json):
# { "mcpServers": { "unreal": { "type": "stdio", "command": "unrealmcp" } } }
See Step 5: Configure Your AI Tool for the exact config format for each AI tool.
Manual Installation
Step 1: Copy the Plugin
Copy the UnrealMCP/ folder into your project's Plugins/ directory:
YourProject/
├── Content/
├── Source/
├── Plugins/
│ └── UnrealMCP/ ← put it here
│ ├── UnrealMCP.uplugin
│ ├── unrealmcp/ # Python MCP server (pip package)
│ └── Source/ # C++ bridge
└── YourProject.uproject
Step 2: Install Python Dependencies
pip install unrealmcp
Step 3: Regenerate Project Files
If you use Visual Studio or Rider, regenerate your project files so the new module is picked up:
# Windows (adjust path to your engine)
"<EnginePath>/Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe" \
-projectfiles \
-project="<YourProject>/YourProject.uproject" \
-game -engine
Step 4: Build and Launch the Editor
Build your project and open the editor. You should see this in the Output Log:
LogUnrealMCPBridge: MCP Bridge initialized on port 55557
This confirms the C++ bridge is running and ready for connections.
Step 5: Configure Your AI Tool
Each AI tool uses a slightly different config file and format. After installing via pip install unrealmcp, pick your tool below.
Tip: Since
unrealmcpis a global pip command, the same config works on Windows, macOS, and Linux — no platform-specific paths needed.
Claude Code — .mcp.json (project root)
{
"mcpServers": {
"unreal": {
"type": "stdio",
"command": "unrealmcp",
"args": [],
"env": {}
}
}
}
Claude Code is the only tool that requires "type": "stdio" explicitly.
Cursor — .cursor/mcp.json (project root)
{
"mcpServers": {
"unreal": {
"command": "unrealmcp",
"args": [],
"env": {}
}
}
}
VS Code / Copilot — .vscode/mcp.json (project root)
{
"servers": {
"unreal": {
"command": "unrealmcp",
"args": [],
"env": {}
}
}
}
Note: VS Code uses "servers", not "mcpServers".
Windsurf — ~/.codeium/windsurf/mcp_config.json (user-level)
{
"mcpServers": {
"unreal": {
"command": "unrealmcp",
"args": [],
"env": {}
}
}
}
Gemini CLI — .gemini/settings.json (project root)
{
"mcpServers": {
"unreal": {
"command": "unrealmcp",
"args": [],
"env": {}
}
}
}
JetBrains / Rider — .junie/mcp/mcp.json (project root)
{
"servers": [
{
"name": "unreal",
"command": "unrealmcp",
"args": [],
"env": {}
}
]
}
Note: JetBrains uses "servers" as an array with a "name" field. Requires IDE 2025.1+ with AI Assistant.
Zed — ~/.config/zed/settings.json
Add to your Zed settings.json:
{
"context_servers": {
"unreal": {
"source": "custom",
"command": {
"path": "unrealmcp",
"args": [],
"env": {}
}
}
}
}
Note: Zed uses "context_servers" with a nested "command" object.
Amazon Q — .amazonq/mcp.json (project root)
{
"mcpServers": {
"unreal": {
"command": "unrealmcp",
"args": [],
"env": {}
}
}
}
Step 6: Verify
Open your AI tool (e.g., Claude Code) in the project directory. The MCP server will auto-connect to the editor. You can verify with:
> Use the health_check tool
If it returns successfully, you're connected.
Configuration (Optional)
Custom Port
Add to Config/DefaultEngine.ini:
[UnrealMCP]
Port=55557
The bridge scans up to 100 ports from this base if the default is taken (useful when running multiple editor instances).
Environment Variable Override
set UNREAL_MCP_PORT=55560
Forces the Python server to connect to a specific port instead of reading from port.txt.
Token Debug Mode
Enable to see estimated token usage per command (useful for optimizing MCP calls):
> Use set_mcp_debug with enabled=true
> Use get_mcp_token_stats to see per-command statistics
Available Tools
UnrealMCP provides 100+ tools organized by category. Here's a summary of what you can do:
Core
| Tool | Description |
|---|---|
health_check |
Verify the bridge is running and responsive |
execute_python |
Run arbitrary Python in the editor (set result to return data) |
Asset Management
| Tool | Description |
|---|---|
find_assets |
Search the Asset Registry by class, path, or name pattern |
list_assets |
List assets in a Content Browser directory |
get_asset_info |
Get asset metadata (class, package, disk path) |
get_asset_properties |
Read all editable properties of any asset |
set_asset_property |
Set a single property on any asset |
find_references |
Find dependents or dependencies of an asset |
import_asset |
Import an external file (FBX, PNG, WAV, etc.) |
import_assets_batch |
Batch import from a file list or directory scan |
duplicate_asset |
Copy an asset to a new location |
rename_asset |
Rename/move an asset (auto-fixes references) |
delete_asset |
Delete an asset (checks for references first) |
save_asset / save_all |
Save one or all dirty assets |
open_asset |
Open an asset in the editor |
sync_browser |
Navigate Content Browser to an asset |
get_selected_assets |
Get currently selected Content Browser assets |
Blueprints
| Tool | Description |
|---|---|
search_parent_classes |
Find valid parent classes for Blueprint creation |
create_blueprint |
Create a Blueprint from any C++ or BP parent class |
compile_blueprint |
Compile a Blueprint |
read_blueprint_content |
Read full BP structure: graphs, variables, components |
add_component_to_blueprint |
Add a component (StaticMesh, Box Collision, etc.) |
create_blueprint_variable |
Create a variable in a Blueprint |
get/set_blueprint_class_defaults |
Read/write Class Default Object (CDO) properties |
get/set_blueprint_variable_properties |
Inspect/modify variable settings |
create/delete/rename_blueprint_function |
Manage Blueprint functions |
add_function_input / add_function_output |
Add parameters to functions |
get_blueprint_function_details |
Inspect function signatures and graphs |
Blueprint Graph
| Tool | Description |
|---|---|
add_blueprint_node |
Add a node (Branch, ForLoop, CallFunction, Print, etc.) |
add_event_node |
Add an event (BeginPlay, Tick, ActorBeginOverlap, etc.) |
connect_blueprint_nodes |
Wire two nodes together (execution or data pins) |
delete_blueprint_node |
Remove a node by ID |
set_blueprint_node_property |
Edit node properties (add pins, set enum, etc.) |
analyze_blueprint_graph |
Get structural analysis of a graph |
Materials
| Tool | Description |
|---|---|
create_material |
Create a new material with blend/shading mode |
create_material_instance |
Create a Material Instance with parameter overrides |
build_material_graph |
Build a complete node graph atomically (nodes + connections) |
get_material_info |
Inspect material properties, parameters, textures |
set_material_properties |
Set blend mode, shading model, two-sided, etc. |
add/delete/move/duplicate_material_expression |
Manage expression nodes |
connect_material_expressions |
Wire expression outputs to inputs |
set_material_expression_property |
Set properties on expression nodes |
layout_material_expressions |
Auto-layout expression nodes |
recompile_material |
Force recompile and save |
get/set_material_instance_parameter |
Read/write MI parameter overrides |
list_material_expression_types |
Discover available expression types |
add_material_comments |
Add comment boxes to the material graph |
apply_material_to_actor / apply_material_to_blueprint |
Apply materials |
get_available_materials |
List materials in project or engine |
Data Tables
| Tool | Description |
|---|---|
get_data_table_schema |
Get column names and types from the row struct |
get_data_table_rows / get_data_table_row |
Read all or one row |
add_data_table_row |
Add a row with optional initial data |
update_data_table_row |
Partial update of row fields |
delete_data_table_row |
Delete a row |
duplicate_data_table_row |
Copy a row under a new name |
rename_data_table_row |
Rename a row in-place |
Data Assets
| Tool | Description |
|---|---|
create_data_asset |
Create any UDataAsset subclass with initial properties |
get_data_asset_properties |
Read all properties (with optional filter) |
set_data_asset_property / set_data_asset_properties |
Set one or many properties |
list_data_assets |
Browse by path or class |
list_data_asset_classes |
List all loaded UDataAsset subclasses |
get_property_valid_types |
Query valid dropdown/enum values for a property |
Actors & Level
| Tool | Description |
|---|---|
spawn_actor |
Spawn an actor (StaticMeshActor, PointLight, etc.) |
spawn_blueprint_actor |
Spawn a Blueprint actor instance in the level |
get_actors_in_level |
List all actors in the current level |
find_actors_by_name |
Find actors by name pattern |
get_actor_properties |
Read all properties from a placed actor |
set_actor_transform |
Set location, rotation, and/or scale |
delete_actor |
Delete an actor from the level |
get_selected_actors |
Get currently selected viewport actors |
get_world_info |
Get level name, actor count, etc. |
set_static_mesh_properties |
Set mesh on a component |
set_physics_properties |
Configure physics simulation |
set_mesh_material_color |
Set material color on a mesh component |
take_screenshot |
Capture viewport or editor window to PNG |
Enhanced Input
| Tool | Description |
|---|---|
create_input_action |
Create a UInputAction (Boolean/Axis1D/2D/3D) |
get/set_input_action_properties |
Read/write action properties |
add/remove_input_action_trigger |
Manage triggers (Hold, Pressed, Tap, etc.) |
add/remove_input_action_modifier |
Manage modifiers (DeadZone, Negate, Scalar, etc.) |
create_input_mapping_context |
Create a UInputMappingContext |
get_input_mapping_context |
Read all key mappings |
add/remove/set_key_mapping |
Manage key-to-action mappings |
add/remove_mapping_trigger / add/remove_mapping_modifier |
Per-mapping overrides |
list_input_actions / list_input_mapping_contexts |
Browse input assets |
list_trigger_types / list_modifier_types / list_input_keys |
Discover available types |
Widgets (UMG)
| Tool | Description |
|---|---|
get_widget_tree |
Read full widget hierarchy as JSON |
add_widget |
Add a widget to a parent slot |
remove_widget / move_widget / rename_widget / duplicate_widget |
Manage widgets |
get/set_widget_properties |
Read/write widget properties |
get/set_slot_properties |
Read/write layout slot properties |
list_widget_types |
Discover available UWidget classes |
Performance Profiling
| Tool | Description |
|---|---|
performance_start_trace |
Start recording a live .utrace (CPU, GPU, frame, etc.) |
performance_stop_trace |
Stop recording and auto-load for analysis |
performance_analyze_insight |
Query loaded traces with smart analysis |
Smart analysis queries:
diagnose— full automated report with severity findingsspikes— worst frames with category breakdownflame— top timers by exclusive (self) timebottlenecks— auto-categorize frame into Animation/Slate/Network/etc.hotpath— drill into a category's children by timecompare— compare a frame vs trace mediansearch— find a timer across all frames (min/avg/max/p95/p99)histogram— frame time distribution
Standard queries: summary, worst_frames, frame_details, timer_stats, butterfly, threads, counters
Provider queries (require specific trace channels): net_stats, loading, logs, memory, regions, bookmarks, session, modules, file_io, tasks, allocations, context_switches, screenshots, stack_samples
Debug
| Tool | Description |
|---|---|
set_mcp_debug |
Enable/disable token estimation debug headers |
get_mcp_token_stats |
Per-command token usage statistics |
Usage Examples
Create a Material
Create a red metallic material at /Game/Materials/M_RedMetal
with roughness 0.3 and metallic 1.0
The AI will call create_material, then build_material_graph to wire up constant nodes to Base Color, Metallic, and Roughness pins.
Spawn Actors
Spawn 5 point lights in a circle around the origin at height 300
The AI will call spawn_actor with actor_type: "PointLight" five times with calculated positions.
Blueprint Creation
Create a Blueprint actor called BP_HealthPickup based on Actor,
add a Sphere Collision component and a Static Mesh component,
set it up so on BeginOverlap it prints "Health Picked Up"
The AI will use create_blueprint, add_component_to_blueprint, add_event_node, add_blueprint_node, and connect_blueprint_nodes.
Profile Performance
Start a performance trace, play for 10 seconds, stop it,
then diagnose the bottlenecks
The AI will call performance_start_trace, wait, performance_stop_trace, then performance_analyze_insight with query: "diagnose".
Data Table Management
Show me the schema of DT_Items, then add a new row called
"IronIngot" with StackSize 100
The AI will call get_data_table_schema, then add_data_table_row with the appropriate data.
Architecture
Plugin Structure
Plugins/UnrealMCP/
├── UnrealMCP.uplugin # Plugin manifest
├── pyproject.toml # pip package config
├── unrealmcp/ # Python MCP server (pip install unrealmcp)
│ ├── __init__.py # Entry point (unrealmcp command)
│ ├── _bridge.py # Shared FastMCP instance
│ ├── _tcp_bridge.py # TCP communication layer
│ └── tools/ # Tool modules (one per category)
│ ├── __init__.py
│ ├── core.py # health_check, execute_python
│ ├── assets.py # Asset management
│ ├── blueprints.py # Blueprint creation & components
│ ├── blueprint_graph.py # Graph node manipulation
│ ├── materials.py # Material creation & graphs
│ ├── editor_commands.py # Actors, physics, screenshots
│ ├── data_tables.py # Data Table CRUD
│ ├── data_assets.py # Data Asset CRUD
│ ├── widgets.py # Widget tree manipulation
│ ├── enhanced_input.py # Input Actions & Mapping Contexts
│ ├── level.py # Level info & actor selection
│ ├── profiling.py # Performance tracing & analysis
│ └── debug.py # Token stats & debug mode
└── Source/UnrealMCPBridge/
├── Public/
│ ├── EpicUnrealMCPBridge.h # Main subsystem (UEditorSubsystem)
│ ├── MCPServerRunnable.h # TCP server thread
│ └── Commands/ # Command handler headers
└── Private/
├── EpicUnrealMCPBridge.cpp # Subsystem implementation
├── EpicUnrealMCPModule.cpp # Module startup
├── MCPServerRunnable.cpp # Server thread implementation
└── Commands/ # Command handler implementations
Communication Protocol
The C++ bridge and Python server communicate over TCP using length-prefix framing:
[4 bytes: big-endian payload length] [N bytes: UTF-8 JSON]
Request format:
{
"type": "create_material",
"params": {
"name": "M_Example",
"path": "/Game/Materials"
}
}
Response format:
{
"status": "success",
"result": { ... }
}
Port Discovery
- C++ bridge starts TCP listener on configured port (default
55557) - Writes the actual port number to
<ProjectDir>/Saved/UnrealMCP/port.txt - Python server reads that file on connection
- If the default port is taken, the bridge scans up to 100 ports
This means multiple editor instances can run simultaneously without conflicts.
Adding Custom Tools
Python Side
Create a new file in unrealmcp/tools/:
# unrealmcp/tools/my_tools.py
from unrealmcp._bridge import mcp
from unrealmcp._tcp_bridge import _call
@mcp.tool()
def my_custom_tool(param1: str, param2: int = 10) -> str:
"""Description shown to the AI assistant."""
return _call("my_custom_command", {
"param1": param1,
"param2": param2,
})
Register it in unrealmcp/tools/__init__.py:
from unrealmcp.tools import my_tools # noqa: F401
C++ Side
- Create a command handler class in
Source/UnrealMCPBridge/Private/Commands/ - Implement the command routing logic
- Register the handler in
UEpicUnrealMCPBridge::ExecuteCommand()
The C++ handler receives the params JSON object and returns a JSON result. All editor operations should be executed on the game thread (use AsyncTask(ENamedThreads::GameThread, ...) if called from the TCP thread).
Troubleshooting
"Connection refused" or tools not working
- Make sure the UE5 editor is running
- Check the Output Log for
LogUnrealMCPBridge: MCP Bridge initialized on port XXXXX - Verify
Saved/UnrealMCP/port.txtexists and contains a port number - Check that
PythonScriptPluginis enabled in your.uproject
Python import errors
pip install fastmcp requests
Make sure the Python on your PATH is the same one your AI tool will invoke.
Multiple editor instances
Each editor instance picks a unique port automatically. The .mcp.json config connects to whichever editor wrote port.txt most recently. If you need to target a specific instance, set the UNREAL_MCP_PORT environment variable.
Plugin not loading
- Verify
UnrealMCP.upluginhas"Type": "Editor"in its module definition - Check that
PythonScriptPluginandEditorScriptingUtilitiesare available in your engine build - Look for errors in the Output Log at editor startup
Commands timing out
Large operations (profiling analysis, complex Blueprint graphs) have a 300-second timeout. If you hit it, break the operation into smaller steps.
Supported AI Tools
UnrealMCP works with any tool that supports the Model Context Protocol:
| Tool | Config File | Status |
|---|---|---|
| Claude Code | .mcp.json |
Tested |
| Cursor | .cursor/mcp.json |
Tested |
| VS Code / Copilot | .vscode/mcp.json |
Supported |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
Supported |
| Gemini CLI | .gemini/settings.json |
Supported |
| JetBrains / Rider | .junie/mcp/mcp.json |
Supported |
| Zed | ~/.config/zed/settings.json |
Supported |
| Amazon Q | .amazonq/mcp.json |
Supported |
See Step 5: Configure Your AI Tool for the exact config format for each tool.
Contributing
Contributions are welcome! Whether it's bug fixes, new tools, documentation, or feature ideas — feel free to get involved.
- Found a bug? Open an issue
- Have a feature idea? Open an issue and describe what you'd like
- Want to contribute code? Fork the repo, make your changes, and open a Pull Request
See CONTRIBUTING.md for detailed guidelines on submitting PRs and adding new tools.
License
MIT — see LICENSE for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file unrealmcp-1.1.0.tar.gz.
File metadata
- Download URL: unrealmcp-1.1.0.tar.gz
- Upload date:
- Size: 44.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24e9e81ff8c47c2de602f60a9e5891efb9af351c0b92942858c548c367ed25d5
|
|
| MD5 |
6ac9294c537cd5bccd5ac91fe558c903
|
|
| BLAKE2b-256 |
980d612777b970cf97b9c8379526d454f1e41aa624c54607da5b9e52c0e0e56e
|
File details
Details for the file unrealmcp-1.1.0-py3-none-any.whl.
File metadata
- Download URL: unrealmcp-1.1.0-py3-none-any.whl
- Upload date:
- Size: 42.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3108e85985b24026df9349be7699b6ceaac01505fcc277207e5db0f547248195
|
|
| MD5 |
93938dcc94a6bbd970661381296b10bf
|
|
| BLAKE2b-256 |
4acf98ccb901cb45afae811aaf25bb2f21d7483045d3b1983e3685796447d479
|