The defaults
| Area | Default |
|---|---|
| Network | Both routes listen on 127.0.0.1 only. The WebSocket listener uses ports 8090 and 8091; the native HTTP server is off until you enable it, then uses port 3000. |
| Capability token | Required on both routes. |
| Consent | Required on every call to 62 capabilities: all deletes, plus some other writes. |
| Console commands | Filtered: no command chaining, no quit or crash commands. |
| Asset paths | /Game, /Engine, /Script, /Temp, /Niagara, plus any prefixes you add. |
| The plugin's own settings | Out of reach of automation, so an assistant can't lift its own limits. |
| Telemetry | None. The plugin and server talk only to each other and to your MCP client. |
How a request is checked
The C++ plugin is the authority. The Node.js server checks requests early so it can fail fast, but the plugin re-checks every request, from either route, before it reaches the editor's queue. A refused request does no editor work at all. The checks run in order:
Capability token. Missing or wrong:
401 Invalid capability token.Scope. The token must hold the scope the capability needs:
SCOPE_NOT_GRANTEDotherwise.Consent. Destructive capabilities need a matching grant:
CONSENT_REQUIREDotherwise.Project, paths, console and quota.
PATH_NOT_PERMITTED,PROJECT_NOT_PERMITTED,COMMAND_BLOCKEDorQUOTA_EXCEEDED.
Capability tokens
The first time the editor starts with the plugin, it generates a random 32-byte token and writes it, as 64 hex characters, to <YourProject>/Saved/MCP/capability-token. Native HTTP clients send it in the X-MCP-Capability-Token header; the stdio server reads the file itself (through UE_PROJECT_PATH) and presents it in its WebSocket handshake.
- Tokens are compared in constant time and never written to logs, receipts or health output.
- A session can't switch tokens halfway through.
- The file is readable by your OS user like the rest of the project.
Saved/is normally not committed; keep it that way, and tighten permissions if it sits on a shared drive.
To rotate the token, delete Saved/MCP/capability-token (or clear the Capability Token setting), restart the editor and update your HTTP clients.
Unticking Require Capability Token lets any program on your machine drive the editor through either route. That can be acceptable on a single-user machine where nothing else runs. Even then, the native server refuses requests that come from web pages (an Origin header), so a website open in your browser can't reach the editor.
Scopes and scoped tokens
Every capability requires one of four scopes: Read, Write, Destructive or Admin. Membership is exact: holding Write does not grant Read, and an action the catalog doesn't know demands Admin, so unknown requests are refused by default. The main token is Admin.
For anything narrower, add entries under Security › Scoped Tokens in the plugin settings. Each scoped token can have its own scopes (never Admin), allowed path prefixes such as /Game/Sandbox/, allowed projects, and per-minute request and tool-call quotas. Typical uses: a read-only token for an assistant that should only look, a token confined to one folder for an experimental agent, or a rate-limited token on a shared machine.
Consent for destructive work
62 capabilities declare a consent mode: explicit, or elevated for the most destructive, such as bulk deletes. describe returns the exact grant; the call must send it back unchanged:
"consent": { "capability": "control_actor.delete", "acknowledge": "explicit", "nonce": "62A12661-4F6A-1C97-339E-69921EE9E2A7" }- A grant covers one call to one capability. On the native route its nonce makes it single-use: a replay is refused with
CONSENT_REUSED. - It is never inferred from localhost, from earlier calls or from an idempotency key.
- Consent is not permission: the caller still needs the capability's scope.
Consent makes deleting a step the model has to take on purpose, rather than a side effect of a loosely worded prompt. To approve such calls yourself, use your client's tool-approval setting for the unreal tool.
Other safeguards
- Paths. File-system paths are checked for traversal and symbolic links, once when accepted and again just before use.
- Console. Chaining (
;,&&,||,|, backticks, newlines) is refused, as arequit,exit,shutdown,crashand similar, and attempts to reach Python or a shell through the console. - Python.
system_control.execute_pythonexists. It needs Write scope and explicit consent per call, and scripts are limited to 1 MB. Anything that can run Python can do anything the editor can, so treat that consent as a real decision. - Rate limits. Native HTTP allows 16 sessions and 32 connections, and per session 600 requests and 120 tool calls a minute.
Remote and LAN access
Both routes are loopback-only by default. Reaching the editor from another machine takes Allow Non Loopback plus a Listen Host in the plugin, a firewall rule, and the token, which stays required: the native server refuses to bind to a LAN address without it. The WebSocket route supports TLS. The native server speaks plain HTTP, so beyond a network you fully trust, reach it through an SSH tunnel or a TLS reverse proxy rather than exposing the port.
FAQ
Can the AI wreck my project?
It can change and delete things; that is the point. Deletes need a per-call consent grant, control_editor.undo steps back through editor transactions, and partial failures are reported rather than hidden. Use source control anyway, and commit before a big job.
Does my project leave my machine?
The plugin and server send nothing anywhere and collect no telemetry. Your AI client does send tool results (asset names, property values, screenshots) to its model provider. Fab and MetaHuman capabilities go through Epic's services, only when you run them.
How do I report a vulnerability?
Privately, through GitHub's private vulnerability reporting, not a public issue.
How does this compare with Epic's plugin?
Epic documents its Unreal MCP as having no authentication layer. See Epic's Unreal MCP vs EngineWire.