uefn-mcp

uefn-mcp

A two-process MCP bridge for Unreal Editor for Fortnite that lets Claude Code, Cursor, and other MCP clients drive a live UEFN editor safely.

Category
Visit Server

README

uefn-mcp

Python 3.10+ UEFN MCP

A two-process MCP bridge for Unreal Editor for Fortnite that lets Claude Code, Cursor, and other MCP clients drive a live UEFN editor safely.

MCP client (Claude Code / Cursor / custom host)
    │
    │ stdio
    ▼
server/main.py  ── FastMCP host process
    │
    │ HTTP 127.0.0.1:8765-8770
    ▼
Content/Python/uefn_tools/tools/mcp_bridge.py
    │
    │ queue + Slate tick callback
    ▼
UEFN editor main thread -> unreal.* -> 354 registered uefn_tools actions

Quick setup

git clone https://github.com/quangdang46/uefn-verse-mcp.git
cd uefn-verse-mcp
python -m pip install -r requirements.txt
python deploy.py --project "MyIsland"

There is no packaged one-line installer yet. The supported path today is source checkout plus local deploy into a UEFN project.

TL;DR

The Problem

UEFN's Python layer is powerful, but it is a bad place to host a modern MCP server directly:

  • unreal.* calls must run on the editor main thread.
  • Blocking Python code can freeze the editor.
  • The MCP SDK belongs in a normal host Python runtime, not inside the editor sandbox.

The Solution

uefn-mcp splits the system in two:

  • server/main.py runs externally as a FastMCP stdio server.
  • Content/Python/uefn_tools/tools/mcp_bridge.py runs inside UEFN as a local HTTP listener.
  • Commands are queued and drained on Slate ticks so editor API calls stay on the main thread.

Why Use uefn-mcp?

Capability What it gives you
31 direct MCP tools A curated surface for actors, assets, project info, viewport, logs, and status
354 run_tool entries An escape hatch into the full uefn_tools registry without re-wrapping every action as first-class MCP
Main-thread-safe dispatch unreal.* work is queued and executed on editor ticks instead of from the HTTP thread
Auto port discovery The host scans ports 8765-8770 and reconnects automatically if the listener moved
Generic UEFN loader init_unreal.py auto-loads any package under Content/Python/ that exposes register()
Deployment helper deploy.py copies the package and keeps .urcignore aligned for editor-only Python files

The live inventory is tracked in FEATURES.md, and deeper engine constraints are documented in docs/UEFN_QUIRKS.md.

Origins and Credits

This repo sits on top of two upstream lines:

  • UEFN Toolbelt — broad in-editor uefn_tools registry and tooling: UEFN-TOOLBELT (Ocean Bennett).
  • External MCP + in-editor listener — architecture and code lineage from KirChuvakov’s MIT-licensed projects (commonly referenced as uefn-mcp-server or uefn-verse-server).

This fork keeps both ideas, but reshapes them into an MCP-first repo:

  • external FastMCP host process in server/
  • in-editor HTTP bridge in Content/Python/uefn_tools/tools/mcp_bridge.py
  • curated direct MCP surface plus a registry escape hatch

License

