unreal-engine-mcp-server 0.6.0-beta-c → 0.6.0-beta-e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +148 -9
  2. package/README.md +2 -2
  3. package/dist/gateway/gateway-manifest.generated.json +838 -133
  4. package/dist/proxy/native-proxy.js +6 -5
  5. package/dist/server/gateway/gateway-execute-dispatch.js +2 -1
  6. package/dist/server/gateway/gateway-execute-envelope.js +5 -1
  7. package/dist/server/gateway/gateway-execute-lookup.js +1 -1
  8. package/dist/server/gateway/gateway-execute.js +17 -4
  9. package/dist/server/gateway/gateway-schema-validate.js +13 -2
  10. package/dist/server/gateway/gateway-task-results.d.ts +6 -0
  11. package/dist/server/gateway/gateway-task-results.js +40 -0
  12. package/dist/server/tool-registry-manage-tools.js +4 -1
  13. package/dist/tools/catalog/capabilities/generated/canonical-registry.generated.d.ts +2 -2
  14. package/dist/tools/catalog/capabilities/generated/canonical-registry.generated.js +2 -2
  15. package/dist/tools/catalog/capabilities/generated/canonical-registry.generated.json +4079 -618
  16. package/dist/tools/catalog/capabilities/generated/capability-cost-index.generated.d.ts +1 -1
  17. package/dist/tools/catalog/capabilities/generated/capability-cost-index.generated.js +18 -1
  18. package/dist/tools/catalog/capabilities/generated/parent-tool-definitions.generated.js +1546 -212
  19. package/dist/tools/catalog/capabilities/records/aggregate.d.ts +1 -1
  20. package/dist/tools/catalog/capabilities/records/aggregate.js +1 -1
  21. package/dist/tools/catalog/capabilities/records/build-environment/spline.data.js +4 -3
  22. package/dist/tools/catalog/capabilities/records/build-environment/water.data.js +8 -5
  23. package/dist/tools/catalog/capabilities/records/control-actor/advanced-records.js +29 -8
  24. package/dist/tools/catalog/capabilities/records/control-actor/search-records.js +2 -2
  25. package/dist/tools/catalog/capabilities/records/control-actor/spawn-records.js +13 -5
  26. package/dist/tools/catalog/capabilities/records/control-actor/state-records.js +2 -1
  27. package/dist/tools/catalog/capabilities/records/control-actor/transform-records.js +27 -9
  28. package/dist/tools/catalog/capabilities/records/control-editor/asset.js +4 -1
  29. package/dist/tools/catalog/capabilities/records/control-editor/camera.js +5 -1
  30. package/dist/tools/catalog/capabilities/records/control-editor/command.js +5 -1
  31. package/dist/tools/catalog/capabilities/records/control-editor/input.js +2 -1
  32. package/dist/tools/catalog/capabilities/records/control-editor/screenshot.js +2 -1
  33. package/dist/tools/catalog/capabilities/records/control-editor/session.js +8 -1
  34. package/dist/tools/catalog/capabilities/records/control-editor/timing.js +5 -3
  35. package/dist/tools/catalog/capabilities/records/core/builder.d.ts +1 -0
  36. package/dist/tools/catalog/capabilities/records/core/builder.js +1 -0
  37. package/dist/tools/catalog/capabilities/records/folds/build-environment.folds.js +2 -2
  38. package/dist/tools/catalog/capabilities/records/folds/control-actor.folds.js +2 -2
  39. package/dist/tools/catalog/capabilities/records/folds/manage-asset.folds.js +8 -8
  40. package/dist/tools/catalog/capabilities/records/folds/manage-audio.folds.js +5 -5
  41. package/dist/tools/catalog/capabilities/records/folds/manage-blueprint.folds.js +2 -2
  42. package/dist/tools/catalog/capabilities/records/folds/manage-effect.folds.js +3 -3
  43. package/dist/tools/catalog/capabilities/records/folds/manage-sequence.folds.js +6 -6
  44. package/dist/tools/catalog/capabilities/records/folds/system-control.folds.js +2 -2
  45. package/dist/tools/catalog/capabilities/records/gameplay/animation-physics/animation-properties.js +7 -5
  46. package/dist/tools/catalog/capabilities/records/gameplay/animation-physics/authoring-1.data.js +86 -1
  47. package/dist/tools/catalog/capabilities/records/gameplay/animation-physics/authoring-2.data.js +7 -2
  48. package/dist/tools/catalog/capabilities/records/gameplay/manage-effect/effect-properties.js +7 -6
  49. package/dist/tools/catalog/capabilities/records/gameplay/manage-effect/effect.data.js +38 -27
  50. package/dist/tools/catalog/capabilities/records/inspect/component-actor.data.js +1 -1
  51. package/dist/tools/catalog/capabilities/records/inspect/object-property.data.js +188 -10
  52. package/dist/tools/catalog/capabilities/records/inspect/properties.d.ts +1 -0
  53. package/dist/tools/catalog/capabilities/records/inspect/properties.js +2 -1
  54. package/dist/tools/catalog/capabilities/records/inspect/runtime.data.js +2 -1
  55. package/dist/tools/catalog/capabilities/records/inspect/stats.data.js +6 -2
  56. package/dist/tools/catalog/capabilities/records/manage-asset/asset-advanced.js +46 -0
  57. package/dist/tools/catalog/capabilities/records/manage-asset/asset-lifecycle.js +2 -2
  58. package/dist/tools/catalog/capabilities/records/manage-asset/asset-query.js +4 -3
  59. package/dist/tools/catalog/capabilities/records/manage-asset/builder.d.ts +3 -0
  60. package/dist/tools/catalog/capabilities/records/manage-asset/builder.js +3 -0
  61. package/dist/tools/catalog/capabilities/records/manage-asset/content-sources.js +3 -1
  62. package/dist/tools/catalog/capabilities/records/manage-asset/material-create.js +17 -2
  63. package/dist/tools/catalog/capabilities/records/manage-asset/material-graph.js +7 -5
  64. package/dist/tools/catalog/capabilities/records/manage-asset/material-params.js +5 -5
  65. package/dist/tools/catalog/capabilities/records/manage-audio/authoring.data.js +15 -5
  66. package/dist/tools/catalog/capabilities/records/manage-audio/runtime.data.js +1 -0
  67. package/dist/tools/catalog/capabilities/records/manage-blueprint/functions-events.js +3 -2
  68. package/dist/tools/catalog/capabilities/records/manage-blueprint/graph-batch.js +2 -2
  69. package/dist/tools/catalog/capabilities/records/manage-blueprint/graph-pins.js +6 -2
  70. package/dist/tools/catalog/capabilities/records/manage-blueprint/properties.js +4 -2
  71. package/dist/tools/catalog/capabilities/records/manage-blueprint/scs-components.js +7 -2
  72. package/dist/tools/catalog/capabilities/records/manage-blueprint/variables-metadata.js +8 -2
  73. package/dist/tools/catalog/capabilities/records/manage-blueprint/widget-animation.js +14 -4
  74. package/dist/tools/catalog/capabilities/records/manage-blueprint/widget-lifecycle.js +13 -5
  75. package/dist/tools/catalog/capabilities/records/manage-blueprint/widget-panels.js +1 -1
  76. package/dist/tools/catalog/capabilities/records/manage-sequence/cinematic.js +12 -3
  77. package/dist/tools/catalog/capabilities/records/manage-sequence/helpers.js +2 -2
  78. package/dist/tools/catalog/capabilities/records/manage-sequence/mrq.js +23 -4
  79. package/dist/tools/catalog/capabilities/records/manage-sequence/timeline-bindings.js +2 -2
  80. package/dist/tools/catalog/capabilities/records/manage-sequence/timeline-lifecycle.js +7 -2
  81. package/dist/tools/catalog/capabilities/records/manage-sequence/timeline-playback.js +9 -5
  82. package/dist/tools/catalog/capabilities/records/manage-sequence/timeline-state-ranges.js +19 -0
  83. package/dist/tools/catalog/capabilities/records/manage-sequence/timeline-tracks.js +10 -5
  84. package/dist/tools/catalog/capabilities/records/manage-tools/index.js +30 -2
  85. package/dist/tools/catalog/capabilities/records/system-control/console.js +3 -1
  86. package/dist/tools/catalog/capabilities/records/system-control/system-ops.js +122 -10
  87. package/dist/tools/catalog/capabilities/records/utility/output-glossary.js +11 -0
  88. package/dist/tools/catalog/capabilities/records/utility/utility-schema-pins.js +6 -3
  89. package/dist/tools/catalog/capabilities/records/world/manage-geometry.optimize.data.js +29 -0
  90. package/dist/tools/catalog/capabilities/records/world/manage-geometry.primitives.data.js +2 -1
  91. package/dist/tools/catalog/capabilities/records/world/properties.js +2 -2
  92. package/dist/tools/catalog/capabilities/semantic/envelope.d.ts +1 -1
  93. package/dist/tools/catalog/capabilities/semantic/errors.d.ts +1 -1
  94. package/dist/tools/catalog/unreal-gateway-definition.js +2 -2
  95. package/dist/utils/responses/gateway-reply-compaction.d.ts +6 -0
  96. package/dist/utils/responses/gateway-reply-compaction.js +264 -0
  97. package/dist/utils/responses/response-content.d.ts +0 -1
  98. package/dist/utils/responses/response-content.js +0 -172
  99. package/dist/utils/responses/response-validator.d.ts +1 -1
  100. package/dist/utils/responses/response-validator.js +39 -8
  101. package/package.json +2 -2
  102. package/server.json +2 -2
