Atlas / MCP servers / kirchuvakov / UEFN Remote Control

UEFN Remote ControlBLOCK

mcp/kirchuvakov/uefn-remote-control

MCP server for controlling UEFN (Unreal Editor for Fortnite) from Claude Code — 22 tools for actors, assets, levels, viewport, and Python execution

Verdict
BLOCK
Grade
D
Trust score
66 /100
Exposed tools
103 53r · 42w · 8d
Transport
—
License
MIT
Stars
69
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Control UEFN (Unreal Editor for Fortnite) from Claude Code via the Model Context Protocol.

Claude Code    MCP Server (mcp_server.py)    Listener (uefn_listener.py, inside UEFN)
|--TCP 127.0.0.1:1962-->  UEFN VerseWorkflowServer   (verse_compile / verse_status / verse_push)
|--stdio------------->  verse-lsp.exe                (verse_symbols / verse_hover / ...)
'--files / Win32 ---->  editor log, settings ini, processes   (uefn_status / uefn_launch_project / ...)
  • 110 tools: actors, assets, levels, viewport, materials, Niagara, animations, static meshes, data tables, asset validation, device @editable wiring, Play-In-Editor control, StaticMeshActor scatter, Verse source introspection, Verse compile/push, Verse code navigation, UEFN session status / launch, and arbitrary Python execution
  • Zero C++ compilation — pure Python, works across UEFN versions
  • Main-thread safe — all unreal.* calls dispatched via editor tick callback
  • Autostart — the listener starts by itself when a project opens (see Auto-start)
  • Crash recovery — the UEFN session tools read the editor state and relaunch UEFN after a crash; see UEFN session and crash recovery
  • No input simulation — the server never sends mouse or keyboard input; tools that are hard to undo are tagged experimental

What's new in 0.5.0

  • UEFN session (uefn_session.py, 3 tools): uefn_status (read-only state from the editor log, processes and

ports), uefn_launch_project (start UEFN, open a project, wait for the listener; can stop a crash reporter left over from a crash), `u

Read from source at commit 7f5fa60e3d63OBSERVED · 2026-10-07
Advertisement
02

Exposed tools (103)

53 read · 42 write · 8 destructive. Blast radius: 8 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
anim_add_float_curvewriteCreate a new float curve on an animation.
anim_add_float_curve_keywriteAdd a keyframe to a float curve on an animation.
anim_add_notifywriteAdd a zero-duration typed notify event to a track.
anim_add_notify_statewriteAdd a duration-based notify state event to a track.
anim_add_notify_trackwriteAdd a new notify track to an AnimSequence/Montage.
anim_create_blendspacewriteCreate a BlendSpace (2D) or BlendSpace1D asset.
anim_create_montagewriteCreate an AnimMontage asset from a source AnimSequence.
anim_get_inforeadGet basic info about an AnimSequence or AnimMontage (length, class, skeleton).
anim_list_notifiesreadList all notify events on an animation with name/time/duration/track/class.
anim_list_notify_tracksreadList notify track names on an AnimSequence/Montage.
anim_remove_all_notify_tracksdestructiveRemove all notify tracks (and their events) from an animation.
asset_find_dependenciesreadList packages this asset depends on (i.e. what it uses).
asset_find_referencersreadList packages that reference this asset (i.e. what uses it).
asset_find_unusedreadFind assets with no referencers in a directory.
asset_get_metadatareadRead all metadata tags on an asset.
asset_remove_metadatadestructiveRemove a metadata tag from an asset.
asset_set_metadatawriteSet a metadata tag on an asset (e.g.
datatable_export_csvreadExport the whole DataTable as a CSV string.
datatable_export_jsonreadExport the whole DataTable as a JSON string.
datatable_get_rowreadGet a single row of a DataTable (parsed from JSON export).
datatable_import_csvwriteReplace all rows in a DataTable from a CSV string. Saves the asset.
datatable_import_jsonwriteReplace all rows in a DataTable from a JSON string. Saves the asset.
datatable_inforeadGet DataTable structure, row names, and column names.
delete_actorsdestructiveDelete actors from the current level by path or label.
device_list_editablesreadList all Verse @editable fields on a creative_device actor in the level.
device_set_editablewriteSet a Verse @editable field on a creative_device actor.
device_set_editables_bulkwriteSet multiple Verse @editable fields on one actor in a single call.
does_asset_existreadCheck if an asset exists at the given path.
duplicate_assetreadDuplicate an asset to a new path.
focus_selectedwriteMove the viewport camera to focus on the currently selected actors (like pressing F).
get_actor_propertiesreadRead specific properties from an actor.
get_all_actorsreadList all actors in the current level.
get_asset_inforeadGet detailed info about an asset.
get_editor_logreadRead recent lines from the Unreal Editor Output Log.
get_level_inforeadGet info about the current level (name, actor count).
get_logreadGet recent MCP listener log entries from the UEFN editor.
get_project_inforeadGet the UEFN project name and content root path.
get_selected_actorsreadGet currently selected actors in the UEFN viewport.
get_selected_assetsreadGet assets currently selected in the Content Browser.
get_viewport_camerareadGet the current viewport camera position and rotation.
list_assetsreadList assets in a directory.
material_add_expressionwriteAdd an expression node to a material. Returns the node_name to use in later calls.
material_connect_expressionsreadConnect an output pin of one expression to an input pin of another. Recompiles material.
material_connect_propertyreadConnect an expression output to a material attribute (BaseColor, Metallic, etc). Recompiles material.
material_createwriteCreate a new Material asset.
material_create_instancewriteCreate a MaterialInstanceConstant from a parent Material.
material_list_expressionsreadList all expression nodes in a material with names and classes.
material_recompiledestructiveForce recompile of a material and save it.
material_set_expression_propertywriteSet an editor property on a material expression node.
material_set_scalar_paramwriteSet a scalar parameter value on a MaterialInstanceConstant.
material_set_static_switch_paramwriteSet a static switch parameter on a MaterialInstanceConstant (triggers recompile).
material_set_texture_paramwriteSet a texture parameter value on a MaterialInstanceConstant.
material_set_vector_paramwriteSet a vector (LinearColor) parameter value on a MaterialInstanceConstant.
mesh_scatterreadScatter StaticMeshActor instances randomly inside an axis-aligned box.
niagara_activatedestructiveActivate the NiagaraComponent on an actor. If reset=True, restarts the simulation.
niagara_deactivatereadDeactivate the NiagaraComponent on an actor.
niagara_place_actorreadSpawn a NiagaraActor in the current level with the given NiagaraSystem asset.
niagara_resetdestructiveReset the particle simulation on an actor
niagara_set_bool_paramwriteSet a bool user parameter on a NiagaraComponent.
niagara_set_color_paramwriteSet a LinearColor user parameter on a NiagaraComponent.
niagara_set_float_paramwriteSet a float user parameter on a NiagaraComponent.
niagara_set_int_paramwriteSet an int user parameter on a NiagaraComponent.
niagara_set_system_assetwriteSwap the NiagaraSystem asset on an actor
niagara_set_texture_paramwriteSet a Texture user parameter on a NiagaraComponent.
niagara_set_vec3_paramwriteSet a vec3 user parameter on a NiagaraComponent (position or direction).
pingreadCheck if the UEFN editor listener is running and responsive.
playtest_startwriteStart a Play-In-Editor session (equivalent to the UEFN Play button).
playtest_statusreadReport whether a Play-In-Editor session is currently running.
playtest_stopwriteEnd the current Play-In-Editor session.
rename_assetwriteRename or move an asset.
save_assetwriteSave a modified asset.
save_current_levelwriteSave the current level.
screenshot_desktopreadCapture the whole desktop (or a specific monitor) as a PNG file.
screenshot_viewportreadCapture the UEFN editor viewport as a PNG file.
search_assetsreadSearch for assets using the Asset Registry.
select_actorsreadSelect actors in the UEFN viewport.
set_actor_propertieswriteSet properties on an actor via set_editor_property().
set_actor_transformwriteSet an actor
set_viewport_camerawriteMove the viewport camera to a position.
spawn_actorreadSpawn an actor in the current level.
staticmesh_add_collisionwriteAdd a simple collision primitive.
staticmesh_enable_nanitewriteEnable/disable Nanite on a static mesh (saves it; the Nanite build takes seconds).
staticmesh_generate_uvreadGenerate a UV channel on a static mesh with a projection gizmo (saves it when it worked).
staticmesh_get_inforeadGet static mesh facts from reads that are safe in UEFN 42.20.
staticmesh_remove_collisionsdestructiveRemove all simple collisions from a static mesh (saves it). Returns `removed`; read the new
staticmesh_remove_lodsdestructiveRemove all LODs except LOD0 (saves the mesh). Returns `removed`; read the new LOD count with
staticmesh_set_lodswriteSet LODs by triangle reduction. First element = LOD0 (usually 1.0 = full).
uefn_statusreadRead-only snapshot of the local UEFN session, no listener needed: state (not_running | starting
validate_assetwriteRun all registered editor validators on one asset. Returns valid/invalid counts.
validate_folderreadValidate all assets under a directory. Good for CI-style content audits.
validate_selectedreadValidate assets currently selected in the UEFN Content Browser.
verse_check_editable_coveragereadSource-side audit: find @editable fields of a config class that are
verse_compilereadCompile the Verse project in the open UEFN editor and return errors/warnings.
verse_definitionreadGo-to-definition from a position in a .verse file (1-based line/col).
verse_find_resource_usagereadFind usages of each variant of a Verse enum across all `.verse` files.
verse_find_symbolreadWorkspace-wide symbol search by name (verse-lsp workspace/symbol).
verse_hoverreadType/signature info at a position in a .verse file (1-based line/col).
verse_list_editablesreadList ``@editable`` fields grouped by their enclosing Verse class.
verse_list_servicesreadList all Verse classes implementing ``i_service`` across the project.
verse_lsp_restartwriteRestart the persistent verse-lsp session.
verse_service_graphreadParse the composition-root file and return the DI graph.
verse_statuswriteReport current Verse build state & push-availability WITHOUT compiling.
verse_symbolsreadOutline a .verse file: classes, functions, vars with line numbers.
03

Trust audit

BLOCKgrade D · trust 66/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)WARN
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (2 observation(s))
Network
declared (5 observation(s))
Shell
declared (1 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (17)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
uefn_listener.py:422
exec(code, exec_globals)
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMPrivilege escalation / persistence · fs.persistence · CWE-269, CWE-250
setup.ps1:175
& schtasks.exe /Query /TN 'UEFN-MCP-hook' *> $null
MEDIUMPrivilege escalation / persistence · fs.persistence · CWE-269, CWE-250
setup.ps1:180
Would "schtasks /Create /F /SC HOURLY /TN UEFN-MCP-hook /TR '$tr'$(if ($taskExists) { '  (task exists; refreshed)' })"
MEDIUMPrivilege escalation / persistence · fs.persistence · CWE-269, CWE-250
setup.ps1:182
& schtasks.exe /Create /F /SC HOURLY /TN 'UEFN-MCP-hook' /TR $tr *> $null
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
uefn_session.py:272
for ln in text.lstrip("").splitlines():
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
uefn_session.py:331
self.scan.feed(raw.decode("utf-8", "replace").rstrip("\r").lstrip(""))
MEDIUMPrompt injection · scope.undeclared_system · CWE-94, CWE-1427
<declared scope>
system use found in code, not declared in the description
Why it matters. the description does not admit a capability the code has
Fix. declare system use in the description, or remove it
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
anim_remove_all_notify_tracks, asset_remove_metadata, delete_actors, material_recompile, niagara_activate, niagara_reset, staticmesh_remove_collisions, staticmesh_remove_lods
Why it matters. 8 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
tests/test_feasibility.py:93
__import__(mod_name)
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
tests/_listener_ast.py:65
exec(code, ns)
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:129
"url": "http://127.0.0.1:8000/mcp"
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:179
`[MCP] Listener started on http://127.0.0.1:8765` and `[MCP] Auto-started on port 8765`.
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/architecture.md:121
│  │  POSTs to http://127.0.0.1:8765     │  │
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/setup.md:115
"url": "http://127.0.0.1:8000/mcp"
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/tools_reference.md:173
"[MCP] Listener started on http://127.0.0.1:8765",
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
requirements.txt
mcp
Why it matters. 1 requirement(s) not pinned with ==
Fix. pin exact versions
LOWPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
README.md:227
The `execute_python` tool is the most powerful — it runs arbitrary Python code inside the editor with full access to the `unreal` module:

Gates applied: no_behavioural_pass.

Audited 2026-10-07 · audit v0.4.1 · source sha 7f5fa60e3d63full audit observations/trust-audit/mcp-server/kirchuvakov__uefn-remote-control.json · Report an issue / request a re-scan
04

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-077f5fa60e3d63BLOCKD66first audit
05

Questions

What is the UEFN Remote Control MCP server?

MCP server for controlling UEFN (Unreal Editor for Fortnite) from Claude Code — 22 tools for actors, assets, levels, viewport, and Python execution

What tools does UEFN Remote Control expose?

103 in total: 53 read-only, 42 that write, and 8 that can delete or overwrite (anim_remove_all_notify_tracks, asset_remove_metadata, delete_actors, material_recompile, niagara_activate). Every one is listed on this page with its risk.

Is UEFN Remote Control safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (66/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 8 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does UEFN Remote Control need?

No credential environment variables were found in its source, so it appears to need none.

How current is this page?

The grade is for one exact copy of the source (7f5fa60e3d63), read on 2026-10-07. The repository is watched and re-audited when it changes.

Advertisement