Driving the bridge
How an AI agent should drive a live Unreal editor through MifBridge: how to find the right call, which results to trust, and what to check after every write. A person can point their agent at this page, and it is written as instructions the agent can follow directly.
Read Editor hazards for agents alongside this page. One covers what can take the editor down, this one covers how to work correctly.
The call
POST http://127.0.0.1:8791/api/<endpoint> with the header X-Mif-Token and a JSON body. The answer is JSON. Through the MCP server, the tools do this for you.
Every answer has ok. ok is not the answer. See Verification below, which is the part that matters.
Never guess the surface, ask it
There are several hundred endpoints and the names are not guessable. Two calls exist so you never have to guess:
| Call | What it tells you |
|---|---|
self_audit |
The endpoints the running plugin has, the engine version as numbers, the write mode and the port |
describe_endpoint |
One endpoint's real parameters, their aliases, and what it refuses |
self_audit reports what the running plugin has. A plugin built earlier can lack an endpoint a newer document mentions, so trust self_audit over any file. It also reports the endpoint count, so no document needs to state one.
A guessed parameter name does not fail quietly. Unknown keys are refused with the list of accepted keys and, usually, a hint naming the right spelling. Read the refusal. It is written to be read.
Nothing is saved, on purpose
The bridge does not write to disk by default. Assets you create live in the editor's memory until a person saves them, so an editor restart loses them. That is the standing contract, and it is enforced by the safety gate, not just promised. See Safety and Write Modes.
In the default scratch mode you can build a thing and not keep it. Asset creation, graph editing and property writes work. save_*, load_level, Play-In-Editor, console execution and a few others are refused by name, and the refusal says how to unlock them and how to make the change stick.
self_audit reports writeMode. Check it before you conclude an endpoint is broken. A gated refusal and a defect look alike if you only read ok.
Verification: the part that matters
A mutation without a read-back is not done. After any write:
- Read it back with a different endpoint than the one that wrote it.
set_propertyreporting success whileget_propertyreturns the old value is exactly the failure to look for. - Compare against what you asked for, not against what the response echoed. An answer that repeats your request tells you nothing.
- Read the numeric fields, not just
ok.deleted: 0,spawned: 0oradded: 0besideok: truehas been a real bug in more than one endpoint. Those are fixed, and the same shape can recur. An outcome count of zero when you expected something is a failure whateveroksays.
Compilation is not automatic
A Blueprint graph edit does not take effect until the Blueprint compiles. An edit that reads back correctly and does nothing at runtime is usually this. Several endpoints say so in their answer, and not all of them do.
Some reads are wrong in a way JSON cannot show
Captured images are the usual case: the response can be well formed and the picture still wrong. Look at the image.
Types are strict
Numbers are numbers. A string where a number belongs is refused, not coerced and not defaulted. This is deliberate, because silently defaulting a malformed value is how a call succeeds while doing something else.
set_property and its neighbors check the value against the property's type before they import it, so a type mismatch fails before it can corrupt the property. Not every endpoint has that check, which is one more reason to read back.
Batch, and when not to use it
batch runs several operations in one transaction, so one Ctrl-Z in the editor undoes the whole thing. It suits a set of related graph edits.
- Compile-heavy operations are refused inside
batchand must be called on their own.batchcompiles once at the end withcompileAtEnd. - Read
results[]per operation. When one operation fails on its own, the others still ran and each reports its own outcome, and the batch'sokgoes false. The aggregateoktells you that something failed, not what. - The safety gate checks every operation before any runs. One gated operation means nothing in the batch runs, and the answer names the operation by its position. See Safety and Write Modes.
When the bridge stops answering
Since 1.2 a modal dialog no longer stops the bridge: other calls are refused at once with modalActive: true and the dialog's title and buttons, and get_modal_dialog reads it. See MifBridge. If calls fail some other way, look behind the editor window for a dialog before you assume a crash.
If the editor is really gone, the journal at Saved/MifBridge/journal.jsonl records every call with a start and an end, written before the handler runs. A start with no matching end names the call that was in flight. The journal cannot tell a crash from an external kill, because both leave a session with no shutdown record. It answers what was running, not why it died.
Six engines
The plugin runs on Unreal Engine 5.3 through 5.8, on cooked and uncooked editors. An endpoint that depends on an optional plugin stays registered on every engine, and where the plugin is absent it answers with a refusal that names the reason. A missing endpoint would tell you nothing. A refusal that says "this engine build has no X" is the system working.
self_audit reports engineMajor and engineMinor as numbers, for branching on version. For which engines each feature supports, see Engines.