package/CHANGELOG.md CHANGED
@@ -13,6 +13,145 @@ _Nothing yet._
13
13
 
14
14
  ---
15
15
 
16
+ ## 🏷️ [0.6.0-beta-e] - 2026-10-09
17
+
18
+ > [!NOTE]
19
+ > **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.
20
+
21
+ <details>
22
+ <summary><b>✨ Added</b></summary>
23
+
24
+ - **Control Rig graphs**: `animation_physics` `edit_control_rig` adds, 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_rig` reads the graph and hierarchy; `list_rig_units` finds units by name or category.
25
+
26
+ </details>
27
+
28
+ <details>
29
+ <summary><b>🛡️ Security</b></summary>
30
+
31
+ - **The proxy's tool-list cache moved out of the shared temp dir** to the user's cache folder (`%LOCALAPPDATA%`, `$XDG_CACHE_HOME` or `~/.cache`, under `unreal-mcp`), written owner-only, so another account cannot plant the tool list and instructions it serves.
32
+ - **`package-plugin.mjs` refuses an argument holding `"`, `%`, `!` or a line break** before it reaches `cmd.exe`, and runs it with delayed expansion off.
33
+ - **source-map-js 1.2.2** (development only) clears GHSA-68fv-2mgg-jv7q.
34
+
35
+ </details>
36
+
37
+ <details>
38
+ <summary><b>📊 Change Statistics</b></summary>
39
+
40
+ | Metric | Count |
41
+ |--------|-------|
42
+ | Diff range | `v0.6.0-beta-d..v0.6.0-beta-e` |
43
+ | Commits | 4, the version bump and this release entry included |
44
+ | Files changed | 36 (27 hand-written, not counting generated files or line-ending-only changes) |
45
+ | Insertions / deletions | 1,868 / 95 (hand-written: 800 / 33) |
46
+ | Capability records | 405 |
47
+ | Callable `{tool, action}` pairs | 1,518 |
48
+ | C++ domain directories | 55 |
49
+
50
+ </details>
51
+
52
+ ---
53
+
54
+ ## 🏷️ [0.6.0-beta-d] - 2026-10-09
55
+
56
+ > [!NOTE]
57
+ > **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.
58
+
59
+ <details>
60
+ <summary><b>✨ Added</b></summary>
61
+
62
+ - **`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.
63
+ - **`inspect.capture_passes`**: aligned id (PNG with a legend), depth (EXR, cm) and normal (PNG) passes of the view, each with a summary.
64
+ - **`inspect.check_mesh`**: whether a static mesh is closed, with its holes, seams, inside-out and degenerate faces, parts, area and volume.
65
+ - **`inspect.raycast_world`**: up to 256 line traces against collision, each with its hit point, normal, distance, actor and component.
66
+ - **`manage_asset` `export_mesh`**: a static or skeletal mesh (or an animation) to glb, gltf, fbx or obj, without the exporters' dialogs.
67
+ - **`process_asset` `mesh_collision`**: box, sphere, capsule, complex or no collision on a static mesh asset and its placed copies.
68
+ - **`manage_geometry` `split_mesh`**: one static mesh per separate part or material slot, with `dryRun`.
69
+ - **Material Parameter Collections**: `create_material` `kind: parameter_collection` and the `CollectionParameter` node.
70
+ - **`system_control` `list_save_games` / `edit_save_game`**: read, edit, create and delete SaveGame slots.
71
+ - **`play_sound` `measure`**: plays a sound and answers how loud it was (`peakDb`, `averageDb`, `silent`, a wave's `wavePeakDb`).
72
+ - **`get_transform` `motion` `points`**: bone, socket or component positions per sample with ground heights and planted and slip stats; samples carry rotation.
73
+ - **`validate_assets` `dataValidation`** runs the project's and engine's validators; **`run_build` `tests`** answers each test's result.
74
+ - **`manage_tools` `get_task_result`**: reads a call that answered "still running"; the stdio server also answers so at 27 s.
75
+ - **`get_stats` `worldTickMs`**: the game world's own tick time while Play In Editor runs.
76
+ - **`add_function` overrides a parent function** such as `OnKeyDown`; **`add_variable` `exposeOnSpawn`**.
77
+ - **`set_property` `objectPaths`** writes one value on many objects, and `watch` samples the written property by default; **`call_actor_function` `componentName`** calls a component's function.
78
+ - **A Blueprint compile warns** about a sound played at a location with no attenuation.
79
+ - **`query_asset` `text`** finds graph nodes by their title.
80
+ - **Widgets**: `add_widget_tree` `material` paints an Image or Border; `add_animation_keyframe` `keys` writes a whole animation in one call.
81
+ - **Audio**: `create_metasound` `oneShot: false` makes a continuous source; distance attenuation sets air absorption (`lpf*`) and reads back what it holds.
82
+ - **Sequences**: `add_keyframe` `keys`, `set_section`, key `interpolation` and `lookAt`, `remove_keyframe` `frames`, particle keys (`particleKey`) and Niagara `moduleEnabled`.
83
+ - **Movie renders** capture gameplay (`gameModeOverride: level`, a `ui` pass, `audioOutput`), take `renderTimeoutMs`, and `create_render_job` `control: remove` clears jobs.
84
+ - **`advance_simulation`** `reset` previews an effect at an exact age, and the reply gives its `age` and `complete`.
85
+
86
+ </details>
87
+
88
+ <details>
89
+ <summary><b>🔄 Changed</b></summary>
90
+
91
+ - **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.
92
+ - **`describe` states where a call runs**: the calls that test a running game list `pie` and `simulate`; Niagara `activate`, `deactivate` and `reset` work in the level editor too.
93
+ - **Vector arrays coerce only when complete and numeric**: two numbers no longer become `{x, y}` with a default `z`; rotation arrays read `[pitch, yaw, roll]`.
94
+ - **A missing parameter names the keys sent in its place**, and a reply names what ran when a call used another name.
95
+
96
+ </details>
97
+
98
+ <details>
99
+ <summary><b>🛡️ Security</b></summary>
100
+
101
+ - **MCP SDK 1.32.1 and proxy-addr 2.0.8** clear GHSA-6qxp-vccf-f47h and GHSA-jqcg-44mw-7w3h.
102
+
103
+ </details>
104
+
105
+ <details>
106
+ <summary><b>🔧 Fixed</b></summary>
107
+
108
+ - **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.
109
+ - **Pins and nodes**: `connect_pins` grows Sequence, Make Array and Switch on Int to the named pin, matches names without spaces and warns on a second Target object; `create_node` makes FlipFlop, DoOnce, DoN, Gate, typed `GetAllActorsOfClass` and native Break/Make nodes.
110
+ - **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.
111
+ - **Properties**: writes go through component setters, fail when put back, reach subobject owners and say whether they saved; `markDirty: false` stays clean; paths reach components by name and any mount; bools answer without `b`; struct reads keep zero fields.
112
+ - **Actors in a running game**: `delete` and `delete_by_tag` remove them, `call_actor_function` reaches the GameInstance, role names work in every lookup, spawns keep their mesh, and `spawn_batch` variables land before BeginPlay.
113
+ - **Placement**: a moved actor is solid where it stands; checks skip triggers, bodiless parts and invisible volumes and treat water as a surface; `fix_coplanar` parts a flush row in one pass; collision changes hold on placed copies; floaters float.
114
+ - **Lists and reads**: `list` reads struct members and `near` skips 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.
115
+ - **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.
116
+ - **Input**: simulated keys reach a focused menu button and release on time while paused; widget input warns when a minimized editor holds widgets still.
117
+ - **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_parameter` says whether it saved.
118
+ - **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: false` stays off.
119
+ - **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; `measure` reads a wave's own level.
120
+ - **Sequences**: keys land as authored (sections span the range, auto tangents, Visibility tracks, transform defaults from the actor); `play` and `pause` seek with `startTime`; skeletal tracks bind the root mesh; spawnables make their own template; full-path create and duplicate save.
121
+ - **Renders and retargets**: a hung render frees the queue; `add_render_pass` names what it added; retargets keep pelvis motion and `create_ik_rig` builds from a mesh.
122
+ - **Captures**: screenshots after a camera move, full-window captures and captures right after an edit show the current state.
123
+ - **Editor**: console commands reach the running game; reflected calls run in the editor world; a restored window stays up; `step_frame` names its speed; paused motion runs end at once and `startWhen` reads component properties; `read_log` `livecoding` reads this editor.
124
+ - **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_all` names what it left.
125
+ - **Environment**: water bodies come out complete with varied waves; `create_sdf` names a too-thin shape; spline reads give both point spaces; `create_primitive` warns about a taken label.
126
+ - **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`.
127
+ - **Builds**: the plugin compiles again on UE 5.0-5.4, on Fab's MSVC and clang toolchains, and without the Geometry Script plugin.
128
+
129
+ </details>
130
+
131
+ <details>
132
+ <summary><b>👥 Contributors</b></summary>
133
+
134
+ - @SoloGorilla for stopping the gateway from making partial or non-numeric vectors out of arrays (#657).
135
+
136
+ </details>
137
+
138
+ <details>
139
+ <summary><b>📊 Change Statistics</b></summary>
140
+
141
+ | Metric | Count |
142
+ |--------|-------|
143
+ | Diff range | `v0.6.0-beta-c..v0.6.0-beta-d` |
144
+ | Commits | 171, the version bump and this release entry included |
145
+ | Files changed | 467 (447 hand-written, not counting generated files or line-ending-only changes) |
146
+ | Insertions / deletions | 19,964 / 4,034 (hand-written: 13,982 / 2,601) |
147
+ | Capability records | 402 |
148
+ | Callable `{tool, action}` pairs | 1,515 |
149
+ | C++ domain directories | 55 |
150
+
151
+ </details>
152
+
153
+ ---
154
+
16
155
  ## 🏷️ [0.6.0-beta-c] - 2026-10-02
17
156
 
18
157
  > [!NOTE]
@@ -36,14 +175,14 @@ _Nothing yet._
36
175
  - **`spawn` takes a mesh path alone.** The handler placed a mesh actor for a bare `meshPath`, but the schema refused the call without a class.
37
176
  - **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 `execute` carries `versionMismatch`: both versions, the release page of the matching plugin, and the `npx -y unreal-engine-mcp-server@<plugin version>` pin that matches the server to the plugin instead.
38
177
  - **`unreal-engine-mcp-server proxy` keeps a native session across editor restarts.** A stdio server in front of the plugin's `/mcp` (`UNREAL_MCP_URL`, default `http://127.0.0.1:3000/mcp`): while the editor is down every call answers `NOT_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.
39
- - **`control_actor.sample_motion` watches an actor over game time in PIE.** It returns location, velocity and `propertyNames` (`"Component.Property"` ok) every `intervalSeconds` for `durationSeconds` (max 30 s, 400 samples) with `start`, `end`, `min`, `max` and `endedBecause` (`duration`, `realTimeCap`, `sampleCap`, `actorDestroyed`, `worldEnded`, `startWhenTimeout`); the editor world gives `NOT_SIMULATING`. `inputs` (up to 32 `{key, atSeconds, holdSeconds}`) press keys at game-time offsets, `startWhen` (`{actorName, propertyName, equals, waitForChange, maxWaitSeconds}`) holds the run until another actor's property takes the `equals` value, by default only by changing into it, `maxRealSeconds` (default 25, max 50) caps wall time; a `startWhen` that never fires, keys that did not move the pawn, or a game stepping 0.1 s or more per frame warn. A minimized editor (which runs PIE at about 3 fps) is put back on screen without taking focus first (`windowRestored`) and minimized again when the run ends, and the background CPU throttle is off for the run only (in memory, put back however the run ends). Also `get_transform`'s `motion` read.
178
+ - **`control_actor.sample_motion` watches an actor over game time in PIE.** It returns location, velocity and `propertyNames` (`"Component.Property"` ok) every `intervalSeconds` for `durationSeconds` (max 30 s, 400 samples) with `start`, `end`, `min`, `max` and `endedBecause`; the editor world gives `NOT_SIMULATING`. `inputs` (up to 32 `{key, atSeconds, holdSeconds}`) press keys at game-time offsets, `startWhen` holds 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. Also `get_transform`'s `motion` read.
40
179
  - **`control_actor.list` finds actors by place and kind.** `near` (`[x, y, z]` or `{x, y, z}`) sorts nearest first, then smaller bounds, and adds each row's `distance` to the actor's bounds; `radius` keeps those within it. `tag`, `className` (class or any parent, by name or path, `_C` optional) and `folder` (that folder and below, `"(none)"` for the root) filter, and every filter combines with `summary` and with each other; `propertyNames` reads `"Component.Property"`, unmatched names under `missingProperties`.
41
180
  - **`set_transform` moves by an offset.** `offset` `[dx, dy, dz]`, also per item in `actors`, moves relative to the current location; with `location` it is refused with `INVALID_ARGUMENT`.
42
181
  - **`control_actor.rename` renames an actor.** It sets the label (`INVALID_NAME` if refused) and, with `renameObject`, the object name too (made valid and unique); the reply has `oldLabel`, `label`, `oldObjectName`, `objectName` and `actorPath`.
