MifBridge
The MifBridge plugin runs inside the Unreal editor and serves a local HTTP API. It has one endpoint per operation, it is strict about its input, and it says exactly what it changed.
Calling it
POST http://127.0.0.1:8791/api/<endpoint>, with a JSON body and the headerX-Mif-Token: <your token>.- Loopback only. Callers from other machines are rejected inside the handler. Never expose the port beyond your own machine.
- Web pages are refused. A page open in a browser on your machine is a loopback caller too, so from 1.2 any request carrying an
Originheader, which only a browser sends, is refused with HTTP 403 (refusedBy: browser-origin) before its token is read. - Every response is JSON with an
okfield. A failure carries anerrorthat says what went wrong and what to do instead.
curl -s -X POST http://127.0.0.1:8791/api/describe_endpoint \
-H "X-Mif-Token: dev" -H "Content-Type: application/json" \
-d '{"name":"set_texture_settings"}'
Through the MCP server, each endpoint is also a tool of the same name, and the tool returns the endpoint's JSON unchanged. A default session loads three tools, find_tools, mif_call and run_python, and mif_call calls any other tool by name.
Finding the right endpoint
- The API reference lists every endpoint and Blender operation, grouped and searchable.
find_tools, through the MCP server, searches every tool by a keyword or a few words, loaded or not, and gives each one's summary and parameters.describe_endpointwith{"name": "<endpoint>"}asks the running plugin what an endpoint accepts: its parameters, their aliases, and the common mistakes it corrects. The answer is derived from the plugin's own parameter guards, and it says so when it cannot vouch that the answer is complete.self_auditlists every live endpoint and reports the engine version, the write mode, whether the safety gate is on, and the change cap in force.
What it covers
Assets, Blueprints and their graphs, levels and actors, materials, meshes, landscape, foliage, water, PCG, Niagara, audio and MetaSounds, animation, Control Rig and MetaHuman, Sequencer and rendering, UMG, input, Play-In-Editor, profiling, and the project itself: plugins, settings, localization and source control. The API reference groups every endpoint by area.
1.2 added these areas, among others:
- Gameplay and AI. StateTrees authored with
edit_state_tree, paused on a named state withwatch_state_treeand read back from a recorded trace withtrace_state_tree; EQS queries run in play withrun_env_query; a running AI's behavior tree and blackboard read withdescribe_ai_live; the Gameplay Ability System's effects, attributes and cues applied and traced (apply_gameplay_effect,list_attribute_sets,gas_trace). - Multiplayer in Play-In-Editor.
pie_add_clientadds a client to a running session,reconnect_pie_clientdrops one and joins it again,read_replicationreads what replicates on each client, andcall_functionsends an RPC and says where it ran.pie_recordrecords a session and replays its input. - Blueprint lint and restructuring.
lint_blueprintsfinds replication mistakes, costly ticks and casts, and untidy graphs.copy_blueprint_components,copy_graph_nodesandcollapse_graph_nodesmove and restructure graphs without the clipboard or a dialog. - Cinematics. Movie Render Graphs made, checked layer by layer and rendered (
edit_movie_render_graph,render_sequence), Sequencer constraints, event keys and curve filters, and Control Rig tracks keyed per frame (edit_sequence_control_rig). - Data and pipeline. DataTables filled from a file, Curve Tables (
create_curve_table), localization (localization_run), what an asset drags in (get_asset_size_map), the assets nothing reaches (audit_unused), a local word search over the asset registry (search_assets), and a Lumen readiness report.
Strict input
Every endpoint checks its parameters before it does anything. An unknown or misspelled key is refused, and the refusal lists the accepted keys and the likely correction. Pass describe_endpoint a tool key, for example, and the refusal tells you to spell it name. Nothing is ever silently ignored, so a typo cannot quietly turn a write into a no-op.
Responses report consequences
- A write returns what the editor holds afterwards, read back from the asset or actor, not your request echoed.
- A side effect you did not ask for gets its own field. If a value was clamped to its limits,
clampAppliedsays what you asked for and what was written. If a write had to switch on a companion override flag,overrideFlagWrittennames it. If an export wrote a different number of files than planned,filesWrittensits besidefileCount. - A refusal says why and what to do next. It never just says no.
Changing things safely
- The write mode decides what may run. By default, saves, Play-In-Editor, cooks and console commands are refused. See Safety and Write Modes.
- Destructive operations need
confirm: true: deleting assets, actors, nodes, variables, functions, components and interfaces, renaming assets and Blueprint members, writing DataTable rows, and more. See Safety and Write Modes. - Bulk changes preview first.
rename_asset,fix_up_redirectors,consolidate_assets,add_to_collection,remove_from_collection,move_actors_to_level,delete_assetandapply_level_snapshottakedryRun: true, which lists exactly what the call would change before anything is written. - A mass change shows its list first. From 1.2, a call that would change more than 25 things writes nothing and answers the list, and only a second call with that list's
previewIdapplies it. See the change cap. - A write is never run twice. Every call from the MCP server carries a request id. If a write's reply times out, the answer says the outcome is unknown instead of telling the agent to retry, and the same call sent again replays the first result.
request_statusreads what became of an id. - Saves respect revision control. With a revision control provider connected, a save checks the file out first, and a file another user has checked out or locked is refused before anything is written, naming them.
- Transacted edits undo with Ctrl+Z in the editor. Saves, cooks, Play-In-Editor, compiles and console commands are not transactions.
batchruns many operations in one call, in one transaction with one compile, and each inner operation still passes the safety gate.- Compile-heavy operations run alone. Creating functions or Blueprints, reparenting a Blueprint, adding event dispatchers, changing a function's network flags, and
batchitself compile outside the surrounding transaction, because a full compile rebuilds the class. Do not nest them inside one another.
When the editor shows a dialog
A modal dialog, such as a message box or a save prompt, used to stop every call until somebody clicked. From 1.2 the bridge keeps answering while one is open: every other call is refused at once with modalActive: true and the dialog's title, text and buttons. get_modal_dialog reads it, answer_modal_dialog presses a button, and arm_modal_answer sets rules for dialogs that have not appeared yet. open_modal_dialog puts a question to the person at the editor and records the answer. The answering calls are gated in scratch, because pressing Save in a save prompt is a save.
The in-editor panel
The MifBridge panel opens a moment after the editor starts. You can also find it under Window, or Tools ▸ Mif Bridge: Live Panel. The brainmap also opens as a tab of its own from Tools ▸ Mif Bridge: Brainmap. Apart from its write-mode control, it only reads, and the bridge works exactly the same with the panel closed.
The header shows four things at a glance:
- LISTENING: the port.
- WRITE MODE: the one control on the panel that changes anything.
- ENDPOINTS: how many are live.
- CALLS: how many have been made.
While a call is running, an in-flight banner names it.
| Tab | What it shows |
|---|---|
| ACTIVITY | Every call as a card, newest first: the endpoint, its duration, its age, and what it was about. Each is color-coded READ, WRITE, BLOCKED (the safety gate), REFUSED (an invalid request, not a defect) or FAILED. The flag button writes a structured report. |
| BRAINMAP | The dependency graph of the assets under a folder. Color is asset type, and size is how many things reference it, so a hub looks like a hub. |
| HEATMAP | Packages sorted by how connected they are. Each shows references in and out separately, because a shared foundation and an object that depends on everything have similar totals and opposite problems. |
| PERFORMANCE | A static cost census of the open level: triangles, components, material slots, and which actors tick in Blueprint. It is not frame timing. For that, use trace_start and trace_stop and open the capture in Unreal Insights. |
| INHERITANCE | Every Blueprint grouped under the native class it derives from, built from asset-registry tags without loading a single asset. That makes it safe on cooked projects. |
| BEHAVIOR | Behavior trees and their blackboards, read through the same describe_behavior_tree endpoint an agent calls. |
| SKELETAL SPLIT | The skeletal meshes in the project. Pick one, and it is analysed fresh through analyze_skeletal_split. |
| SETUP | Install and connection help: a checklist that tests each step for itself, and Set up Claude Code, which connects Claude Code to this editor in one press. |
The same data is available without the panel: project_dependency_graph, project_asset_distribution and perf_heavy_actors. Every result that caps what it returns reports both the cap and the true total, so a shortened answer can never read as a complete one.
The crash journal
Every call is recorded in Saved/MifBridge/journal.jsonl, and the record is flushed to disk before the call runs. After a crash, the call with a start and no end is the one that was running when the editor died. Each session records its process id, so several editors on one project stay separable. python Content/Python/MifBridge/mifwatch.py, run from the plugin folder, reads the journal and names the call for you. See Troubleshooting.