Licensing is documented in LICENSE. In short:

  • Combined distribution: This repository is offered under GNU AGPL v3.0 with UEFN Toolbelt’s additional visible-attribution term (copyleft; network use triggers source-sharing obligations — see the license file and the AGPL-3.0 text).

  • Upstream MIT components: Portions derived from KirChuvakov’s work were originally under the MIT License; their copyright and permission notice must stay intact in copies of this project (also reproduced in LICENSE).

  • Forks and derivatives: If you ship something built on this codebase or its architecture, include the visible Toolbelt credit required in LICENSE (for example in README, docs, store page, or an in-editor credits panel):

    Built on UEFN Toolbelt by Ocean Bennett
    (https://github.com/undergroundrap/UEFN-TOOLBELT)
    

    …or an equivalent that names Ocean Bennett and links to that repository.

This is not legal advice; read LICENSE for full terms.

Quick Example

The fastest end-to-end workflow is:

git clone https://github.com/quangdang46/uefn-verse-mcp.git
cd uefn-verse-mcp
python -m pip install -r requirements.txt
python deploy.py --project "MyIsland"
# In the UEFN Python console
import uefn_tools as ut; ut.register(); ut.run("mcp_start")
// In your MCP client config (.mcp.json)
{
  "mcpServers": {
    "uefn": {
      "command": "python",
      "args": ["C:\\path\\to\\uefn-verse-mcp\\server\\main.py"]
    }
  }
}

Once the client reconnects, the typical first calls look like this:

ping()
get_project_info()
get_all_actors()
spawn_actor(class_path="/Game/Blueprints/BP_Cube.BP_Cube_C", location=[0, 0, 200])
set_viewport_camera(location=[-800, 0, 400], rotation=[-15, 0, 0])
list_tools(category="Materials")
describe_tool("material_gradient_painter")
run_tool("arena_generate", kwargs={"size": "large", "teams": True})
run_tool("smoke_test")

Examples above use conceptual MCP call syntax. The tool names and parameters match the real FastMCP surface exported by server/main.py.

Design Philosophy

1. Keep the MCP SDK outside UEFN

The host process uses ordinary Python and mcp>=1.2.0. UEFN only needs the local listener and the tool registry.

2. Never call unreal.* from the wrong thread

The HTTP server runs on a daemon thread, but every editor action is queued and drained on the Slate post-tick callback. That is the safety boundary that keeps automation from fighting the editor event loop.

3. Curate the common path, keep the full escape hatch

The direct MCP surface covers the most common actor, asset, level, and viewport workflows. run_tool, list_tools, and describe_tool expose the deeper registry when you need specialized behavior.

4. Make deploys boring

The intended setup is:

  1. Copy uefn_tools/ and init_unreal.py into the target project.
  2. Start the bridge in the editor.
  3. Point the MCP client at server/main.py.

No editor-side package installation and no IDE-specific glue should be required beyond that.

Comparison

Approach MCP-native Full registry access Main-thread safety model Best for
Ad hoc UEFN Python scripts No No You own every threading mistake One-off local editor tasks
Minimal custom HTTP bridge Partial Usually narrow Depends on your implementation Small, fixed editor automations
uefn-mcp Yes Yes, via run_tool Queue + Slate tick dispatch AI-agent-driven UEFN editing and experimentation

Prerequisites

  • UEFN on Windows, with the Python Editor Script Plugin enabled
  • Host Python 3.10 or newer for server/main.py, deploy.py, and the MCP dependency
  • A local UEFN project you can copy Content/Python/ files into

Installation

Option 1: deploy.py (recommended)

deploy.py is the clean MCP-first path.

python -m pip install -r requirements.txt
python deploy.py --project "MyIsland"

You can also deploy by full path:

python deploy.py --path "D:\\Projects\\MyIsland"

If you omit both flags, deploy.py will prompt you interactively.

Link mode (opt-in, local dev only)

For fast local iteration you can link uefn_tools/ instead of copying it. Edits in the repo checkout are then immediately visible to UEFN without redeploying.

python deploy.py --project "MyIsland" --link-kind junction
python deploy.py --path "D:\\Projects\\MyIsland" --link-kind symlink
--link-kind Behavior Privileges
junction Windows directory junction (recommended on Windows) No special privileges required
symlink OS-native symbolic link May need Developer Mode or admin on Windows

init_unreal.py is always copied as a real file regardless of link mode.

Note: Link mode is a local development convenience. Do not use it for shared or team projects — use the default copy mode instead.

What it installs:

  • Content/Python/uefn_tools/
  • Content/Python/init_unreal.py
  • .urcignore entry for Content/Python/*

Option 2: deploy.bat (Windows interactive helper)

If you prefer a Windows batch workflow:

deploy.bat

This is still present as a helper, but the repo's documented MCP-first path is deploy.py.

Option 3: Manual install

If you need full control:

  1. Copy Content/Python/uefn_tools/ into your project at Content/Python/uefn_tools/.
  2. Copy init_unreal.py into your project at Content/Python/init_unreal.py.
  3. Install host dependencies:
python -m pip install -r requirements.txt
  1. Ensure the project root .urcignore includes:
Content/Python/*

Not Recommended: install.py

install.py still contains older Toolbelt/UI-era behavior. Use deploy.py for the current MCP-first workflow.

Quick Start

  1. Clone the repo.
git clone https://github.com/quangdang46/uefn-verse-mcp.git
cd uefn-verse-mcp
  1. Install the host dependency into the same Python interpreter your MCP client will use.
python -m pip install -r requirements.txt
  1. Deploy the UEFN-side package.
python deploy.py --project "MyIsland"
  1. Start the listener inside UEFN.
import uefn_tools as ut
ut.register()
ut.run("mcp_start")
  1. Add the server to your MCP client config.
{
  "mcpServers": {
    "uefn": {
      "command": "python",
      "args": ["C:\\path\\to\\uefn-verse-mcp\\server\\main.py"]
    }
  }
}
  1. Verify the connection.
ping()
get_status()
run_tool("smoke_test")
  1. Start editing the level from your MCP client.
get_all_actors()
search_assets(class_name="StaticMesh", directory="/Game", recursive=True)
spawn_actor(class_path="/Game/Blueprints/BP_Cube.BP_Cube_C", location=[0, 0, 100])

Command Reference

System

Tool What it does Example
ping Confirms the host can reach the in-editor bridge ping()
get_status Returns listener status and bridge metadata get_status()
execute_python Executes arbitrary Python inside the UEFN editor runtime execute_python(code="result = {'status': 'ok'}")
get_log Returns recent bridge log lines get_log(lines=100)
shutdown Stops the in-editor listener shutdown()

Actors

Tool What it does Example
get_all_actors Lists actors in the current level get_all_actors()
get_selected_actors Reads the current editor selection get_selected_actors()
spawn_actor Spawns an actor from a class or object path spawn_actor(class_path="/Game/Blueprints/BP_Cube.BP_Cube_C", location=[0, 0, 100])
delete_actors Deletes actors by label delete_actors(actor_labels=["Cube_1", "Cube_2"])
set_actor_transform Updates actor location, rotation, and/or scale set_actor_transform(actor_label="Cube_1", location=[200, 0, 100])
get_actor_properties Reads properties for a named actor get_actor_properties(actor_label="Cube_1")
set_actor_properties Writes multiple actor properties set_actor_properties(actor_label="Cube_1", properties={"mobility": "Static"})
select_actors Selects actors in the editor select_actors(actor_labels=["Cube_1"])
focus_selected Moves the viewport to the active selection focus_selected()

Assets

Tool What it does Example
list_assets Lists assets in a directory list_assets(directory="/Game", recursive=True)
get_asset_info Reads details for a specific asset path get_asset_info(asset_path="/Game/MyFolder/MyAsset")
get_selected_assets Returns selected Content Browser assets get_selected_assets()
rename_asset Renames or moves an asset rename_asset(old_path="/Game/Old", new_path="/Game/New")
delete_asset Deletes an asset delete_asset(asset_path="/Game/Trash/TempAsset")
duplicate_asset Copies an asset to a new path duplicate_asset(source_path="/Game/A", dest_path="/Game/B")
does_asset_exist Checks if an asset exists does_asset_exist(asset_path="/Game/Props/SM_Crate")
save_asset Saves a dirty asset save_asset(asset_path="/Game/Props/SM_Crate")
search_assets Searches the Asset Registry with directory and class filters search_assets(class_name="Material", directory="/Game", recursive=True)

Project / Level

Tool What it does Example
get_project_info Returns project metadata get_project_info()
save_current_level Saves the current level save_current_level()
get_level_info Returns summary info about the active level get_level_info()

Viewport

Tool What it does Example
get_viewport_camera Reads the editor camera position and rotation get_viewport_camera()
set_viewport_camera Moves the editor camera set_viewport_camera(location=[-800, 0, 400], rotation=[-15, 0, 0])

Escape Hatch

Tool What it does Example
run_tool Executes any registered uefn_tools action by name run_tool("arena_generate", kwargs={"size": "large"})
list_tools Lists all registered tools, optionally by category list_tools(category="Materials")
describe_tool Returns description and parameters for one tool describe_tool("material_gradient_painter")

Working With the Full Registry

The direct MCP surface is intentionally small. The deeper workflows are meant to be discovered dynamically:

list_tools()
list_tools(category="Verse Helpers")
describe_tool("device_call_method")
run_tool("device_call_method", kwargs={"class_filter": "TimerObjective", "method": "blueprint_pause"})

The full generated inventory lives in FEATURES.md.

Configuration

.mcp.json

Use the same Python interpreter here that you used for python -m pip install -r requirements.txt.

{
  "mcpServers": {
    "uefn": {
      "command": "python",
      "args": ["C:\\dev\\uefn-verse-mcp\\server\\main.py"]
    }
  }
}

Environment Variables

Variable Default Purpose
UEFN_MCP_REQUEST_TIMEOUT 30 Default timeout in seconds for bridge requests
UEFN_MCP_LONG_TOOL_TIMEOUT 900 Timeout for long-running run_tool calls that opt into the extended budget

Port Behavior

  • The in-editor listener binds to the first available port in 8765-8770.
  • The host discovers the active port by probing http://127.0.0.1:<port>/.
  • If the cached port stops responding, the host rescans automatically.

UEFN Loader Contract

init_unreal.py is intentionally generic:

  • it adds Content/Python/ to sys.path
  • it discovers packages with __init__.py
  • it calls register() when available

That means uefn_tools is only one possible package. The loader is reusable for other editor-side Python packages in the same project.

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│ MCP client                                                          │
│ Claude Code / Cursor / custom FastMCP host                          │
└──────────────────────────────────────────────────────────────────────┘
                                │
                                │ stdio
                                ▼
┌──────────────────────────────────────────────────────────────────────┐
│ server/main.py                                                      │
│ - FastMCP server                                                    │
│ - 31 direct tools                                                   │
│ - run_tool / list_tools / describe_tool                             │
└──────────────────────────────────────────────────────────────────────┘
                                │
                                │ HTTP JSON POST
                                ▼
┌──────────────────────────────────────────────────────────────────────┐
│ Content/Python/uefn_tools/tools/mcp_bridge.py                       │
│ - Local HTTP listener inside the UEFN process                       │
│ - Queue-based handoff from HTTP thread to editor main thread        │
│ - Bridge commands: system, actors, assets, viewport, escape hatch   │
└──────────────────────────────────────────────────────────────────────┘
                                │
                                │ Slate post-tick callback
                                ▼
┌──────────────────────────────────────────────────────────────────────┐
│ UEFN editor main thread                                             │
│ - Executes unreal.* calls safely                                    │
│ - Reads and writes level / assets / viewport                        │
│ - Invokes 354 registered uefn_tools actions                         │
└──────────────────────────────────────────────────────────────────────┘

Important files:

File Responsibility
server/main.py External FastMCP entrypoint
server/bridge.py Host-side HTTP client for the in-editor listener
server/port_discovery.py Port probing across 8765-8770
Content/Python/uefn_tools/tools/mcp_bridge.py In-editor HTTP server and queue dispatcher
Content/Python/uefn_tools/__init__.py Package root, registry setup, plugin loading
deploy.py Project deployment and .urcignore maintenance
init_unreal.py Generic UEFN Python package loader

For a shorter architecture note, see ARCHITECTURE.md.

Troubleshooting

Symptom Likely cause Fix
No module named 'mcp' Your MCP client is running a different Python than the one you installed into Install requirements.txt into the exact interpreter used by the MCP command
UEFN listener not found on ports 8765-8770 The in-editor bridge is not running In the UEFN console, run import uefn_tools as ut; ut.register(); ut.run("mcp_start")
Commands fail right after deploy The package was copied into the project, but the editor has not loaded it yet Re-run ut.register() manually, or restart UEFN if you changed init_unreal.py
The editor freezes during custom automation Blocking code is running on the main thread Avoid time.sleep() and long synchronous loops in editor-side code; keep work queued and tick-driven
Asset or project paths resolve strangely in init_unreal.py UEFN path helpers do not always point where you expect during startup Use the file-system path of init_unreal.py itself rather than unreal.Paths.project_content_dir()
run_tool works locally but returns unusable data to the client A tool is returning None, a primitive, or a live Unreal object instead of a JSON-friendly result Make the tool return a structured dict, preferably with a "status" field

Limitations

  • This repo does not make UEFN headless. You still need a live local editor session.
  • The direct MCP surface is curated; deeper workflows rely on run_tool.
  • The 354-tool registry is broad, but not every entry has been verified in every environment yet. See the status column in FEATURES.md.
  • UEFN Python has engine-specific quirks and unsafe APIs. Some operations that are fine in full Unreal Engine are limited or crash-prone in UEFN.
  • The documented install path is source-based. There is no PyPI, Homebrew, winget, or standalone installer release flow documented here today.

FAQ

Do I need to install anything inside UEFN's embedded Python?

No for the MCP server itself. The mcp dependency belongs in the external host Python that runs server/main.py.

Why not run the MCP SDK directly inside the editor?

Because the editor runtime is the wrong place for a long-lived stdio server and blocking automation. The two-process split is the safety boundary.

What should I call first after connecting?

ping(), then get_status(), then either get_project_info() or run_tool("smoke_test").

How do I access the specialized tools?

Use list_tools() to discover categories, describe_tool() to inspect parameters, and run_tool() to execute the chosen action.

Can I use this without Claude Code?

Yes. Any MCP client that can launch a stdio server can point at server/main.py.

Do I have to restart UEFN after every change?

No. Most package changes can be reloaded with ut.register(). Changes to startup loader behavior in init_unreal.py are the ones most likely to require a restart.

Where should I look if UEFN behavior seems weird?

Start with docs/UEFN_QUIRKS.md. That file captures the non-obvious engine behavior this repo is already compensating for.

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured