PythonMCP-UEFN
Exposes the Unreal Editor for Fortnite to AI assistants via MCP, enabling actor manipulation, device property editing, Verse building, and more through a Python bridge.
README
PythonMCP-UEFN
Drive Unreal Editor for Fortnite from any MCP client over a local Python bridge.
This is a Model Context Protocol server that exposes the UEFN editor to an AI assistant. With it, an assistant can spawn and move actors, browse and validate assets, read and write device options, run arbitrary editor Python, trigger a Verse build and read the compile result, all without anyone touching the mouse.
It ships 39 tools. The interesting part is the device bridge: it reads and writes the @editable Verse properties that the standard unreal Python API refuses to surface by name. More on that below.
How it works
There are two halves. A listener that runs inside UEFN, and an MCP server that runs on your machine and talks to it.
MCP client (Claude Code, or any MCP host)
|
| stdio
v
mcp_server.py host process, this repo
|
| HTTP POST -> 127.0.0.1:8765
v
uefn_listener.py runs inside the UEFN editor
|
| game thread (slate post-tick callback)
v
unreal.* editor scripting API
The listener is a ThreadingHTTPServer bound to 127.0.0.1:8765. The HTTP thread only enqueues work. A slate post tick callback drains that queue on the game thread, because the unreal API is not thread safe and will crash if you call it from anywhere else. A watchdog re-arms the tick and the accept loop after a world or map change, and on a full project reopen the init_unreal hook re-runs the module. The whole listener is one self-contained file so you can paste it straight into Execute Python Script.
On the host side, transport.py adds retry with backoff, per-tool timeouts, and error classification. When something goes wrong it tells you whether the listener is down (socket refused) or wedged (reachable but the game thread stopped draining), so the failure message points at the actual fix.
Requirements
Host:
- Python 3.11
- The
mcppackage (pip install -r requirements.txt)
Editor:
- UEFN with Python editor scripting enabled (experimental, UEFN 40.40 or newer)
The listener itself has no third party dependencies. It uses only the standard library plus the unreal module that UEFN provides.
Setup
1. Install the host dependencies
pip install -r requirements.txt
2. Register the server with your MCP client
For Claude Code:
claude mcp add uefn --scope user -- python /absolute/path/to/PythonMCP-UEFN/mcp_server.py
For any other MCP host, point it at the same command. The server speaks stdio.
{
"mcpServers": {
"uefn": {
"command": "python",
"args": ["/absolute/path/to/PythonMCP-UEFN/mcp_server.py"]
}
}
}
3. Start the listener inside UEFN
Open your project, then Tools > Execute Python Script and pick uefn_listener.py. It binds the port and starts serving.
To confirm it is up, call the ping tool from your assistant (it returns {pong, uefn, tools}), or open http://127.0.0.1:8765/health in a browser.
4. Optional: start the listener automatically
Running the script by hand every session gets old. Install an autostart hook into your project:
python install_autostart.py "C:\path\to\YourProject"
That writes Content/Python/init_unreal.py into the project, so the listener comes up on its own whenever you open it.
Usage
Once the server is registered and the listener is running, ask your assistant to work in the level. A request like "spawn a cube at the origin and frame the camera on it" turns into:
spawn_static_mesh mesh_path=/Engine/BasicShapes/Cube location={x:0,y:0,z:0}
focus_on_actor actor=<the new actor>
Reading and writing a device option works the same way:
device_list_options label="My Trigger"
device_set_option label="My Trigger" option="EnabledAtGameStart" value=false
When you need something no tool covers, execute_python runs arbitrary code in the editor with the unreal module already in scope. Assign your return value to _result.
Tools
Session and level
| Tool | Purpose |
|---|---|
ping |
Health check. Returns pong, uefn flag, tool count. |
get_current_level |
Current level name and asset path. |
save_level |
Save the current level. |
save_all |
Save every dirty level and asset under /Game. |
load_level |
Load a level by path. |
diagnostics |
Listener health snapshot: uptime, last tick age, accept loop, port, world, autostart. |
Actors
| Tool | Purpose |
|---|---|
spawn_actor |
Spawn an actor from a class path. |
spawn_static_mesh |
Spawn a StaticMeshActor from a mesh asset. |
list_actors |
List actors, optionally filtered by class or label. |
delete_actors |
Delete actors by label or path. |
set_actor_transform |
Set location, rotation, scale. |
get_actor_transform |
Read a transform. |
set_actor_label |
Rename an actor in the Outliner. |
duplicate_actor |
Duplicate, with an optional offset and new label. |
select_actors |
Replace the editor selection. |
get_selected_actors |
Read the current selection. |
focus_on_actor |
Frame the viewport on an actor. |
Viewport
| Tool | Purpose |
|---|---|
get_viewport_camera |
Read the viewport camera transform. |
set_viewport_camera |
Set the viewport camera transform. |
Assets
| Tool | Purpose |
|---|---|
list_assets |
List asset paths under a folder. |
find_asset |
Substring search for assets. |
load_asset |
Load an asset and return its class and name. |
asset_exists |
Check whether an asset exists. |
create_folder |
Create a content folder. |
validate_assets |
Run the editor validator. Catches publish time strips before you push. |
describe_class |
Resolve a class by path and return its name and super. |
Devices
| Tool | Purpose |
|---|---|
list_editor_properties |
List the editor properties exposed on an actor. |
set_device_property |
Set one editor property on a device. |
set_device_properties_bulk |
Apply many updates in one undo group. |
device_scan |
Scan a custom Verse device once to cache its mangled @editable names. |
device_list_options |
List readable option names and values. Auto detects native versus Verse. |
device_get_option |
Read one option by its author facing name. |
device_set_option |
Write a scalar option. Returns the value read back. |
device_wire |
Wire a Verse reference field to another actor. |
device_set_prop_array |
Set a Verse array of reference fields to a set of actors. |
Verse build
| Tool | Purpose |
|---|---|
verse_build_trigger |
Trigger a Verse build without a manual key press. |
verse_compile_status |
Read the latest compile verdict and errors from the editor log. |
Python and autostart
| Tool | Purpose |
|---|---|
execute_python |
Run arbitrary Python in the editor. Assign to _result to return a value. |
install_autostart |
Write the autostart hook into a project. |
The device bridge
A Fortnite device places its author written @editable Verse fields on a BlueprintGeneratedClass. The friendly name you wrote in Verse does not exist as a settable property. The fields live under mangled internal names of the form __verse_0x<hash>_<name>, and that hash changes on every recompile, so you cannot hardcode it.
The bridge recovers the mapping by dumping the placed device to T3D and matching the mangled names with a regex, then caches the result in _device_options_cache.json next to the listener. After that, the device_* tools let you read and write those fields by their real names. Native Epic devices expose clean properties and need no scan. Custom Verse devices need device_scan run once with the device configured, so the dump has values to recover.
The full background, including the editor Python limitations that made this necessary, is written up in docs/UEFN_Python_API_gaps.md.
Limitations
- Editor only. Python here cannot run gameplay. Runtime logic stays in Verse.
- One editor instance. The port
8765is fixed. - Do not issue tool calls while a Launch Session is starting. A racing call can abort the socket and trip asset validation with a false failure.
- The device introspection surface in the editor Python API is thin. The bridge works around it rather than relying on official support, so expect rough edges as UEFN changes.
Project layout
mcp_server.py host MCP server, tool schemas, routing
transport.py host HTTP client, retry, timeouts, error classification
uefn_listener.py listener that runs inside UEFN, self-contained
install_autostart.py writes the project autostart hook
init_unreal_template.py template for Content/Python/init_unreal.py
tests/ transport tests, no UEFN needed
docs/ UEFN Python API gaps report
Development
The transport layer runs without UEFN, so its tests run anywhere:
python -m unittest discover tests
The listener and the server import unreal and mcp, so a full end to end run needs UEFN open with the listener started.
License
MIT. See LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.