Repository navigation
Releases
Release v0.6.1-beta-b
Note
Beta. Published as a semver prerelease (0.6.1-beta-b) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.6.0. This section is everything on dev since the v0.6.1-beta-a tag, written from the code diff.
🔄 Changed
- Inputs are held to their contract: execute refuses a string or object key past its
maxLength, or past the 1023 characters an FName holds where none is set (code, scripts and prose parameters take more); a vector or color sent as an array must hold exactly the type's numbers;add_keyframerequiresproperty.
🔧 Fixed
- Builds: the plugin builds on macOS again and on UE 5.0 and 5.1, and a source check in CI keeps those compiler traps out.
- Crashes: an overlong tag, name or key and an
add_keyframewith nopropertyno longer close the editor. - Vectors and colors: Niagara parameters, effect and skeleton
scale, light, debug shape and texture colors, material vector defaults, blackboard vector and rotator keys and actor location, rotation and scale no longer pad, cut or zero an array that is not exactly their numbers and answer success. - Sequence keys: an
add_keyframeTransform whose value keys nothing is refusedINVALID_ARGUMENTnaming the value instead of reading as an unsupported property, a value that wrapspropertyorvalueis refused, and every refusal shows a key's whole params (the old example putpropertyinsidevalue).
⚠️ Migration
- Long text: a string over 1023 characters, or over a parameter's own
maxLength, is refusedOUT_OF_RANGE; send long text only in the parameters that take it (code, scripts, descriptions, comments, subtitles, widget text). - Vector and color arrays: send exactly the type's numbers (three for a vector, three or four for a color), or the object form.
- Sequence keys: send
propertybesidevalueinadd_keyframe; a Transform whose value keys nothing answersINVALID_ARGUMENT, notUNSUPPORTED_PROPERTY.
🔄 Dependencies
- GitHub Actions:
github/codeql-action(init, autobuild, analyze) 4.39.0 → 4.39.2. No npm package changed, and the package still has no runtime dependencies.
📊 Change Statistics
| Metric | Count |
|---|---|
| Diff range | v0.6.1-beta-a..v0.6.1-beta-b |
| Commits | 12, the version bump and the release cut included |
| Files changed | 80 (65 hand-written, not counting generated files or line-ending-only changes) |
| Insertions / deletions | 2,035 / 540 (hand-written: 889 / 101) |
| Capability records | 489 |
Callable {tool, action} pairs |
1,658 |
| C++ domain directories | 58 |
Release v0.6.1-beta-a
Note
Beta. Published as a semver prerelease (0.6.1-beta-a) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.6.0. This section is everything on dev since the v0.6.0 tag, written from the code diff.
✨ Added
- Engine versions: a capability an older engine cannot run reads
unavailableand is refusedENGINE_VERSION_UNSUPPORTED(Geometry Script 5.1, MetaSound graph reads and skinning 5.5, retargeting 5.8). - Search and execute: a typo is read as the word meant (
corrected),options.aggregatecounts a long list by group, and an alias sent as tool + action resolves. - Blueprints:
lint_blueprintfollows values (a divisor that can be 0, an index past the end, a Set outside a Value Range,==on computed floats, a decided Branch, an endless While);fuzz_blueprintcalls a Blueprint's functions in Play with edge-case inputs and names each error's node; MVVM viewmodels (UE 5.4+);add_variableexposeToCinematics. - Graph as code:
read_graph_as_codeentryandcodeOnly;write_graph_from_codereads back only what it wrote. - Views and cameras:
cameralooks through a camera actor (screenshot,describe_view,analyze_view,audit_materials);pauseandlist_track_keysname each cut's camera;screenshotrenderSizeandpathTraced(a denoised path-traced image);fovon every view read. - Plugins and project:
get_plugin_info,create_plugin/remove_plugin, game features (UE 5.1+), data registries, an unused-asset report,set_project_thumbnail,get_console_variables,remove_cpp_class. - Editor:
read_editor_ui,configure_editorclose_tab,set_selected_actors, viewportshow_flags,reimportwithout a dialog,set_current_level,console_commandfilter. - Actors: snap to grid, distribute, align, lock, group, randomize, replace, convert to a Blueprint, move to a level, numbered rename, copies along a spline,
place_decals;listboundsandfindlocations;sample_motionfeel(jump, run, key latency, camera jerk). - Sequences:
add_actorsrebindpoints a sequence copied with its level at the new level's actors;add_behavioursequence_triggerplays one when the player walks in. - Geometry:
append_tubes,append_polygonsrepeatandbake_vertex_colorscoarseShare. - Look and sound: material
color/glow, lightflicker, a first-person view,sound_trigger, subtitles, sound volume and looping, footsteps, animation play rate,massKg. - Scripts and sheets:
run_scripttakes(if cond a b)as a value and waits withindeadlineMsfor a call that answers later; contact and thumbnail sheets takekeepFile: false. - Frame budget:
fit_frame_budgetfinds which lights' shadows and far small meshes to turn down to meet a GPU frame time at the least change to the picture, and keeps them as one undo step. - Proxy CLI:
init <client>writes a client's MCP config;doctorchecks the setup (the token is never shown).
🔄 Changed
- Movie Render Queue, Takes and MetaSound are required plugins: EngineWire links their modules, so enabling it turns them on (left off in a Blueprint-only project, EngineWire did not load on Windows and the editor crashed at startup on macOS).
- Write replies pass on only lint errors: the warnings (unreachable nodes, heavy Tick work) stay in Validate Assets, saves and
validate_assets, so a graph built one node at a time is not told its newest node never runs. - No-op and mid-compile edits are refused: an edit that changes nothing is refused instead of answered done, and so is any edit while a Live Coding compile runs.
- Scopes follow what a call writes:
export_levelneedswrite, andexport_meshoutputPath,screenshotpathandget_transform(sample_motion)inputsraise a call towrite.
🛡️ Security
- Native
/mcpbinds to loopback only, whatever Allow Non Loopback says: it has no TLS, so a token would cross the network in clear text. A WebSocket listener on a LAN address needs the capability token and TLS. - The stdio proxy sends its token only to a loopback upstream unless
UNREAL_MCP_ALLOW_REMOTE_TOKEN=1, anddoctorfollows the same rule. - A path-restricted token's prefixes hold everywhere: saves, deletes, reflection reads, searches and listings run as the request's principal, and a file the caller places is written through a handle checked inside the project.
- Inputs and consent: script, search and list inputs are bounded, and a consent grant comes back only when no handler ran.
🔧 Fixed
- Plugin loading: geometry and skinning actions refuse with
GEOMETRYSCRIPTING_PLUGIN_NOT_ENABLEDwhile GeometryScripting is off instead of crashing, and the game features module compiles on UE 5.6 and 5.7. - Crashes: a glTF or GLB export and a key tapped with no Play session no longer take the editor down.
- Input: simulated game keys stay out of the editor's panels.
- Search: about 250 more plain requests find their capability, and an alias a family member declared runs that member.
- Replies: long lists page and aggregate from the reply's
data; console replies stay short; a script step still running at the deadline says so; logpoints read an unwired input's own value; the tool says how to get a fresh consent grant. - Undo: asset edits are one step each (notifies, sockets, physics bodies, blackboard keys, Behavior Trees and more), enum undo no longer crashes UE 5.7+, and a script's rollback undoes only its own steps.
- Graph as code:
%,==on text, calls used as values, ids with underscores, custom event calls, other classes' variables, expose-on-spawn inputs, calls on the Blueprint itself and events bound to a delegate write asread_graph_as_codeprints them. - Placement: props in a room built as one mesh read as they are; a support with no collision is named;
fix_coplanarchecks each move against the others. - Views: frame readers warn while shaders, meshes or textures still build;
contact_sheetdraws beside water and titles small sheets in full. - Geometry:
bevelandchamfercut whole parts, and material and PolyGroup edits are their own undo steps. - Assets:
check_meshfinds parts wound inside out, on skeletal meshes too; FBX imports open no Message Log window and convert units with options; material instances draw their parent; morph targets and skin weight profiles survive rebuilds; output files reach captures, exports and thumbnails. - Editor state:
save_allsaves streaming sublevels; dry runs no longer compile or save; Blueprint compiles leave placed skeletal meshes posed; Behavior Trees build from their Root. - Niagara: a created emitter keeps the name it was asked for.
- Game framework and materials:
default_pawn_classtakesNone, and material pins connect by the short names the material editor shows. - Sequence sections: a sound section plays in the editor and the game, and adding one is one undo step.
⚠️ Migration
- A client on another machine: the native server no longer binds to a LAN address. Tunnel to it (
ssh -L 3000:127.0.0.1:3000 <user>@<editor machine>) and keepUNREAL_MCP_URLathttp://127.0.0.1:3000/mcp; a stdio proxy pointed at another machine sends no token unlessUNREAL_MCP_ALLOW_REMOTE_TOKEN=1. A WebSocket listener on a LAN address also needs Enable Tls. - Scoped tokens: a token without
writeno longer runsexport_level, norexport_meshwithoutputPath,screenshotwithpathorget_transformwithinputs. - Projects that turned off Movie Render Queue, Takes or MetaSound: enabling EngineWire turns them on again.
- Lint warnings after a write: read them with
lint_blueprintorvalidate_assets; write replies carry only lint errors.
🔄 Dependencies
- None: no npm package and no GitHub Action changed, and the package still has no runtime dependencies.
👥 Contributors
- @SoloGorilla for keeping a created Niagara emitter's requested name (#669), and for reporting the crash when a key was tapped with no play session (#685) and simulated keys reaching editor panels,
sample_motioninputs included (#686). - @claudemlandry for reporting the macOS startup crash on UE 5.7.4 (#705).
📊 Change Statistics
| Metric | Count |
|---|---|
| Diff range | v0.6.0..v0.6.1-beta-a |
| Commits | 164, the version bump and the release cut included |
| Files changed | 767 (741 hand-written, not counting generated files or line-ending-only changes) |
| Insertions / deletions | 43,428 / 5,766 (hand-written: 29,413 / 3,729) |
| Capability records | 489 |
Callable {tool, action} pairs |
1,658 |
| C++ domain directories | 58 |
Release v0.6.0
Note
Stable. The 0.6 line's stable release, published under the npm latest dist-tag. This section is everything since the v0.6.0-beta-f tag, written from the code diff.
✨ Added
- Blueprint runtime errors name their node and an Accessed None its
cause;lint_blueprintfinds such mistakes before Play, and Validate Assets and saves report them too; logpoints record a node's pin values each time it runs in Play, without pausing;read_graph_as_codeandwrite_graph_from_coderead and write graphs as Epic's 5.8 Blueprint DSL text, on every 5.x (a rewrite keeps the nodes its ids name);create_nodemenuId,arrange_nodeslayout: 'layered'. - MCP 2026-07-28: sessionless requests, client consent and tasks; older clients unchanged.
- Reads:
get_editor_statefocus;describe_viewpoints,labels,coveredBy,compareWith(what changed sincesaveAs);analyze_view(saliency, palette, light, shader cost);contact_sheet(an actor from every side);audit_materials(base colours, metallic and roughness off physically based ranges, stretched or crammed textures, meshes to instance);get_statsframe;get_ai_infoinfo: 'path'(can a pawn walk there, and why not);analyze_level_layout(a level's rooms, corridors, chokes and dead ends);audit_widget(a menu or HUD checked at several screen sizes: cut-off text, overlaps, contrast, safe area). - Large results come in pages (
page.nextCall), and search hands over a clear first hit (signature,executeCall). nanite_rebuild_meshassetPaths,inspect_assetdiff,get_niagara_infovalues,setup_global_illuminationsaveToProject, fouredit_dynamic_meshoperations.- Renders and sequences:
frame_shot(a camera placed so one or two actors sit where asked on screen, in clear view),fly_through(a camera flown smoothly through points, clear of geometry, keyed into a sequence),auto_edit(a sequence cut between its cameras as an editor would: no crossing the line, no jump cuts),cancel_render, the path tracer's denoiser by name, camera shutter and overscan,set_sectionplayRate, clips and keyed bones in the readers. - Sound:
measure_loudnessandnormalize_loudness(Sound Waves measured in LUFS as broadcast measures them, and set to play at one loudness);analyze_acoustics(how long a room rings where a listener stands, and the reverb that fits it). - Animation:
auto_blend_space(a locomotion blend space laid out from how its clips move). - World building: a hip roof over any footprint (
create_primitiveroof), its faces meeting along ridges, hips and valleys;erode_landscapewears terrain down the way water does (valleys, gullies, filled hollows) so every cell drains, and lists its rivers;plan_roadfinds a drivable road under a grade limit, round obstacles and wide enough at every turn, switchbacks on steep slopes;assemble_moduleslays a modular kit out over a grid so every face where two pieces meet fits. - Assets found by what they show:
thumbnail_sheet(a folder's thumbnails as one numbered picture),caption_assets(captions kept beside the project, never in the assets),find_assets_like(by words, an example asset, colour or size). - Writes are checked: sunk, floating, intersecting, z-fighting or untextured actors, placeholder text, pasted twins, Map Check findings, and Data Validation on assets.
- Replies say what undo can revert;
restore_pointundoes only this server's steps and offers the delete of what they created. inspect explainsays why something does not happen and names the call that fixes it.- A call failing three times unchanged is refused (
REPEATED_FAILURE). - Batches check every step first;
build_graph,build_material_graphandadd_widget_treetakedryRun;run_scriptruns many calls with loops and conditions in one request, rolled back on a failure; recipes keep such a script in the project to run again with other values, and search lists the ones a request names. run_map_check,fix_placement,describe_relations,arrange_by_relations,arrange_widgets(a menu or HUD laid out by relations, held at every screen size),playtest(a pawn walked to a goal in Play, judged with evidence),settle_physics(props dropped and kept where they come to rest),explore_level(a pawn explores the level: falls, traps, unreachable areas), and execute'sexpect/require, checked after or before a call.inspect changes_sinceandue://changessubscriptions: what changed since a cursor, and by whom.- Domain playbooks as MCP prompts: Blueprint logic, input, UI, Niagara, materials, world building, animation, cinematics and play testing, each with the traps of its domain.
remove_sublevel: a sublevel leaves the open level, as the Levels panel's Remove does; its map file stays.
🔄 Changed
- The npm package is a stdio proxy to the plugin's
/mcpwith no runtime dependencies:NOT_CONNECTEDwhile the editor is down;UNREAL_MCP_URLpicks the endpoint,UE_PROJECT_PATHfinds the token. - Enable Native MCP Server is on by default.
- Consent grants need the nonce
describeminted: a missing or made-up one is refused (CONSENT_NOT_ISSUED).
🗑️ Removed
- The TypeScript gateway and WebSocket client, with their resources, telemetry, mock mode and
test:smoke;.envis not read. - Over stdio: search and describe with the editor down, the
ue://assets/actors/editor/selectionresources, TLS to a remote editor, protocols2024-11-05and2024-10-07.
🔧 Fixed
- Crashes: Ability System actions on non-Actor Blueprints, creates or bakes over another class's asset, and
validate_assetsdataValidationwith the Data Validation plugin off are refused. run_benchmarkmeasures frames, FPS and thread times (it measured nothing).- Builds and links on UE 5.0-5.8, Windows and Mac: every file compiles on its own, Smart Objects and State Trees need no experimental engine module, and older Apple clang and UE 5.8's unreachable-code rule pass.
- Small fixes:
RayTracedGI refused from 5.4,runtime_reportfilters, retry hints, reads return 0 and false, a material instance can be another's parent,list_tracksanswers again, a thumbnail'soutputPathis a PNG on every 5.x,set_bone_keykeys a sequence's last frame,create_primitivesays its meshes have no collision,configure_landscape_splinesshapes the terrain where its points are, placement warnings judge a spline mesh road where its segments lie and an actor on a landscape by its surface, undo takes back a new primitive mesh. - Removals take exact components, keep assets others use (through a chain of uses too) and undo for tracks and keys.
- Nothing is overwritten unasked: taken names and paths are refused, unsent fields kept, engine content never edited in place.
- Family variants enforce their own requirements, shown by describe.
- Renders honour
renderTimeoutMs;save_allandrestart_editorwait for them. - An open editor dialog answers calls
EDITOR_MODAL_ACTIVEwith its title instead of a timeout. - Viewport screenshots wait for streaming and name video memory over budget.
- Property writes refuse deprecated properties, restart placed Niagara effects, take object references and run components' own change handling.
- Placement checks count simulated bodies and player starts;
fix_coplanarhandles several neighbours. - Animation and effects: whole track names, partial
set_bone_key, key times across frame rates, curve read-back; Niagara creates refuse taken names. - Undo covers spawns, transforms, properties, meshes, landscape, foliage, sequences and more.
- Finds stop at
limit(default 200) and say how many matched. - Replies say what happened, failed saves and compiles included.
- Successes that did nothing now act (foliage, water, AI, Play audio, splines, landscape and more).
manage_effect cleanupneeds destructive consent and afilter, is one undo step and refuses Play; debug shapes clear throughdebug_shape.- Object paths work in
open_level,loadandadd_sublevel; relative.t3dexports land in the project. - Git: any commit message is safe (a quote could inject options); checkout and submit list skipped paths.
/mcpdiscovery: search rows,describeby domain and family,cursorand paramsuggestions.- A disabled tool's
nextCallturns it back on (configureenable_tools).
🔄 Dependencies
@modelcontextprotocol/sdk,wsandzodleft the runtime (zodstays for the record build).
Release v0.6.0-beta-f
Note
Beta. Published as a semver prerelease (0.6.0-beta-f) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.5.30. This section is everything on dev since the v0.6.0-beta-e tag, written from the code diff.
✨ Added
- Gameplay in one call:
add_behaviour, with a shortcut action for each kind (add_health,add_patroland so on), writes health, damage on touch, pickups, sprint, shooting, chase, patrol, turrets, stomps, explosives, moving and falling platforms, player controls, respawn with checkpoints, goals, launch pads, teleporters, a time limit, spawners, dashes, HUD bars and counters, hints and game over into an Actor Blueprint as plain engine nodes. - Blueprint authoring: Blueprint Interfaces (
implement_interface), timelines (edit_timeline), Bind Event, Switch on Enum, animation-graph nodes by class, a Math Expression'sexpressionin batches, andremove_variablevariableNames. - Reading graphs:
find_functionsfinds a function by plain words,get_graph_detailsfilterfinds what reads or moves a variable,unusedOnlylists nodes that do nothing, andcompiletakes afolder. - Graph checks: edits and compiles flag pure nodes and random values read twice, timers that name nothing or restart every frame, waits inside loops, values changed in place, event values read after a wait, and sounds that never end on play-and-forget nodes.
- Packaging:
package_projectexecutableNamenames the game's .exe,launch_buildmapsmoke-runs one level, andenable_plugintargetskeeps an editor-only plugin out of the packaged game. - Project setup:
configure_rendering(Lumen, shadows, anti-aliasing, ray tracing, MegaLights) andcreate_cpp_class. - Many actors at once: spawn batch
repeat(rows and grids) andproperties,set_transformandedit_componentwithactorNames,set_folderand spawnfolderandtags, and spawns and moves that name z-fighting faces. - Motion and physics: motion reads that wait for a spawn (
spawnOf), name surfaces passed through and actors overlapped, and return what the game logged, asstep_framenow does;analyze_animation, collision presets and per-channel responses, physical materials andapply_damage. - Effects and audio: several parameters on a placed effect at once,
add_emitterfrom another system,get_niagara_infofor one emitter,list_metasound_nodesand box-shaped sound zones. - More reads:
get_propertyobjectPaths, a child Blueprint's own values for its parent's components,widget_listtexts and parent panels,describe_viewactors,get_widget_animation, screenshot field of view, video memory over budget andvalidate_assetsmaterialUsage. - More edits: skeletal mesh import onto a skeleton, a dynamic mesh started from a static mesh (
meshPath),mesh_materialsassetPaths, SDFrelativeTo, inputreplaceKeyandplayunpauseGame.
🔄 Changed
- The editor plugin is now EngineWire (was McpAutomationBridge), shipped as
EngineWire-plugin-<version>.zip, with file names short enough for Fab; settings saved under the old name still load. - A Blueprint graph batch is all or nothing: a failed step undoes the steps before it, and a step works in the graph of the node it names.
- Leaner replies: each actor is named once,
runtime_reportreports the session unless asked for more,get_component_detailssends values only forpropertyNamesordetailed, spawn batches past 20 items list only failures, and transforms read as typed. - The HTTP door takes capability IDs as the stdio door does.
- Widget templates take their content: a shop its
itemsandcurrency, a dialog itstextandbuttons.
🔧 Fixed
- Replies say what really happened: a widget rename refuses a taken name, a clean compile drops stale warnings, a Shipping smoke run says it wrote no log, compiler warnings reach the receipt,
stopanswers once play has ended, a link through a conversion node reads connected, and a self-destroying spawn, a destroyed actor, a game's own pause, a paused world, a minimized editor, a non-realtime screenshot and a widget holding the keyboard focus are named. - Blueprint graphs: enums keep their type, array pins say so, pins show a literal only where the graph reads one, call nodes take the names the editor shows, nodes made without a position find a free slot, refused nodes leave nothing, misspelled types are refused, child Blueprints edit their parent's components, and Math Expressions take a unary minus and
&&/||comparisons and still compile in a duplicated Blueprint. - Property values: Map, Set, array, float and Blueprint struct values read and write as sent, actor arrays take labels, a mesh component's StaticMesh goes through its setter, unknown variable names are refused, and
set_project_settingresolves a class name and refuses an unknown one. - Gameplay: projectiles hit, hurt and expire, weapons fire, doors, chests, switches and triggers work,
apply_forcepushes, placed props simulate, batch references land before BeginPlay, and a mouse move reaches a running game. - Input and motion: a key held across stepped frames counts game time and its reply says it is still down,
remove_mappingnames the action's ownactionMappings, a scripted mover reads its real velocity, and a reloaded level reads aslevelChanged. - Placement checks: no false off-map, sunk or floating reports for floors over pits, enclosures, stacked items, stretched parts and complex collision.
- Niagara: edits act only on the emitter the caller named (#658), create actions refuse a folder that cannot be a package (#668), modules go where their dependencies hold and are named as their inputs are, a duplicated system plays at once, and placed-effect parameters are typed and fully bindable.
- Assets: deletes count what they removed, a filtered list names only matching folders, imports name the mesh, Fab adds a pack's Unreal build, dead material branches list as orphaned, and material usage flags are saved.
- Geometry: appended faces face outwards, arrays are no longer one copy short, and SDF shapes mesh at the resolution asked for.
- Editor: a level load answers once the level has settled,
console_commandkeeps lines logged on other threads, and native replies write negative zero as0, which strict clients rejected (#662). - Builds: the plugin declares Win64, Mac and Linux, so an Android build skips it (#666), and it compiles again with Fab's UE 5.0-5.4 toolchains.
- Undo, search and guidance: volume and single-actor component edits are one undo step, more plain requests are found, a refusal names the parameter a stray key belongs to, a reply keeps the typed and project paths it quotes, and every pointer in record text names a real action.
🗑️ Removed
- Level-call aliases that were always refused:
open_levelpathandassetPath,focus_actorname,manage_leveldeletepathandlevelPaths,duplicate_leveltargetPath, andset_metadataandvalidate_levelassetPath. SendlevelPath,actorNameordestinationPath.
⚠️ Migration
- Plugin rename: delete
Plugins/McpAutomationBridgeand unpackEngineWire-plugin-<version>.zipin its place; a.uprojectthat namesMcpAutomationBridgeshould nameEngineWire. Settings under[/Script/McpAutomationBridge.McpAutomationBridgeSettings]still load while[/Script/EngineWire.EngineWireSettings]is empty. get_component_detailslists property values only withpropertyNamesordetailed: true.resumeanswersGAME_PAUSEDwhen the game paused itself (a pause menu or a title screen); passunpauseGame: trueto lift that pause too.- A spawn whose actor destroys itself answers
SPAWNED_THEN_DESTROYED, and property reads and writes refuse a destroyed actor. - Reply fields:
remove_mappingand a per-mappingset_modifierreturnactionMappings(wasmappingCountandmappings), andset_camerareturnsrequestedLocationandrequestedRotationonly when the pose was not taken.
🔄 Dependencies
👥 Contributors
- @SoloGorilla for making Niagara edits act only on the emitter the caller named (#658), and Niagara create actions refuse a folder that cannot be a package instead of reporting success with nothing saved (#668).
- @Robin7-hub-code for reporting the negative zero that strict MCP clients rejected (#661), and @HeCPDF for reporting the Android packaging failure (#665).
📊 Change Statistics
| Metric | Count |
|---|---|
| Diff range | v0.6.0-beta-e..v0.6.0-beta-f |
| Commits | 212, the version bump and this release entry included |
| Files changed | 1,976 (1,950 hand-written, not counting generated files or line-ending-only changes) |
| Insertions / deletions | 34,715 / 11,597 (hand-written: 26,407 / 10,792) |
| Capability records | 416 |
Callable {tool, action} pairs |
1,554 |
| C++ domain directories | 55 |
Release v0.6.0-beta-e
Note
Beta. Published as a semver prerelease (0.6.0-beta-e) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.5.30. This section is everything on dev since the v0.6.0-beta-d tag, written from the code diff.
✨ Added
- Control Rig graphs:
animation_physicsedit_control_rigadds, wires, sets and removes rig units and adds or removes bones, nulls and controls (or imports a skeleton's bones), one edit or a batch, then compiles;get_control_rigreads the graph and hierarchy;list_rig_unitsfinds units by name or category.
🛡️ Security
- The proxy's tool-list cache moved out of the shared temp dir to the user's cache folder (
%LOCALAPPDATA%,$XDG_CACHE_HOMEor~/.cache, underunreal-mcp), written owner-only, so another account cannot plant the tool list and instructions it serves. package-plugin.mjsrefuses an argument holding",%,!or a line break before it reachescmd.exe, and runs it with delayed expansion off.- source-map-js 1.2.2 (development only) clears GHSA-68fv-2mgg-jv7q.
📊 Change Statistics
| Metric | Count |
|---|---|
| Diff range | v0.6.0-beta-d..v0.6.0-beta-e |
| Commits | 4, the version bump and this release entry included |
| Files changed | 36 (27 hand-written, not counting generated files or line-ending-only changes) |
| Insertions / deletions | 1,868 / 95 (hand-written: 800 / 33) |
| Capability records | 405 |
Callable {tool, action} pairs |
1,518 |
| C++ domain directories | 55 |
Release v0.6.0-beta-d
Note
Beta. Published as a semver prerelease (0.6.0-beta-d) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.5.30. This section is everything on dev since the v0.6.0-beta-c tag, written from the code diff.
✨ Added
inspect.describe_view: what the level viewport's camera sees, as text: each actor's share of the frame, screen box, brightness and distance, plus the background share and the frame's brightness.inspect.capture_passes: aligned id (PNG with a legend), depth (EXR, cm) and normal (PNG) passes of the view, each with a summary.inspect.check_mesh: whether a static mesh is closed, with its holes, seams, inside-out and degenerate faces, parts, area and volume.inspect.raycast_world: up to 256 line traces against collision, each with its hit point, normal, distance, actor and component.manage_assetexport_mesh: a static or skeletal mesh (or an animation) to glb, gltf, fbx or obj, without the exporters' dialogs.process_assetmesh_collision: box, sphere, capsule, complex or no collision on a static mesh asset and its placed copies.manage_geometrysplit_mesh: one static mesh per separate part or material slot, withdryRun.- Material Parameter Collections:
create_materialkind: parameter_collectionand theCollectionParameternode. system_controllist_save_games/edit_save_game: read, edit, create and delete SaveGame slots.play_soundmeasure: plays a sound and answers how loud it was (peakDb,averageDb,silent, a wave'swavePeakDb).get_transformmotionpoints: bone, socket or component positions per sample with ground heights and planted and slip stats; samples carry rotation.validate_assetsdataValidationruns the project's and engine's validators;run_buildtestsanswers each test's result.manage_toolsget_task_result: reads a call that answered "still running"; the stdio server also answers so at 27 s.get_statsworldTickMs: the game world's own tick time while Play In Editor runs.add_functionoverrides a parent function such asOnKeyDown;add_variableexposeOnSpawn.set_propertyobjectPathswrites one value on many objects, andwatchsamples the written property by default;call_actor_functioncomponentNamecalls a component's function.- A Blueprint compile warns about a sound played at a location with no attenuation.
query_assettextfinds graph nodes by their title.- Widgets:
add_widget_treematerialpaints an Image or Border;add_animation_keyframekeyswrites a whole animation in one call. - Audio:
create_metasoundoneShot: falsemakes a continuous source; distance attenuation sets air absorption (lpf*) and reads back what it holds. - Sequences:
add_keyframekeys,set_section, keyinterpolationandlookAt,remove_keyframeframes, particle keys (particleKey) and NiagaramoduleEnabled. - Movie renders capture gameplay (
gameModeOverride: level, auipass,audioOutput), takerenderTimeoutMs, andcreate_render_jobcontrol: removeclears jobs. advance_simulationresetpreviews an effect at an exact age, and the reply gives itsageandcomplete.
🔄 Changed
- Lean replies on both transports: no log-only fields or repeated values; batches list only steps with something to say; a screenshot's bytes travel once over stdio.
describestates where a call runs: the calls that test a running game listpieandsimulate; Niagaraactivate,deactivateandresetwork in the level editor too.- Vector arrays coerce only when complete and numeric: two numbers no longer become
{x, y}with a defaultz; rotation arrays read[pitch, yaw, roll]. - A missing parameter names the keys sent in its place, and a reply names what ran when a call used another name.
🛡️ Security
- MCP SDK 1.32.1 and proxy-addr 2.0.8 clear GHSA-6qxp-vccf-f47h and GHSA-jqcg-44mw-7w3h.
🔧 Fixed
- Blueprint graphs: batches call custom events they create, check expressions before any step and name an unknown edit; math expressions name what is wrong and the pins they made.
- Pins and nodes:
connect_pinsgrows Sequence, Make Array and Switch on Int to the named pin, matches names without spaces and warns on a second Target object;create_nodemakes FlipFlop, DoOnce, DoN, Gate, typedGetAllActorsOfClassand native Break/Make nodes. - Blueprint assets: an unknown parent class is refused; class defaults reach placed actors and derived Blueprints; a removed root promotes its children; SCS adds say where a component went and what it set.
- Properties: writes go through component setters, fail when put back, reach subobject owners and say whether they saved;
markDirty: falsestays clean; paths reach components by name and any mount; bools answer withoutb; struct reads keep zero fields. - Actors in a running game:
deleteanddelete_by_tagremove them,call_actor_functionreaches the GameInstance, role names work in every lookup, spawns keep their mesh, andspawn_batchvariables land before BeginPlay. - Placement: a moved actor is solid where it stands; checks skip triggers, bodiless parts and invisible volumes and treat water as a surface;
fix_coplanarparts a flush row in one pass; collision changes hold on placed copies; floaters float. - Lists and reads:
listreads struct members andnearskips debug and editor-only bounds; multi-property reads keep dotted paths apart; the mesh view follows a placed actor; a missing asset reads as not found. - Widgets: create by
widgetPath, a tree root fills its canvas, a removed widget frees its names, new animations play from the graph at once, a key on an occupied frame replaces it, and previews show what the game shows. - Input: simulated keys reach a focused menu button and release on time while paused; widget input warns when a minimized editor holds widgets still.
- Materials: enum settings take the Details panel's names and are checked before anything is made; Custom node pins wire like any node's; compile errors come after the shaders compile; batch steps take
nodeKind;set_material_parametersays whether it saved. - Niagara: static switches read and set, standalone ribbons draw, renderer and mesh materials get their usage flags, objects support undo, bindings link the input, linked inputs show their source, parameter writes answer success, and
autoActivate: falsestays off. - Audio: MetaSound edits are heard at once and batches check classes and pins first and save once; placed sounds play in game; attenuation shapes take the radius on every axis;
measurereads a wave's own level. - Sequences: keys land as authored (sections span the range, auto tangents, Visibility tracks, transform defaults from the actor);
playandpauseseek withstartTime; skeletal tracks bind the root mesh; spawnables make their own template; full-path create and duplicate save. - Renders and retargets: a hung render frees the queue;
add_render_passnames what it added; retargets keep pelvis motion andcreate_ik_rigbuilds from a mesh. - Captures: screenshots after a camera move, full-window captures and captures right after an edit show the current state.
- Editor: console commands reach the running game; reflected calls run in the editor world; a restored window stays up;
step_framenames its speed; paused motion runs end at once andstartWhenreads component properties;read_loglivecodingreads this editor. - Search and receipts: text search finds assets picked on pins and keeps to its paths; graph lookup names the reader for non-Blueprint assets; Enhanced Input, foliage, folder moves, legacy mappings and deletes name what they changed;
save_allnames what it left. - Environment: water bodies come out complete with varied waves;
create_sdfnames a too-thin shape; spline reads give both point spaces;create_primitivewarns about a taken label. - Timing: Fab library and media waits count real time; an accepted file delete counts as done; a refused call's text summary no longer reads
success: true. - Builds: the plugin compiles again on UE 5.0-5.4, on Fab's MSVC and clang toolchains, and without the Geometry Script plugin.
👥 Contributors
- @SoloGorilla for stopping the gateway from making partial or non-numeric vectors out of arrays (#657).
📊 Change Statistics
| Metric | Count |
|---|---|
| Diff range | v0.6.0-beta-c..v0.6.0-beta-d |
| Commits | 171, the version bump and this release entry included |
| Files changed | 467 (447 hand-written, not counting generated files or line-ending-only changes) |
| Insertions / deletions | 19,964 / 4,034 (hand-written: 13,982 / 2,601) |
| Capability records | 402 |
Callable {tool, action} pairs |
1,515 |
| C++ domain directories | 55 |
Release v0.6.0-beta-c
Note
Beta. Published as a semver prerelease (0.6.0-beta-c) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.5.30. This section is everything on dev since the v0.6.0-beta-b tag, written from the code diff.
Important
🔍 The editor checks its own work, and long calls stay alive
Spawns, Blueprint component edits and mesh conversions measure where the result landed and name what is sunk, buried, floating or z-fighting; sample_motion plays and times a game over game time without the OS cursor; and a call that runs past the client's time limit answers that it is still running instead of failing. New one-call authoring covers smooth SDF shapes, polygon cages, text textures, whole widget layouts, palettes of material instances and several properties at once; Epic's 5.8 editor toolsets run behind the gateway's scopes and consent, and Fab imports run in the background. Contract changes are listed under
✨ Added
server/discoveranswers on both transports. The MCP 2026-07-28 discovery method (missing, it failed six conformance checks in #614) returns the protocol versionsinitializenegotiates, the same capabilities, instructions and server identity, and an hour-long public cache hint, with no session or handshake. The 2026-07-28 revision itself is not served, so a client on it falls back toinitialize.- Epic's 5.8 editor toolsets run through the gateway, behind its scopes and consent.
control_editor.list_editor_toolsetslists the tools of Epic's Toolset Registry (StateTree, PCG, GAS, Niagara, UMG, MVVM and more, as their plugins are enabled), each with an effect judged from its name, or returns one tool's input schema (toolName).call_editor_toolruns one and answers with its output; a tool named for deleting or resetting is refused withDESTRUCTIVE_EDITOR_TOOLand runs throughcall_editor_tool_destructive(destructive scope, elevated consent), and a tool that would run scripts or console code is never called (EDITOR_TOOL_BLOCKED), nor is any tool ofConfigSettingsToolset, which writes any settings section, this bridge's own included (project settings stay onsystem_control). Before 5.8 they answerEDITOR_TOOLSETS_UNAVAILABLE. inspect.raycast_meshfinds a mesh's surface. Up to 256 rays at a static mesh asset in its own local space answer with the point each one meets, the surface normal (facing back along the ray), the material slot and the rotation a decal needs to print upright there, from the source triangles (full detail on a Nanite mesh), with no placed actor or collision. A part, print or decal can be put exactly on a curved surface.- Text becomes a texture.
create_texturewithkind: "text"(create_text_texture) draws words with any Font asset and face (fontFamily,typeface, default Roboto Bold),letterSpacing,justificationandpadding, at the largest font size whose lines (letter spacing included) fit the texture, incoloroverbackgroundColor(default transparent, so the alpha channel is the text mask). The reply lists the font's faces and the pixel box the letters cover; a face the font lacks is refused with the faces it has. - A palette of material instances takes one consent.
create_material_instanceinstances(up to 64{name, parentMaterial, savePath, parameters, save}) makes each one as a single call would, with the call's ownparentMaterial,savePathandsaveas every entry's defaults; the reply lists each underinstanceswithcreated, and the call fails naming any that were not made. Seven instances of one parent took seven describes and seven consents. Retuning them is one consent too:set_material_parameterassets(up to 64{assetPath, parameters}or{assetPath, parameterName, value}) writes each as a single call would and the receipt lists every instance it changed. - A whole widget layout is one call.
add_panel_widgetwidgetKind: widget_treebuilds a nestedtreeof panels, borders, text, images and bars with their looks (size, face, letter spacing, outline and shadow on text; rounded corners and an outline on a border) and their slots, refuses an unknown field instead of ignoring it, and lists every widget it made. A HUD cost an add call per widget and a style call per look. - Every material slot of an actor in one call.
set_materialmaterialsputs entry i into slot i (""leaves a slot alone) in one undo step: an SDF part with six slots took six calls. - Several properties in one call.
set_propertyproperties({name or dotted path: value}) writes each as a single call would and reports them underproperties;get_propertypropertyNamesreads several, answeringpropertiesand naming any that do not resolve undermissingProperties. spawntakes a mesh path alone. The handler placed a mesh actor for a baremeshPath, but the schema refused the call without a class.- A server and plugin from different releases say so, and name the fix. The plugin reports its version in the bridge handshake; when it is not the server's (or a plugin too old to report one), the server logs a warning and every failed
executecarriesversionMismatch: both versions, the release page of the matching plugin, and thenpx -y unreal-engine-mcp-server@<plugin version>pin that matches the server to the plugin instead. unreal-engine-mcp-server proxykeeps a native session across editor restarts. A stdio server in front of the plugin's/mcp(UNREAL_MCP_URL, defaulthttp://127.0.0.1:3000/mcp): while the editor is down every call answersNOT_CONNECTED, and the first call after it is back opens a new upstream session and runs, so the client never reconnects. It sends the capability token the stdio server would find, relays progress notifications as they stream, and caches the editor's tool list and instructions (UNREAL_MCP_PROXY_CACHE) for sessions that start before the editor.control_actor.sample_motionwatches an actor over game time in PIE. It returns location, velocity andpropertyNames("Component.Property"ok) everyintervalSecondsfordurationSeconds(max 30 s, 400 samples) withstart,end,min,maxandendedBecause; the editor world givesNOT_SIMULATING.inputs(up to 32{key, atSeconds, holdSeconds}) press keys at game-time offsets,startWhenholds the run until another actor's property takes a value,maxRealSeconds(default 25, max 50) caps wall time, and a start that never fires, keys that did not move the pawn or a slow frame rate warn. A minimized editor is shown without focus for the run (windowRestored) with the background CPU throttle off, then minimized again. Alsoget_transform'smotionread.control_actor.listfinds actors by place and kind.near([x, y, z]or{x, y, z}) sorts nearest first, then smaller bounds, and adds each row'sdistanceto the actor's bounds;radiuskeeps those within it.tag,className(class or any parent, by name or path,_Coptional) andfolder(that folder and below,"(none)"for the root) filter, and every filter combines withsummaryand with each other;propertyNamesreads"Component.Property", unmatched names undermissingProperties.set_transformmoves by an offset.offset[dx, dy, dz], also per item inactors, moves relative to the current location; withlocationit is refused withINVALID_ARGUMENT.control_actor.renamerenames an actor. It sets the label (INVALID_NAMEif refused) and, withrenameObject, the object name too (made valid and unique); the reply hasoldLabel,label,oldObjectName,objectNameandactorPath.audit_placementfinds z-fighting andfix_coplanarfixes it.audit_placementreportscoplanarFacesper finding (kindcoplanar,byKind.coplanar, read from each mesh's LOD0 triangles, also for actors taggedmcp.placement.ok) and takeskindsto limit problem kinds.fix_coplanarmoves each facedistance(0.1-20, default 1) in up to 4 passes as one undo step (dryRunis one pass); parts of one Blueprint are fixed in the Blueprint itself (compiled and saved, every placed copy fixed;blueprintsFixed), andskippedholds only the pairs left alone, with a reason.componentNamesnarrows a component listing oncontrol_actorget_components,inspectget_componentsandinspect_cdo: it keeps the named components (case-insensitive) and lists misses undermissingComponents. A mesh component's row names itsstaticMeshandmaterialson a world actor too, not only in a Blueprint.- Every spawn says where the actor ended up.
spawn,spawn_blueprintand eachspawn_batchrow report whatset_transformreports:placementWarning(sunk into the surface under it, floating, intersecting other actors or nothing below),groundZ,groundClearance,overlappingActorsandsuggestedLocation, where a mesh whose pivot is its bounds centre spawned half under the floor behind a bare success (spawn_blueprintnever checked, andspawn_batchdropped what each item's spawn found). A batch measures each item after its tags, somcp.placement.oksilences a deliberate placement;placementWarningscounts the flagged items (a warning is not a failure) andreport: "failures"keeps them.suggestedLocationis the actor's own location raised by the depth it is sunk, whatever its pivot (it was the bounds centre, which moved a corner-pivot mesh sideways). - Blueprint parts that sink into each other are named. Every
edit_scsedit that adds, moves, re-meshes, re-parents or sets a property on a component measures the mesh parts it touched against the rest of the actor, on their real triangles in a preview instance (the level is untouched), and returnspartWarningswith awarningssentence each:kindburied(inside...
Release v0.6.0-beta-b
Note
Beta. Published as a semver prerelease (0.6.0-beta-b) under the npm beta dist-tag, so npm install keeps serving the newest stable release, 0.5.30. This section is everything on dev since the v0.6.0-beta-a tag, written from the code diff.
Important
🧱 Fewer calls, honest replies, and a game you can drive from the tool
Batch forms turn a Blueprint graph, a material graph, a MetaSound, a whole level layout or a row of actors into one call each, and a Play-In-Editor game can be played, timed and inspected without the OS cursor. A long list of handlers that answered success for work they never did now report what actually happened. Two small contract changes are listed under
✨ Added
One call instead of many
manage_blueprint.build_graph— runs up to 200 graph edits (create_node,connect_pins,set_pin_default_value,set_node_property,create_reroute_node,add_variable) through the ordinary single-step handlers, with their replies captured instead of sent. A step names its node withidand later steps refer to it as"$id";from/totake"$id.pin"shorthand; a create step can carrypinDefaults;"$entry"is the graph's own function-entry node (a Construction Script's start). Nodes without a position fill a grid to the right of the existing graph, and an overlap is retried at the guard's own suggestion. Before any step runs, every function and variable a step names is resolved, so a misspelled name fails the batch with nothing applied; any other failure stops at that step and returns the node ids of the steps that were applied. The Blueprint compiles and saves once at the end.manage_material_authoring.build_material_graph— adds a material's nodes, wires them and sets blend mode, shading model, domain and two-sidedness in one consented call, then recompiles and saves once throughcompile_materialand reports its errors. Only additive edits are batched; deleting and disconnecting keep their own consent. Auto-placed nodes are stacked by their reported height, so tall vector-parameter swatches no longer overlap.manage_audio.build_metasound— MetaSoundadd_node,connect,set_default,add_inputandadd_outputsteps in one call, with the same$idaliases.control_actor.spawn_batch— up to 500 actors per call, each item merged over shareddefaultsand run through the ordinary spawn path (mesh, class or Blueprint, per-itemvariables, folder, tags). A failed item is reported and the rest still spawn;report: "failures"returns counts and failed items only.- List forms of existing actions, each item running the single-item path and each reported, with a batch that fails naming only the items that did not apply:
set_transformactors(each with its own location, rotation or scale, as{x,y,z}objects or arrays),set_blueprint_variablesactors(each with its own values),set_materialandadd_tagactorNames,delete_by_tagtags,remove_scs_componentcomponentNames,set_variable_metadatavariableNames,set_material_parameterandcreate_material_instanceparameters, andremove_foliageareas. One consent grant covers the whole list. - An omitted fold selector is inferred — a call that leaves out a family's selector (for example
nodeKind) but sends parameters that only one variant declares now runs that variant on both gateways; parameters pointing at different variants still run the default.
Reading what is already there
control_actor.listpages withoffsetandnextOffset, carries each actor's location, rotation and scale, reads named variables on every row withpropertyNames(a name the class lacks is listed undermissingPropertiesinstead of vanishing), and withsummary: truecounts actors by class, tag and outliner folder instead of listing them.inspect_graphfilters and pages a large graph, and a pin's links name the linked node's title.get_blueprintwithpropertyNamereturns just that value (read off the class default object when the property is inherited) instead of the whole summary; Blueprintget_componentsgives each component's location, rotation, scale, visibility, mesh, materials and whether it is authored, inherited or native.get_niagara_infolists every emitter's module inputs with their current values.manage_asset.listnarrows by name with a stringfilter(it used to be ignored).system_control.read_logreturns the recent editor log without a subscription, filtered by text, category or minimum verbosity.sourcereads the UnrealBuildTool log of the last compile (where "Live coding failed" keeps its compiler errors, with the file name kept readable), the Live Coding console log, or a previous editor run's log;runsBackreaches past the last restart, andlogFilenames the file read.console_commandreturns the lines the command logged.
Driving and testing a running game
simulate_inputdrives Enhanced Input —inputAction(an asset path),valueandholdSecondsinject the action itself, which a raw key never reaches; the reply namesinjectedAction. Holds are measured in game seconds and all end when the editor shuts down;key_tappresses and releases, keeping the key down for at least two game frames.widget_listnames every live UMG widget in a PIE session andwidget_clickpresses a Button, toggles a CheckBox or sets a Slider by name, without moving the OS cursor or taking focus.- The game clock acts on the running game —
set_game_speedandset_fixed_delta_timeapply to the PIE world (a fixed step is switched off again when play stops), andstep_framesteps the requested number of frames in the plugin and reports them. control_editor.restore_editor_windowrestores a minimized editor window without activating it, and by default turns off the background CPU throttle that pins a minimized editor's PIE at about 3 fps.control_editor.restart_editorrelaunches the editor on the same project, withvalidateOnly,delaySeconds, anddiscardUnsaved(unsaved packages are refused otherwise).system_control.launch_buildsmoke-runs the game thatpackage_projectproduced (offscreen by default, 5 to 120 seconds) andpackage_statusreports the maps it loaded, its error count and the tail of its log.
Authoring
- MetaHuman Creator in
manage_character—metahuman_status,create_metahuman,rig_metahuman(Epic's cloud auto-rig, non-blocking by default),build_metahumanandexport_metahuman(geometry, materials or DNA). - Sequencer keys —
list_track_keysandremove_keyframeinmanage_sequence, resolving tracks the same way every other track edit does;onlyJobis honoured when a Movie Render Queue render starts. - Animation Blueprints —
set_transition_rulesbuilds the transition condition fromconditionVariable,conditionComparisonandconditionValue;delete_transitionremoves one; transitions honourcrossfadeDuration(aliasblendTime),priorityOrder,automaticRuleandbidirectional;add_statewires the state's entry and, with an animation, a sequence player into its result. animation_physics.skin_mesh_to_skeletonskins a static mesh (or a donor skeletal mesh) to a skeleton through GeometryScripting; retargeting builds real IK Rig definitions and a retarget pipeline.- Blueprint graphs —
set_node_propertyreaches a node's reflected asset and object fields;add_variablestores object defaults and keepsisPublic: false. - Fab is driven through its own API by reflection: the tab opens without the web page, an already-open Fab window is reused, listings are claimed before download, and
objandusdzdownloads are accepted alongsideunreal-engine,gltf,glbandfbx. - FBX animation import —
manage_asset.importbrings in the animation an FBX carries as an AnimSequence on a named skeleton.
Finding the right capability
- Plain phrasings rank the intended capability first, native
searchhonours theeffectandtoolfilters, andcreate_material, material instances, widget clicks and map cooking each have search topics of their own.
🔧 Changed
- Native requests are timed from their last progress, not their start. While the game thread is alive, every open request gets a "still working" progress notification every 20 seconds,
MaxLifetimeSecondsstill ends a request that never answers, and progress percentages never go backwards. Long imports and builds are no longer killed and reported as failures. - A too-large result names the parameters that would narrow it on the native gateway as well, and
summarycounts as a narrowing parameter on both. - A world edit made during Play-In-Editor carries a receipt warning that it landed in the PIE world and is discarded when play stops.
- Text summaries pair a record's display name with its path, asset path, object path or id.
- The
.envfile is read fromMCP_ENV_FILEwhen it is set, otherwise from the package root, otherwise from the working directory, using Node's own loader. - A client's capability profile comes from the capabilities the client declares, not from a lookup table of known client names.
- The console command policy compiles each rule's pattern once instead of on every command, and every command-queue failure is logged.
- Lighting and geometry records declare what their handlers read —
configure_lumentakesquality,indirectLightingIntensityandbounces;configure_shadowstakes the shadow quality, cascade, distance, contact, ray-traced and virtual-shadow-map settings;configure_exposuretakesmethod;enable_volumetric_foghonoursenabled: false; the geometry primitives take their own dimensions (boxheight...
Release v0.6.0-beta-a
Note
Beta. Published as a semver prerelease (0.6.0-beta-a) under the npm beta dist-tag, so npm install keeps serving the newest stable release. 0.6.0a is not valid semver — npm, the bump-version workflow and the version-consistency gate all reject it — so the release spells the beta out.
Important
🚪 Single-Tool Gateway, Capability Catalog & Full Source Reorganization
Everything on this branch since the 0.5.30 tag: the permanent cutover to a single public unreal gateway tool, a hand-authored capability catalog that now generates both the TypeScript and the C++ contract surfaces, cinematics/render/replay automation, and a top-to-bottom split of the TypeScript handlers and the C++ plugin into per-domain modules.
This release contains breaking changes — see the
✨ Added
- Folded capability families — a record can stand for a whole family of bridge actions.
routing.dispatchBymaps one selector parameter's value to the existing handler action, and every former name stays callable as a folded legacy pair whose pins supply the value it implied; both gateways apply the same two steps (pins before validation, action after it). The folds are data (records/folds/<parent>.folds.ts, applied byrecords/shared/fold.ts): 244 fold families across 22 parents (222 of the resulting records dispatch through arouting.dispatchByselector — 221 of them from the fold specs, plusmanage_level_structure.create_volume, whosevolumeClassdispatch is authored on the record itself — and the remaining 23 families are pure-alias folds; 246 of the 380 records carry at least one folded legacy pair, across 1,166 pinned pairs) take the catalog from 1,379 authored pre-fold action entries to 380 records, while all 1,549{tool, action}pairs (every shipped name plus 164 new family primaries) still resolve, describe and execute, the normalization audit total is unchanged at 1,341, and a fold whose primary is one of its members keeps the selector optional so every pre-fold call is unchanged. A consent grant may name the capability by any name it answers to (canonical id, alias, or a foldedtool.actionpair) on both doors; the native completion pool completes the old names too; the search index counts a name once per identifier field and stops re-scoring folded member ids as aliases. Per-action contract tests pin the authored, unfolded records (records/unfolded.ts), and the integration suites derive one twin case per family (tests/fold-twins.mjs) so every advertised primary and selector is exercised.
Gateway surface
unrealgateway tool with four operations —search,describe,execute, andconfigureare now the entire public MCP surface on both transports. The routing engine lives insrc/server/gateway/(26 TypeScript modules) and covers capability indexing and views, search filters, browse/capability describe modes, execute resolve → validate → policy → authorization → dispatch, receipt context, schema normalization, guidance, and availability probing.- Execute idempotency ledger — repeat
executecalls carrying the same idempotency key return the original receipt instead of re-running the action. Mirrored on both sides of the bridge: TypeScript (src/server/gateway/idempotency-ledger.ts, cap 1024) and C++ (Private/Foundation/McpIdempotencyLedger, cap 4096). - Compensation receipts and capability principals —
Private/Foundation/McpCompensationReceiptandMcpCapabilityPrincipal/McpCapabilityAuthorizationgive the plugin its own authorization identity rather than trusting the caller's claim. DIRECT_TOOL_CALL_REMOVEDmigration receipt — a directtools/callon a canonical parent name returns a bounded, executable receipt whosenextCallre-runs the same request through the gateway.- Execute option validation and refusal —
timeoutMsmust be an integer in 1..600000 ms andidempotencyKey1..128 characters — a malformed key previously bypassed the ledger entirely, so a retry re-ran the mutation with nothing reporting that dedup was off.previewis refused outright withUNSUPPORTED_PREVIEW(no dispatch path implements a dry run, andbehavior.supportsPreviewis deliberately not consulted, because honouring it would perform the real mutation and call it a preview), and an option that is accepted but not implemented (savePolicy,validationLevel,taskPreference) answersUNSUPPORTED_OPTIONinstead of being validated, echoed on a success receipt, and dropped. AnexpectedCatalogRevisionthat no longer matches answersSTALE_STATE. A result that would exceed the transport budget is refused asRESULT_TOO_LARGE(100,000 characters, 6,000,000 for image-payload capabilities) on the failure path as well as the success path. - Bounded search —
limitdefaults to 12 and is capped at 25, a page is additionally held tomaxBytes(default 24,576, floor 512, ceiling 262,144) by dropping whole trailing rows, andhasMore,truncated,truncationReason,nextCursor,coercionsandbudgetExceededreport exactly what happened: an argument that was clamped is named, a page that could not fit even one row answersbudgetExceededinstead of returning an identical cursor forever, and a truncated page says why. A capability id or alias that collides in the index fails closed withGATEWAY_INDEX_CONFLICTrather than resolving to an arbitrary record.
Capability catalog and contract generation
- Hand-authored capability records as the single source of truth —
src/tools/catalog/capabilities/records/**holds 380 records across the 23 canonical parents, authored withbuildCoreRecord()declaring deltas only.aggregate.tshard-asserts the record count and throws on mismatch. - Generation pipeline —
scripts/generate-canonical-registry.ts(+ thescripts/canonical-registry/modules) emits the generated capability shards, the orchestration routing index, the docs action reference, and the C++ side:Private/MCP/Generated/shards andMcpGeneratedParentRegistry*.scripts/generate-gateway-manifest.ts(+scripts/gateway-manifest/) emitssrc/gateway/gateway-manifest.generated.{ts,json}with content hashing and path policy. - New drift gates —
registry:generate,registry:check,manifest:check,policy:generate,policy:check,normalization:check,normalization:audit,migration:check,primitives:check,security:check,eval:check,version:check,workflow:check. - Deterministic ordering helper —
src/utils/serialization/ordering.tsprovides byte-order comparison so generated shards are byte-identical across machines and locales (localeCompareis no longer used for ordering).
MCP protocol primitives
- Resources, prompts, completions and progress — new
src/server/mcp-primitives/implements the primitive registry, wiring, handlers, notifications, catalog revision reader, and fallback pointers, with a prompt catalog and typed prompt errors, a completion provider (ranking, slots, sources, fixtures), and a progress reporter/token/sink registry. - MCP Tasks (
2025-11-25) — a per-session bounded task store implementing the MCP SDK's ownTaskStorecontract, sotasks/get|list|cancel|resultare auto-registered and reachable from the wire. It deliberately does not reuse the SDK'sInMemoryTaskStore, which is unbounded, drives expiry off realsetTimeouttimers, and ignoressessionIdentirely. Task checkpoints ride alongside it. - Resource subscriptions and revisions — a subscription store with a notification coalescer so bursts of editor changes collapse into one client notification, plus resource revision stamps for change detection.
- Session capability profiles and
configurestate — a client profile store, a session capability profile and a session configure store model the gateway'sconfigureoperation and per-client capability negotiation. The session resolver is exercised by tests only — nothing in the stdio path installs one yet. - Elicitation decision policy — a decision policy (
isSafeToElicit) that answers whether a field is safe to elicit. Elicitation itself is wired into the execute path:dispatchAndValidate()awaitsmaybeElicitMissingArgs(), which prefills only missing required primitive fields through the client's elicitation function, under a timeout and amissing-paramsfallback. It never elicits secrets, tokens, or credentials, and never a destructive-confirmation value. Mirrored natively for cross-transport parity. - Resource providers — new
src/resources/supplies capability resources, editor-state resources, knowledge resources, the resource catalog, read router, typed resource errors, and asset pagination. - Native primitive parity — the plugin gained matching
Private/MCP/Primitives/,Resources/,Routing/,Execute/,Gateway/, andDynamicTools/modules (task store and methods, subscription store, notification coalescer, completion pools and provider, prompt catalog/render/argument validation, client profile store, elicitation policy), audited by theprimitives:checkparity harness. - Protocol negotiation — support for
2025-11-25plus the native transport'sMCP-Protocol-Versionheader guard: a present-but-unsupported version is refused with HTTP 400, while an absent header derives from the session's negotiated version and otherwise falls back to the2025-03-26default. Native accepts the three modern versions; the TypeScript SDK additionally accepts two legacy ones, from the pinned SDK's own supported set rather than from code in this repository. - Bounded task store and progress — only
searchanddescribemay be task-augmented; any mutating operation, and any tool other thanunreal, is refused withTASK_CHECKPOINT_REFUSEDbefore any work runs. The per-session store is capped at 32 tasks w...
Release v0.5.30
Important
🚀 Native MCP & Code-Backed Tool Parity Release
This release covers the v0.5.21 to 0.5.30 release diff, including the TypeScript MCP server, native bridge plugin, tests, scripts, docs, workflows, and dependency manifests. The summary below is based on code and test changes, not commit subjects alone.
✨ Added
- Native MCP Streamable HTTP endpoint — added an opt-in in-plugin
/mcpserver with JSON-RPC 2.0 initialize/tools/list/tools/call handling, POST/GET/DELETE routing,Mcp-Session-Idsession tracking, SSE tool-result streaming, progress notifications, persistent notification streams,notifications/tools/list_changedbroadcasts, CORS handling, loopback-first binding, capability-token checks, and an editor status-bar indicator. - Self-describing native MCP tools — added C++
FMcpToolRegistry,FMcpSchemaBuilder,MCP_REGISTER_TOOL, canonical native tool filtering, cached schema generation, and native dynamic tool/category enablement for the 23 canonical parent tools. - PCG automation — added
manage_pcgTypeScript/native schemas and handlers for graph/subgraph creation, PCG node aliases, pin connections, reflected node settings, component/world execution, partition grid configuration, save/overwrite behavior, and PCG plugin availability errors. - Environment systems automation — added build-environment coverage for heightmap import/export, landscape layer info/material/splines/LOD/streaming proxies, foliage type configuration/paint/remove flows, sky and volumetric-cloud setup, weather/wind/time-of-day systems, water bodies, water waves/material/collision, and buoyancy components.
- Behavior Tree authoring and introspection — added
add_subnode, root-sentinel decorators, decorator/service validation, subnode-aware lookup,FBlackboardKeySelectorassignment, andget_treeruntime hierarchy serialization with root decorators, edge decorators, decorator ops, services, key properties, subtree references, and a success-with-null-root contract for graphless trees. - Blueprint, property, and inspection tools — added
inspect_cdo, Class Default Object component/property export, SCS and inherited SCS component classification, typed Blueprint custom-event pins, Enhanced Input graph nodes, inherited variable/member-class graph node lookup, and property access for Blueprint-added SCS component templates. - Editor, world, and input capabilities — added full editor-window screenshots, game viewport screenshot routing, image content responses, simulated keyboard/mouse input aliases, active camera reporting, PIE runtime inspection, native
get_current_level, actor material/view-target native actions, spawn scale support, and create-plane height handling. - Material, audio, animation, and system actions — added Material Function creation/editing/calls/info, FunctionInput/FunctionOutput graph support, source-effect chains and source-effect presets,
force_rebuild_blend_space, legacy/per-key input mapping edits, project setting writes, native asset validation, andexecute_pythonfor inline or project-local Python files.
🛡️ Security
- GraphQL attack surface removed — deleted the GraphQL server, schema/resolver/loaders, GraphQL docs, GraphQL unit tests, and direct GraphQL runtime dependencies.
- Native MCP exposure controls — default native MCP binding stays loopback-only unless explicitly allowed; non-loopback hosts warn, sessions are validated, stale requests/streams are cleaned up, and native HTTP requests use explicit request-origin routing instead of socket inference.
- Capability-token and dynamic-tool protections — native MCP validates
X-MCP-Capability-Tokenwhen required, while both TypeScript and native dynamic tool managers protectmanage_tools/inspectand protected categories from accidental disablement. - Python execution hardening —
execute_pythonenforces code/file exclusivity, a 1 MB inline code limit, project-root path normalization, symlink escape checks,__file__setup for file execution, temp-file cleanup, and directPythonScriptPluginexecution. - Path, command, log, and workflow hardening — tightened UE path normalization, console-command validation, snapshot/log path handling, level save/load flows, image/log redaction, safe
tmp/cleanup, sync-script argument parsing, and GitHub Actions interpolation by moving untrusted values into environment variables.
🔧 Changed
- Release metadata — updated
package.json,package-lock.json,server.json, thesrc/index.tsfallback, andMcpAutomationBridge.upluginto0.5.30. - Canonical TypeScript tool surface — kept the 23 parent tools but moved action lists into shared constants, grouped tools into
core,world,gameplay, andutility, merged nestedparamsinto top-level arguments for constrained clients, centralized handler routing, and removed legacy per-domain tool files. - Dynamic tool listing —
tools/listnow checks known client support fortools.listChanged; dynamic clients can receive category-filtered tools, while clients without dynamic loading still see the full compatible tool surface. - Automation bridge lifecycle — refactored host/port parsing, multi-port WebSocket connection attempts, handshake metadata, request queueing, progress timeout extension, stale-progress detection, absolute timeout caps, rate/message-size boundaries, disconnect/error tracking, and image-payload redaction.
- Native bridge runtime — split request dispatch out of the subsystem, added explicit
ERequestOrigin, queued requests through the game thread, converted captured engine errors into failed responses, pumped GameThread tasks during native transport shutdown, and exposed native transport session/tool counts to UI. - Response and schema handling — improved response validation, summary text generation, image response content, scalar result promotion, safe JSON cleanup, schema reuse, action-specific parameter descriptions, and stricter error context on tool failures.
- Plugin compatibility — updated bridge metadata for UE 5.8 Preview and added PythonScriptPlugin, StructUtils, Synthesis, and PCG plugin declarations where the new handlers need them.
- Scripts and workflows — made smoke tests run through SDK
InMemoryTransport, added native parity/parameter audit npm scripts, changedcleanto removetsconfig.tsbuildinfo, added Linux/macOS/Windows plugin packaging scripts, strengthened sync/cleanup scripts, and made CI/publish/release gates stricter.
🛠️ Fixed
Routing & Native Tool Parity
- Fixed native/consolidated action routing for validation, audio creation, material graph pins, editor simulation,
add_widget_child,get_current_level, AnimBP graph discovery, lighting, SCS edits, native actor/editor actions, exact action matching, and nestedparamspayloads.
Blueprint, Graph & Property Handling
- Fixed inherited UPROPERTY lookup for VariableGet/VariableSet with
memberClass, staleK2Node_EnhancedInputActiontitle cache refresh, Blueprint SCS component introspection, SCS template get/set paths, typed custom-event pin reconstruction, transaction ordering, null pin checks, case-insensitive pin connections, graph allocation fallback, and Blueprint busy-state cleanup.
Editor, World & Gameplay Behavior
- Fixed PIE/game viewport screenshots, full editor screenshot capture, simulated input dispatch, active camera view-state reporting, PIE runtime inspection, spawn scale application, plane height fields, landscape bounds fallback, prompt-save return codes, actor list response handling, editor/world handler stability, and native actor/editor contract alignment.
Asset, Level, Animation, Niagara & Audio
- Fixed unloaded level info via AssetRegistry fallback, classNames-only recursive asset search, normalized level path validation, source audio persistence, source-effect routing, audio authoring saves, material expression aliases, material pin routing to main inputs, UMaterialFunction graph details, animation notify validation, BlendSpace grid rebuilds, Niagara crash paths, hollow getters, parameter aliases, FText and FText-array property serialization, and
execute_pythonfile mode/output capture.
Plugin Stability & Compatibility
- Fixed native plugin compatibility across UE versions, macOS Clang audio literal builds, plugin package output detection, bridge socket/runtime handling, JSON key normalization, request telemetry, native MCP session validation, safe operations includes, handler review findings, and optional module/plugin availability paths.
🧪 Tests
- Added/expanded Vitest coverage for automation bridge connection, handshake, message schema, request tracking, config defaults, resources, health/metrics services, response validation, command validation, log reading/redaction, safe JSON, type coercion, normalization, queues, elicitation, and consolidated handler routing.
- Expanded MCP integration suites across core/world/gameplay/utility tools, including PCG, Behavior Tree subnodes/get-tree, networking/sessions/input, control-editor screenshots/input, actor list handling, audio/source effects, assets/material functions, Blueprints/SCS, levels, geometry, GAS, combat, inventory, interaction, sequence, environment, and system-control Python/project-setting flows.
- Added static native MCP action parity auditing and strict parameter-combination auditing that compare TypeScript schemas, native C++ tool definitions, native canonical registration, and test coverage.
- Hardened the custom test runner with richer assertions, captured variables, live/static reports, fake-success detection...