43
182
  - **`audit_placement` finds z-fighting and `fix_coplanar` fixes it.** `audit_placement` reports `coplanarFaces` per finding (kind `coplanar`, `byKind.coplanar`, read from each mesh's LOD0 triangles, also for actors tagged `mcp.placement.ok`) and takes `kinds` to limit problem kinds. `fix_coplanar` moves each face `distance` (0.1-20, default 1) in up to 4 passes as one undo step (`dryRun` is one pass); parts of one Blueprint are fixed in the Blueprint itself (compiled and saved, every placed copy fixed; `blueprintsFixed`), and `skipped` holds only the pairs left alone, with a reason.
44
183
  - **`componentNames` narrows a component listing** on `control_actor` `get_components`, `inspect` `get_components` and `inspect_cdo`: it keeps the named components (case-insensitive) and lists misses under `missingComponents`. A mesh component's row names its `staticMesh` and `materials` on a world actor too, not only in a Blueprint.
45
184
  - **Every spawn says where the actor ended up.** `spawn`, `spawn_blueprint` and each `spawn_batch` row report what `set_transform` reports: `placementWarning` (sunk into the surface under it, floating, intersecting other actors or nothing below), `groundZ`, `groundClearance`, `overlappingActors` and `suggestedLocation`, where a mesh whose pivot is its bounds centre spawned half under the floor behind a bare success (`spawn_blueprint` never checked, and `spawn_batch` dropped what each item's spawn found). A batch measures each item after its tags, so `mcp.placement.ok` silences a deliberate placement; `placementWarnings` counts the flagged items (a warning is not a failure) and `report: "failures"` keeps them. `suggestedLocation` is 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).
46
- - **Blueprint parts that sink into each other are named.** Every `edit_scs` edit 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 returns `partWarnings` with a `warnings` sentence each: `kind` `buried` (inside `otherComponent`, with `depth` in cm and `insideShare`) or `sunk` (below a Character's capsule bottom). A rider's legs 12 cm inside his mount answered a plain success, because both parts belong to one actor. `convert_to_static_mesh` and `convert_to_nanite` onto an existing path check the loaded Blueprints that draw the replaced mesh the same way (`partWarnings` with `blueprintPath`), since a reshaped body buries whatever sat on it. `audit_placement` with `blueprintPath` lists every part of a Blueprint the same way (`minSeverity` is the tolerance, default 0.5 cm; the level filters `kinds`, `nameFilter` and `maxTilt` are refused there with `INVALID_ARGUMENT`), and a component tagged `mcp.placement.ok` (`ComponentTags`) is a deliberate embed and is left out; `mcp.placement.ok:<component>` accepts the embed in that one part only (a neck in its collar, a hand round a handle) and keeps every other check.
185
+ - **Blueprint parts that sink into each other are named.** Every `edit_scs` edit 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 returns `partWarnings` with a `warnings` sentence each: `kind` `buried` (inside `otherComponent`, with `depth` in cm and `insideShare`) or `sunk` (below a Character's capsule bottom). `convert_to_static_mesh` and `convert_to_nanite` onto an existing path check the loaded Blueprints that draw the replaced mesh the same way, and `audit_placement` with `blueprintPath` lists every part of a Blueprint (`minSeverity` is the tolerance, default 0.5 cm; the level filters `kinds`, `nameFilter` and `maxTilt` are refused there with `INVALID_ARGUMENT`). A component tagged `mcp.placement.ok` is a deliberate embed and is left out; `mcp.placement.ok:<component>` accepts it against that one part only.
47
186
  - **`spawn_batch` names the actors it could not label.** `unnamedActors` lists the unique actor name of each item without `actorName`, in batch order (`""` for a failed one), under any report mode, and that item's `results[].name` is the unique name instead of the mesh label.
48
187
  - **The running game's objects have names.** During PIE, `GameInstance`, `GameMode`, `GameState`, `PlayerController`, `PlayerPawn`, `PlayerState` and `HUD` (any case) work as `objectPath` for `inspect` `get_property`/`set_property` and as `actorName` in every `control_actor` action that takes one (not `GameInstance`, which is no actor); a real actor of that name wins. A live widget goes by the name `simulate_input` `widget_list` reports (`WBP_HUD_C_0` or `WBP_HUD`), so its widgets read and write as property paths (`CoinBox.RenderTransform`).
49
188
  - **Class lookups take a Blueprint's short name.** `BP_Door` and `BP_Door_C` resolve to the Blueprint of that name (through the `/Game` asset registry when unloaded, also during play) for `find_by_class`, `spawn`, SCS, graph-node and widget creators and about 30 other actions.
@@ -75,7 +214,7 @@ _Nothing yet._
75
214
  - **`maintain_content` `refresh_blueprints` refreshes many Blueprints.** It refreshes every node of each Blueprint under `folderPath` or `assetPaths`, then compiles and saves each; the reply has `refreshedCount`, `savedCount` and `compileErrors` (`COMPILE_FAILED` on any).
76
215
  - **`query_asset` searches text.** `lookup: "text"` (`find_text`) finds a string in Blueprint pin literals and comments (with `nodeId`), variable and component defaults, widget texts, DataTable rows, String Table entries and, with `includeLevel` (default true), the open level's actors; `caseSensitive` matches case. A reference to another asset matches by its path, so searching a sound's name finds the component that plays it. `search` and `by_tag` say how many assets they found ("No assets matched." instead of "Assets found.").
77
216
  - **`inspect_asset` lists what uses an asset.** `lookup: "dependencies"` with `referencers: true` returns the using packages under `referencers`. The dependencies list is sorted, and an object path (`Pkg.Asset`) is reduced to its package for both directions.
78
- - **A screenshot can start from a camera position and skip the disk.** `control_editor` `screenshot` in `editor_viewport` mode takes `location` and `rotation` to move the viewport camera first (while PIE runs, the ejected view; `PIE_VIEW_NOT_EJECTED` until the player is ejected). `keepFile: false` returns the image without writing `Saved/Screenshots` (refused with `returnBase64: false`); `mode` is an enum (`editor_viewport`, `game_viewport`, `full_editor_window`) with a description each, and `window` takes the list index as a number too (it was string only, so `{"window": 1}` failed `INVALID_PARAMETER_TYPE`). A reply says how many shader jobs were still compiling (`shadersCompiling`, with a warning above 0: after `scalability 2` the trees came out black and the ground the default material, and nothing said why), `waitForShaders: true` waits for the queue first (at most 25 s, without blocking the game thread; `shaderWait` reports the wait and the jobs left), and the `inspect` editor-state reads (`get_project_settings`, `get_editor_settings`, `get_world_settings`, `get_viewport_info`, `get_selected_actors`) carry the same count.
217
+ - **A screenshot can start from a camera position and skip the disk.** `control_editor` `screenshot` in `editor_viewport` mode takes `location` and `rotation` to move the viewport camera first (while PIE runs, the ejected view; `PIE_VIEW_NOT_EJECTED` until the player is ejected), `keepFile: false` returns the image without writing `Saved/Screenshots`, and `window` takes the list index as a number. A reply counts the shader jobs still compiling (`shadersCompiling`, with a warning above 0), `waitForShaders: true` waits for them first (at most 25 s; `shaderWait`), and the `inspect` editor-state reads carry the same count.
79
218
  - **`configure_editor` `window` can minimize the editor.** `minimize: true` puts the main frame away without taking focus and turns the background CPU throttle back on (saved; `unthrottle` is ignored); the reply has `wasMinimized`, `minimized` (read back from the window), `restored` and `throttleOff`. A restore's `unthrottle` now lasts the editor session instead of being saved, so a later launch no longer runs flat out in the background. An editor launched with `-McpStartMinimized` puts itself away the same way as soon as its main window is on screen.
80
219
  - **`system_control` lists and deletes its output files.** `list_output_files` pages newest first (`root`, `extension`, `limit` default 100 max 500, `offset`) with `total`, `returned`, `hasMore` and `nextOffset`; `delete_output_file` takes `path` or `paths`, answers per-path `results` (`PARTIAL_DELETE`) and names every deleted path in the receipt. Both stay inside `Saved/Screenshots`, `Saved/unreal-mcp`, `tmp/unreal-mcp` and `temp/unreal-mcp`.
81
220
  - **`read_log` `filter` takes alternatives.** It splits on `|` and matches a line (message or category; for build, livecoding and previous sources also the file tail) containing any alternative, case-insensitively; plain text, not a regex. `source: "previous"` counts only the editor's own runs: the Fab browser's logs were counted too, so a `runsBack` could land on a browser log.
@@ -83,14 +222,14 @@ _Nothing yet._
83
222
  - **MetaSound graphs can be read and pruned (UE 5.5+).** `get_metasound_graph` returns nodes (`nodeId`, `name`, `className`, `kind`, inputs with literals, outputs), edges by pin name, `graphInputs` and `graphOutputs`. `edit_metasound` `remove_metasound_node` (`nodeId`/`nodeIds`, all-or-nothing; graph inputs and outputs refused) and `disconnect_metasound_nodes` (by target input, source output or exact pair) also run as `build_metasound` steps (`$id` ok in `nodeIds`).
84
223
  - **`manage_audio` `stop_sound` stops, pauses and resumes sounds.** `play_sound` spawns a tracked component that `stop_sound` stops (only `soundPath`'s sound when given); `all: true` stops every audio device of the editor and game. The reply has `stopped` and `allStopped`. `soundOp` `pause` or `resume` pauses or resumes the same sounds instead (`all: true` covers every playing sound, game music included; `paused`, `resumed`).
85
224
  - **Cutscenes can have music.** `add_track` with `trackType: "Audio"` and then `add_section` with `soundPath` puts a sound on the sequence, sized to the sound unless `end` is given; a missing sound is `ASSET_NOT_FOUND` and `soundPath` on another track `INVALID_ARGUMENT`.
86
- - **Fab imports run in the background and can be followed or cancelled.** `import_marketplace_asset` `fab_listing` replies when Fab accepts the download (`operationId`, format, quality tier, file, size) instead of waiting minutes for the import; `query_marketplace` `fab_import_status` reports `phase` (queued, resolving, downloading, importing, cancelling, done, failed), `downloadPercent` from Fab's own notification, then `importedRoot`, `sampleAssetPaths` (meshes first) and `saved`, or `failureCode` with the lines Fab logged; a failure Fab logs after some assets have landed lets the import settle, then reports `IMPORT_PARTIAL` naming it. One import runs at a time and later adds queue behind it (8 at most, then `QUEUE_FULL`); a repeat add of a listing still importing gets that import back, or `ADD_ALREADY_RUNNING` when it asks for a different `quality`, `combineMeshes`, `destinationPath` or `assetName`. `fab_cancel` drops a queued add, presses Cancel on a pack download or cancels an Interchange import; a source-format download has no cancel (`NOT_CANCELLABLE`, and `cancellable` says beforehand). The packages an import creates are saved once Interchange has finished with them and again 15 and 60 seconds later; `saved`, `savedCount` and `unsavedPackages` say how it went, and a package that could not be saved is named in capitals in the reply line and the `note`.
225
+ - **Fab imports run in the background and can be followed or cancelled.** `import_marketplace_asset` `fab_listing` replies when Fab accepts the download (`operationId`, format, quality tier, file, size) instead of waiting minutes for the import; `query_marketplace` `fab_import_status` reports `phase` (queued, resolving, downloading, importing, cancelling, done, failed), `downloadPercent` from Fab's own notification, then `importedRoot`, `sampleAssetPaths` (meshes first) and `saved`, or `failureCode` with the lines Fab logged; a failure Fab logs after some assets have landed lets the import settle, then reports `IMPORT_PARTIAL` naming it. One import runs at a time and later adds queue behind it (8 at most, then `QUEUE_FULL`); a repeat add of a listing still importing gets that import back, or `ADD_ALREADY_RUNNING` when it asks for a different `quality`, `combineMeshes`, `destinationPath` or `assetName`. `fab_cancel` drops a queued add, presses Cancel on a pack download or cancels an Interchange import (a source-format download is `NOT_CANCELLABLE`, which `cancellable` says beforehand). The packages an import creates are saved once Interchange is done with them and again 15 and 60 seconds later; `saved`, `savedCount` and `unsavedPackages` say how it went.
87
226
  - **The Fab add takes `combineMeshes`, `quality`, `destinationPath` and `assetName`.** `combineMeshes: false` imports each mesh of a file as its own asset, and a single mesh file of 50 MB or more is refused with `LARGE_SCENE_FILE` until it is chosen. `quality` (`raw`, `high`, `mid`, `low`) takes exactly that Megascans tier (`QUALITY_NOT_AVAILABLE` names the tiers offered). `destinationPath` and `assetName` move and name what the import created (`SM_<name>`, `MI_<name>`, `T_<name>_*`) through the rename `asset.move` uses, and never touch `/Game/Fab/Materials`, `MaterialFunctions` or `Textures`; a taken name stops it before anything moves. A complete project is refused (`COMPLETE_PROJECT`), as is a MetaHuman listing (`METAHUMAN_FORMAT`).
88
227
  - **`fab_listing_details` says what adding the listing would do.** `canAddToProject` is false, with `addBlockedCode` and `addBlockedReason`, for a complete project, a MetaHuman listing and a listing with no importable format. `addFormat`, `versionName`, `engineVersions`, `supportsRunningEngine`, `engineMatch`, `downloadFile`, `qualities`, `downloadBytes` (left out, with `downloadSizeKnown` false, when Fab publishes no size), `formats` and `addWarnings` describe the download; `category`, `averageRating`, `ratingCount`, `licenseNames`, `isCc0`, `price`, `currency`, `isFree` and `publishedAt` describe the listing. `attributionRequired` says a Creative Commons Attribution license needs a credit line, and `isCc0` (in search rows too) is read from the license names: Fab sets its own CC0 flag on CC-BY licenses, so a pack that needs credit read as needing none.
89
228
  - **`fab_search` rows carry the publisher, category, rating, price and formats,** and `seller` and `listingType` narrow the search.
90
229
  - **`fab_library` syncs an empty table itself** (`syncTriggered`, `syncWaitedSeconds`) instead of asking for a console command.
91
230
  - **`process_asset` sets the materials in a mesh asset's slots.** `process: "mesh_materials"` (`set_mesh_materials`) takes `assetPath` and `materials` (`[{slot, materialPath}]`, `slot` a 0-based index or a slot name) for a static or skeletal mesh, applies the valid entries in one rebuild and saves the mesh (`save` defaults to true; engine content is never saved, `saveSkippedReason` says so). The reply lists every slot with the material it holds and whether this call `changed` it, and each refused entry under `refused` (index out of range, unknown slot name, a material that does not load, never swapped for a default material); any refusal fails the call (`MATERIAL_SLOTS_PARTIAL`, or `MATERIAL_SLOTS_REFUSED` when none applied) while the valid entries stay applied.
92
231
  - **`inspect_object` with `objectKind: "mesh"` says where each material slot's geometry is.** Every `materialSlots` row carries `triangles` and `sections` (what LOD0 draws with the slot) and `bounds` (`origin`, `extent`, `min`, `max`, `size`, `radius`, in mesh space) for a static mesh, and for a skeletal mesh in its reference pose, so a slot can be matched to a part of the mesh in one call. When the render data keeps no CPU copy of the vertices, `slotBoundsAvailable` is false and `bounds` is left out. A Nanite mesh reports its fallback mesh.
93
- - **`create_primitive` `primitive: "sdf"` models smooth organic shapes in one call.** `shapes` (1-64 spheres, ellipsoids, boxes, capsules, cylinders, tori or cones, each with `center`, `rotation`, its sizes, an `operation` of union, subtract or intersect, and a `blend`: the radius of the soft fillet where it meets the shapes before it) become one signed distance field, meshed at `resolution` (16-256). Each shape's surface is its own polygroup (`groupId` = index + 1) and carries its `materialId`, listed under `parts`: a surface belongs to the shape whose field decides it there, and the mesh is cut along the middle of each fillet where that changes, so a carved visor, a painted band or a sole takes its own material slot with a clean, smooth edge. A subtract as the first shape is refused, shapes that leave no volume answer `SDF_EMPTY`, a mesh over 500,000 triangles answers `POLYGON_LIMIT_EXCEEDED` (lower the resolution), and shapes whose sizes, centres and blends span more than 100,000 units are refused (`INVALID_ARGUMENT`). A shape with `mirror` (`["y"]`, `["x","z"]` ...) also adds its reflections across the mesh's own planes, and one with `repeat` lays copies in a row (`count`, `offset`) or a ring (`count`, `axis`, `angle`, `pivot`), so a pair of eyes, a row of stitches or a ring of rivets is one entry (`parts` keeps one entry per shape, with `copies`; at most 1024 shapes in all). A shape farther from a point than its blend reaches is not evaluated there, so hundreds of small shapes mesh quickly.
232
+ - **`create_primitive` `primitive: "sdf"` models smooth organic shapes in one call.** `shapes` (1-64 spheres, ellipsoids, boxes, capsules, cylinders, tori or cones, each with `center`, `rotation`, its sizes, an `operation` of union, subtract or intersect, and a `blend`: the radius of the soft fillet where it meets the shapes before it) become one signed distance field, meshed at `resolution` (16-256). Each shape's surface is its own polygroup carrying its `materialId` (listed under `parts`), cut cleanly along each fillet where ownership changes, so a carved visor or a painted band takes its own material slot. `mirror` adds a shape's reflections and `repeat` lays copies in a row or a ring (at most 1024 shapes in all). A subtract as the first shape is refused, shapes that leave no volume answer `SDF_EMPTY`, a mesh over 500,000 triangles answers `POLYGON_LIMIT_EXCEEDED` (lower the resolution), and shapes spanning more than 100,000 units are refused (`INVALID_ARGUMENT`).
94
233
  - **`edit_dynamic_mesh` `append_polygons` builds a polygon cage in one call.** `vertices` (`{x, y, z}` points, at most 20000) and `faces` (three or more corner indices each, at most 20000; a larger or concave face is ear clipped) become a manifold surface, each face its own polygroup unless `faceGroups` says otherwise, with `faceMaterials` ids. A bad index, a repeated corner, an edge shared by three faces or two faces wound the same way along an edge is `INVALID_POLYGONS` naming the face, as are faces that come to more than 500,000 triangles (append them in several calls), and the mesh is left as it was. The reply has `verticesAdded`, `facesAdded`, `trianglesAdded`, `vertexCount`, `triangleCount` and `groupCount`.
95
234
  - **`subdivide` takes a `scheme`.** `catmull_clark`, `loop` and `bilinear` join `pn` (the default, as before); `iterations` is the level, 1-6. `catmull_clark` and `bilinear` read every polygroup as one face of a cage (an `append_polygons` cage, or `create_box`, which has one polygroup per face), keep polygroup and material ids through the subdivision, and refuse a mesh with no usable cage as `INVALID_CAGE` with how to build one; `loop` refines the triangles and needs no cage. The reply adds `scheme`, `level`, `trianglesBefore`, `trianglesAfter` and `cageFaces`. These three schemes need the MeshModelingToolset plugin that GeometryScripting enables (`SUBDIVISION_UNAVAILABLE` without it).
96
235
  - **The face operators take a `region`.** `extrude`, `inset`, `outset`, `offset_faces`, `bevel`, `chamfer` and `poke` accept `region` instead of `triangleIndices` (both is refused): a `box` the triangle centroids lie in, a `normal` with `normalAngle` (default 30), `groupIds` and `materialIds`, ANDed, in the mesh's local space. A region that matches nothing is `REGION_EMPTY` with the mesh's local bounds, and each reply says `trianglesSelected`.
@@ -106,7 +245,7 @@ _Nothing yet._
106
245
 
107
246
  - **HUD pieces from `add_game_widget` are real, styled widgets.** `health_bar`, `ammo_counter`, `crosshair`, `minimap`, `compass`, `damage_indicator`, `interaction_prompt`, `objective_tracker` and `quest_tracker` honour `percent`, colour, text, size, `texturePath`, `keyLabel`, `items`, `maxVisibleObjectives` and `positionX`/`positionY`/`sizeX`/`sizeY`, give an empty tree a `RootCanvas`, list what they created under `widgets`, and refuse a taken `slotName` (`SLOT_EXISTS`) or missing parent (`PARENT_NOT_FOUND`); the damage indicator adds a `<slot>_Flash` animation.
108
247
  - **`create_widget_template` builds ten screens as new Widget Blueprints** (`main_menu`, `pause_menu`, `settings_menu`, `loading_screen`, `hud`, `dialog`, `inventory`, `radial_menu`, `credits`, `shop`) named `name` in `path`; an existing asset gives `ALREADY_EXISTS`, a bad setting is refused before anything is created, and the reply lists every Button for `bind_widget` `on_clicked`.
109
- - **The stdio door runs capabilities exactly like the native door.** `execute` forwards `{action, ...params}` to the record's parent tool and the plugin routes it; the TypeScript action layer is gone and only `manage_tools` runs in process. Both accept only declared parameters, so a spelling only that layer converted (`path` for `blueprint.create`'s `savePath`) is refused with the declared name; declared aliases (`type` on `add_material_node`, `targetPath` on `import_level`/`duplicate_level`, `emitter` on Niagara module actions, `actorName` on `set_niagara_parameter`) work, and parameters that layer dropped now arrive (`set_transition_rules` `conditionVariable`/`conditionComparison`/`conditionValue`, `add_node` `memberName`). `system_control` `set_quality` and a `play_sound` without `soundPath` work on the native door. The plugin has one dispatch table: each parent tool routes its sub-actions explicitly (`system_control`'s widget, screenshot, project-settings, sound and display ones too), with no fallback that offered an unmatched action to every handler.
248
+ - **The stdio door runs capabilities exactly like the native door.** `execute` forwards `{action, ...params}` to the record's parent tool and the plugin routes it; the TypeScript action layer is gone and only `manage_tools` runs in process. Both accept only declared parameters and their declared aliases (a spelling only that layer converted, such as `path` for `blueprint.create`'s `savePath`, is refused with the declared name), and parameters that layer dropped now arrive. The plugin has one dispatch table: each parent tool routes its sub-actions explicitly, with no fallback that offered an unmatched action to every handler.
110
249
  - **Gateway refusals say what to do next.** `UNKNOWN_ACTION` for an action owned by one other tool names it with a `nextCall` to its describe (or, when no suggestion shares the verb, a search on the action's words); a conflicting folded selector answers `INVALID_PARAMETER_VALUE` naming both values, with an executable `nextCall`; an undeclared parameter never suggests `action` and says when a capability declares none; a parameter only another variant of a folded family reads is named in the receipt's `warnings` (`pinName is read only when info is pins; this info=node call did not use it.`). A cancelled stdio `execute` answers `MCP_REQUEST_CANCELLED`, not `TOOL_EXECUTION_FAILED` or `TOOL_TIMEOUT`.
111
250
  - **Capability guidance is complete.** Folded families keep every variant's `whenToUse` and `whenNotToUse` lines, not just the first six (labelled `control=play: ...` when only some variants hold them, bare when all do; search ignores the labels; `struct.edit_struct` lists 13 of each), and drop `whenNotToUse` lines that send a capability to itself. 54 more asset, material, inventory, texture, DataTable, enum, interaction and struct records carry authored lines instead of filler.
112
251
  - **Reader capabilities say what they return.** Summaries of `get_audio_info`, `get_texture_info`, `get_character_info`, `get_ai_info`, `get_level_structure_info`, `list_plugins`, `read_log` and other readers name their reply fields and topics ("sound length", "pixel format", "walk speed"); `get_mesh_info` has no material info, `analyze_trace` no timing counters, `get_stats` no draw calls.
@@ -117,7 +256,7 @@ _Nothing yet._
117
256
  - `control_editor.play` names the values of `control`; `close_asset` points to `restart_editor`; `set_widget_layout` `alignment` and `sizeRule` name box, overlay and scroll-box slots; `variableType` lists every `add_variable` type; `get_dependencies` returns direct packages only.
118
257
  - `manage_audio` and `manage_networking` guidance reads "Use it to ..." (104 lines said "Use when ...") and 32 empty "Do not use when ..." lines are gone; widget guidance reads as English.
119
258
  - The session instructions open with "The only tool is `unreal`; it reaches the whole editor" and quote no capability count.
120
- - **Search finds the capability a plain request names.** On both doors a record whose action names, family, domain or topics cover every word of the request ranks ahead of one that matches fewer; summary prose does not count, and function words such as "this" and "does" stay whole. A leading read word (get, list, show, what, which, where, ...) prefers readers (80 points on the stdio door, 40 on the native door), a leading delete (or remove, destroy, erase) prefers destructive ones, and on the native door a record whose own action words are all named gets 50 more, as does one with a topic that holds the whole request as written ("tag an asset" is `set_metadata`, "connect blueprint nodes" `edit_graph`). Folded families keep every member's topics, so "list sounds/materials/textures/meshes/blueprints" finds `query_asset`, "widget click" and "list live widgets" `simulate_input`, "copy button" `duplicate_widget`, "delete the quit button" `remove_widget`, "move the button" and "make the button bigger" `set_widget_layout`, "set light intensity" and "text render text" `edit_component`, "inspect material graph" `get_material_info`, "make the actor bigger" `set_transform`, "add point light" `create_light`, "add fog" and "add sky" `configure_atmosphere`, "press space" `simulate_input`, "make a cutscene" `sequence.create`, "set game mode" `configure_game_mode`. Nearly 300 more everyday requests across every domain ("add a checkbox", "make a folder", "slide in the menu", "stream in a sublevel", "remove a key binding", "mute all sounds") now rank their capability first on both doors.
259
+ - **Search finds the capability a plain request names.** On both doors a record whose action names, family, domain or topics cover every word of the request ranks ahead of one that matches fewer (summary prose does not count); a leading read word (get, list, show, what, which, where) prefers readers, a leading delete prefers destructive ones, a topic that holds the whole request wins ("tag an asset" is `set_metadata`), and folded families keep every member's topics. Nearly 300 everyday requests across every domain ("list sounds", "copy button", "add fog", "make a cutscene", "add a checkbox", "stream in a sublevel", "mute all sounds") now rank their capability first.
121
260
  - **Screenshots return the picture by default.** `control_editor` and `system_control` screenshots return the image inline (`returnBase64` true), fitted to 1600x900 without `resolution`; `returnBase64: false` keeps the full-size file only. A resampled `game_viewport` or `full_editor_window` image reports its size in `viewportWidth`/`viewportHeight`.
122
261
  - **More edits save by default.** `save` defaults to true (`save: false` keeps the change in memory) for `modify_scs` (which now declares `compile`, applies a `location`, `rotation`, `scale`, `meshPath` or `materialPath` given at the top level or on an operation (an `add_component` given only a mesh or material used to keep neither), and names one it cannot apply in `warnings`), Game Framework, DataTable and struct writes, `manage_asset` `import`, `set_two_sided`, material `delete_node`, Niagara graph edits, `create_metasound`, enum edits (`create_enum` included) and the `manage_inventory` edits; a `parameters` list on `set_material_parameter` or `create_material_instance` passes the call's `save` to every entry (each saved the asset whatever the call said). GAS ability and effect edits always compile and save (`COMPILE_FAILED`, `SAVE_FAILED`).
123
262
  - **Level and volume edits report whether the level is saved.** Streaming, World Partition, data layer, level blueprint and volume edits save only with `save: true` (a level save also writes its other unsaved changes), answering `saved: true` or `SAVE_FAILED` with the edit kept in memory; otherwise `saved: false` and the reply says the level is not saved yet. `configure_hlod_layer` saves its layer unless `save: false`.
@@ -183,7 +322,7 @@ _Nothing yet._
183
322
  - **A math expression that does not parse is refused.** `set_node_property` `Expression` on a Math Expression node answered success while an expression it cannot parse (`-1`: there is no unary minus) left the node with no pins but the orphaned old output, which still counted as one; it now fails `EXPRESSION_INVALID` and the node keeps its previous expression and its links.
184
323
  - **A palette's receipt lists the instances it made.** `create_material_instance` `instances` answered with an empty `changes`.
185
324
  - **A misspelled function gets near names.** `VInterpToConstant` was answered with a bare "not found"; the suggestion now ignores underscores (`VInterpTo_Constant`), and without a `memberClass` it also searches the stock libraries the lookup itself tries.
186
- - **A class path in the wrong folder names where the asset is.** `find` by class answers `CLASS_NOT_FOUND` with the `/Game` assets of that name, so `/Game/X/Gameplay/BP_Bug` points to `/Game/X/Enemies/BP_Bug`.
325
+ - **A class path in the wrong folder names where the asset is.** `find` by class answers `CLASS_NOT_FOUND` with the `/Game` assets of that name, so `/Game/X/Gameplay/BP_Enemy` points to `/Game/X/Enemies/BP_Enemy`.
187
326
  - **A function with two return nodes lists its outputs once.** `get_blueprint_details` listed every output once per return node.
188
327
  - **`connect_pins` says which link it replaced.** A pin that holds one link (an exec output, a data input) dropped its old link without a word; the reply (and a batch step) now lists it under `replacedLinks`.
189
328
  - **A class default write reaches the placed copies that kept it.** `set_property` on a Blueprint's class defaults or a component template also writes every copy placed in an editor level that still held the old default, as the details panel does (`instancesUpdated`); the compile had kept their old value as if they overrode it. A copy that overrides the value keeps its own.
@@ -239,7 +378,7 @@ _Nothing yet._
239
378
  - **`convert_to_nanite` makes Nanite meshes, and `nanite_rebuild_mesh` sticks.** From UE 5.1 `convert_to_nanite` baked plain static meshes while replying `naniteEnabled: true`; it now turns Nanite on and reads the flag back from the mesh (`NANITE_NOT_ENABLED` if it is still off). `nanite_rebuild_mesh` rebuilt the mesh on 5.7+ only, never saved it, echoed its request and reset the mesh's position precision and fallback settings; it now changes only Nanite and `trianglePercent`, rebuilds and saves on every version (`SAVE_FAILED` otherwise) and replies with the mesh's own `naniteEnabled` and `trianglePercent`, the same over both routes.
240
379
  - **Long calls say what Unreal is doing instead of failing.** A call still open after 27 s answers with `task.state` `running` while the work goes on, where it used to hit the client's time limit in silence. Through the stdio server only a call with an `idempotencyKey` and no `timeoutMs` answers that way, since resent with the same key once the work is done it answers with the real result; any other call waits for its result. On the editor's own MCP server the answer also names what the editor is working on and how far it has got (`queued` if it has not started, with `progress`); until then it hears every 8 s what the editor is doing, and thumbnail and LOD progress now reach it too. `EDITOR_BLOCKED` names the work holding the editor, its last progress and the shaders still compiling. `asset.delete` on a folder reports as it goes and removes unloaded assets that nothing outside the delete references straight from disk instead of loading them first (a 9,000-asset folder held the editor for over 15 minutes without a word).
241
380
  - **Object and class references can be cleared, and a wrong one is refused.** Wherever a property value is written (`edit_scs` `properties`, `set_scs_property`, `set_property`, `set_component_property`, Blueprint `create` and the rest), `null`, `""` or `"None"` clear an object, class or soft reference (`null` and `"None"` were refused, so a child actor's class could not be emptied), and a path to an object of the wrong class is refused with the class the property holds, where it used to be stored as-is.
242
- - **Actor calls tell the truth.** A `set_transform` batch re-checks every item against the finished layout; the placement check no longer takes something an actor holds up for the floor under it (shelf legs poking into their deck read as sunk by their full height, with a suggested height on top of the deck), and checks a box overlap against the collision shapes before reporting it (a blimp beside a mountain peak "intersected" the cone's mostly empty box), and no longer calls an actor held from the side floating (20 window bands flush on a hall and 96 awnings on a facade read "floating 139 / 521 units": only support from below was looked for; an actor whose bounds touch or overlap another actor's vertical face now reports `mountedOn` instead, in `set_transform`, `spawn` and `audit_placement` alike); `audit_placement` rows list every actor they intersect (`overlappingActors`), where only the deepest was named, and its `nameFilter` (and `fix_coplanar`'s) matches the object name it reports for actors sharing a label; `find_by_tag` walks the running game during PIE; an incomplete `delete` answers `DELETE_PARTIAL` (or `NOT_FOUND`) with `deleted`, `missing` and `undo`; `delete`/`delete_by_tag` are one undo step, and so are `spawn`, `spawn_blueprint` and `spawn_batch` ("Spawn Actors": one step for every actor the call made, `undo` in the reply; `control_editor.undo` answered `NOTHING_TO_UNDO` after a spawn) and `set_material` (one actor, or an `actorNames` list as one step, `undo` in the reply; it had none); `set_visibility` and `set_actor_collision` take `actorNames` as `add_tag` does (hiding 17 actors was 34 calls; one call and one undo step, `undo` in the reply, on a Blueprint actor too, where a billboard made without `RF_Transactional` made `set_visibility` answer `undoable: false` and `set_actor_collision` had no undo at all; names not found come back under `missing` (`ACTOR_NOT_FOUND` when none is) and the actors changed under `affectedActors`, so the receipt lists each as a change and gives it an actor handle (the first 20), as it does for `add_tag` and `set_material` with `actorNames` and for the `spawn_batch`, `set_transform` and `set_blueprint_variables` batches, whose receipts were empty; a single `set_blueprint_variables` names the instance it changed); `call_actor_function` runs Blueprint custom events on editor actors; `set_blueprint_variables` whose every name misses answers `PROPERTY_NOT_FOUND` listing the actor's Blueprint variables and changes nothing (it answered "Variables updated"); `find_by_name` with no match offers `similar` labels ("Bug1" finds Bug_01), and any `ACTOR_NOT_FOUND` hands back that find as its `nextCall`; replies name clashing labels by object name.
381
+ - **Actor calls tell the truth.** The placement check re-checks a `set_transform` batch against the finished layout, no longer takes what an actor holds up for its floor, confirms a box overlap on the collision shapes, and reports an actor held from the side as `mountedOn` instead of floating (`set_transform`, `spawn`, `audit_placement`); `audit_placement` rows list every actor they intersect (`overlappingActors`), and its `nameFilter` (and `fix_coplanar`'s) matches the object name it reports. `delete`, `delete_by_tag`, `spawn`, `spawn_blueprint`, `spawn_batch`, `set_material`, `set_visibility` and `set_actor_collision` are one undo step each with `undo` in the reply, and an incomplete `delete` answers `DELETE_PARTIAL` (or `NOT_FOUND`) with `deleted` and `missing`. `set_visibility` and `set_actor_collision` take `actorNames` as `add_tag` does, with misses under `missing` (`ACTOR_NOT_FOUND` when none matched) and changed actors under `affectedActors`, which the receipt lists as changes with actor handles, as it now does for the batch calls. `find_by_tag` walks the running game during PIE, `call_actor_function` runs Blueprint custom events on editor actors, a `set_blueprint_variables` whose every name misses answers `PROPERTY_NOT_FOUND` listing the actor's variables, `find_by_name` offers `similar` labels, any `ACTOR_NOT_FOUND` hands back that find as its `nextCall`, and replies name clashing labels by object name.
243
382
  - **`control_editor.undo` and `redo` work.** They undo or redo the last transaction ("Undid: <title>") and answer `NOTHING_TO_UNDO`, `NOTHING_TO_REDO`, `UNDO_FAILED` or `REDO_FAILED`.
244
383
  - **Fab opens its own tab.** Fab calls answered `FAB_NOT_READY` until someone opened Window > Fab: the auto-open never ran the menu item's action. It does now.
245
384
  - **Saves and deletes never open a dialog.** Asset and level saves run unattended, and `bulk_delete` never shows the delete confirmation, so no prompt blocks the editor.
package/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
  </p>
21
21
 
22
22
  <p align="center">
23
- <sub>🧭 One tool, nearly 400 capabilities &nbsp;·&nbsp; ⚙️ Native C++ editor plugin &nbsp;·&nbsp; 🌐 HTTP or stdio &nbsp;·&nbsp; 🔐 Local and token-protected by default &nbsp;·&nbsp; 🎮 Unreal Engine 5.0 – 5.8</sub>
23
+ <sub>🧭 One tool, over 400 capabilities &nbsp;·&nbsp; ⚙️ Native C++ editor plugin &nbsp;·&nbsp; 🌐 HTTP or stdio &nbsp;·&nbsp; 🔐 Local and token-protected by default &nbsp;·&nbsp; 🎮 Unreal Engine 5.0 – 5.8</sub>
24
24
  </p>
25
25
 
26
26
  <p align="center">
@@ -134,7 +134,7 @@ Build the plugin once on a machine with the engine and a compiler, then hand out
134
134
  node scripts/package-plugin.mjs "C:/Program Files/Epic Games/UE_5.7"
135
135
  ```
136
136
 
137
- This writes `build/McpAutomationBridge-v<version>-UE5.7-<Platform>.zip`, where `<version>` is the `package.json` version (currently `0.6.0-beta-c`). Unzip it into `YourProject/Plugins/`. Binaries only work with the engine minor and platform they were built for: a 5.6 build won't load in 5.5, 5.7 or 5.8.
137
+ This writes `build/McpAutomationBridge-v<version>-UE5.7-<Platform>.zip`, where `<version>` is the `package.json` version (currently `0.6.0-beta-e`). Unzip it into `YourProject/Plugins/`. Binaries only work with the engine minor and platform they were built for: a 5.6 build won't load in 5.5, 5.7 or 5.8.
138
138
 
139
139
  </details>
140
140