Commit f9bc023
committed
Niagara: full stack-input authoring + graph introspection loop
Brings the Niagara MCP surface to parity with what the editor UI actually
lets you do. You can now read, mutate, and replicate any module input
binding at any nesting depth without guessing engine API or hardcoded
asset paths — and the same 96 commands work from Python MCP, Go CLI, or
direct C++ dispatcher.
Graph introspection (new NiagaraGraphIntrospection.cpp)
- get_niagara_graph_nodes: list every node with verbosity control
(summary / connections / full) + type_filter + name_filter. Three
resolver modes: scratch pad (system+module), emitter stack graph
(system+emitter+script_usage), or standalone script asset.
- get_niagara_node_info: deep single-node inspect by index/class/GUID
with pin layout, connections, and node-type-specific fields
(op_name, function_script, hlsl_preview, input_name/type).
- trace_niagara_connection: BFS upstream/downstream with pin_name filter.
- validate_niagara_graph: orphan/dead-end/missing-input classifier,
skips +Add placeholder pins so no false positives.
Scratch pad apply + script properties (new NiagaraScratchPadApply.cpp)
- apply_niagara_scratch_pad / apply_and_save_niagara_scratch_pad wrap
FNiagaraScratchPadScriptViewModel::ApplyChanges[AndSave] — the actual
Apply / Apply & Save buttons.
- get/set_niagara_script_properties covers every
FVersionedNiagaraScriptData field including TArray<FName>
(ProvidedDependencies) and TArray<FNiagaraModuleDependency>
(RequiredDependencies). Explicit per-FProperty-type reader avoids
an FText reflection crash the generic walker used to hit.
Script parameters + node creation (new NiagaraScriptParams.cpp)
- list/add/remove/rename_niagara_script_parameter with automatic
cascade to Map Get / Map Set pins on remove. Output-param adds
dispatch PostEditChangeProperty on the Output node so the canvas
refreshes immediately instead of needing a name-field tickle.
- add_niagara_graph_node supports Op, FunctionCall, DataInterfaceFunction,
ParameterMapGet, ParameterMapSet, Reroute, Input. DI member functions
(array.Length etc) use UNiagaraDataInterface::GetFunctionSignatures
and set UNiagaraNodeFunctionCall::Signature directly — FunctionScript
stays null, same as the editor's right-click "Functions" submenu.
- delete_niagara_graph_node by index or GUID, mirrors on asset + edit-copy.
Stack input binding loop (new NiagaraStackBinding.cpp)
- get_niagara_module_input_binding resolves Default / Local / Linked /
Dynamic / Data / Expression mode for every input and recurses into
dynamic-input children. One call returns the full tree — no separate
walk of override pins.
- clear_niagara_module_input resets any input to default, top-level or
nested via dot-path (e.g. "Spawn Count.Position Array"). Replicates
FNiagaraStackGraphUtilities::RemoveNodesForStackFunctionInputOverridePin
(non-exported) using exported primitives.
- list_niagara_input_source_menu reproduces the stack-UI source dropdown —
all DynamicInput-usage scripts from AssetRegistry plus scratch-pad DIs
on the same system (tagged source: "scratch_pad"), plus link parameters
from Engine / Particles / User namespaces via FNiagaraConstants.
Stack discovery + reverse lookup (new NiagaraStackDiscovery.cpp)
- find_niagara_scratch_pad_usage scans every system + emitter stack graph
for FunctionCall nodes referencing a scratch pad, so you can answer
"what uses this DI?" in one call.
- resolve_niagara_built_in_dynamic_input replaces hardcoded engine paths
(/Niagara/Modules/DynamicInputs/UniformRangedFloat — which moves
between UE versions) with live AssetRegistry scan.
- list_niagara_data_interface_functions enumerates DI member functions
via UNiagaraDataInterface::GetFunctionSignatures so the AI can pick a
real function_name before spawning a DataInterfaceFunction node.
Nested path resolver (new NiagaraStackPathResolver.h)
- Shared DescendNestedPath helper walks a dot-path like
"Spawn Count.Position Array" through dynamic-input function-call chains.
- Wired into set_niagara_dynamic_input, link_niagara_parameter, and
set_niagara_module_input so every setter now accepts arbitrary nesting.
Nested literal setter
- set_niagara_module_input on a dot-path routes to
GetOrCreateStackFunctionInputOverridePin + DefaultValue write, the
actual path the editor uses for local values. Top-level inputs whose
source is parameter_map_input auto-delegate to the rapid-iteration
setter so you don't get "input not found" errors for Module.* aliased
inputs like SpawnPerFrame's Spawn Probability.
Dynamic input template resolution
- set_niagara_dynamic_input for random_range / uniform_random types now
falls back to FNiagaraEditorUtilities::GetFilteredScriptAssets filtered
on Usage=DynamicInput + name substring if the canonical engine path
doesn't resolve. Handles V2 asset-moves across UE versions.
Emitter stack graph introspection
- get_niagara_graph_nodes accepts emitter_name + script_usage so you can
read EmitterUpdateScript / ParticleSpawnScript graphs directly — the
actual graphs where stack modules appear as UNiagaraNodeFunctionCall
nodes with visible override pins.
Renderer binding reader
- get_niagara_renderer_info now returns each binding with binding_name
(the UPROPERTY name that set_niagara_renderer_binding accepts) +
bound_variable + bound_variable_type + dataset_variable. Uses
reflection to map binding pointers to their UPROPERTY names.
Describe-type fallback
- describe_niagara_type falls back to UEnum / UScriptStruct reflection
when the name isn't in FNiagaraTypeRegistry, so script-property enums
like ENiagaraScriptLibraryVisibility and custom project enums resolve
cleanly.
FGraphNodeCreator contract fix
- Op / FunctionCall / ParameterMapGet / ParameterMapSet / Reroute / Input
node creation now calls Creator.Finalize() before the creator goes out
of scope. Previous templated helper returned early and tripped the
bPlaced assert (EdGraph.h:312).
Bridge dispatcher prefix routing
- Added trace_niagara, validate_niagara, apply_niagara,
apply_and_save_niagara, clear_niagara, find_niagara, resolve_niagara
prefixes so the new command names reach the Niagara handler rather
than falling through to the generic "Unknown command" error.
Python MCP wrappers
- New @mcp.tool() entries in unrealmcp/tools/niagara.py for all new
commands with full docstrings, keyword arg support, and optional
param handling. Nothing to regenerate — drop-in.
Go CLI parity
- cli/cmd/niagara.go now ships 96 Niagara CommandSpecs (was 54).
Every C++ command has a matching Go entry with Short/Long docs,
ue-cli ... --flag examples, typed params, and Required flags where
the handler requires them. ue-cli.exe rebuilt.
Bonus: get_available_materials
- Added filter + max_results params so material listings can be
scoped without returning engine-wide dumps.
Works on a real asset — verified end-to-end on NS_MuzzleFlash:
read Spawn Count's GetDataInterfaceLength binding recursively, clear
the nested Position Array link, re-link it through User.FlashPositions,
build a 1:1 replica DI from scratch with a real array-Length DI
function node, swap it onto SpawnPerFrame, set the nested int32001
local value to 250, and verified the full tree in a single binding
query. No hand-editing in the editor.1 parent 727615c commit f9bc023
18 files changed
Lines changed: 5850 additions & 178 deletions
File tree
- Source/UnrealMCPBridge
- Private
- Commands
- Niagara
- Public/Commands
- cli/cmd
- unrealmcp/tools
Lines changed: 23 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
789 | 789 | | |
790 | 790 | | |
791 | 791 | | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
792 | 805 | | |
793 | 806 | | |
794 | 807 | | |
| |||
866 | 879 | | |
867 | 880 | | |
868 | 881 | | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
869 | 892 | | |
870 | 893 | | |
871 | 894 | | |
| |||
Lines changed: 82 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
229 | 229 | | |
230 | 230 | | |
231 | 231 | | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
232 | 314 | | |
233 | 315 | | |
234 | 316 | | |
| |||
Lines changed: 152 additions & 53 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
311 | 312 | | |
312 | 313 | | |
313 | 314 | | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
314 | 320 | | |
315 | 321 | | |
316 | 322 | | |
317 | | - | |
| 323 | + | |
318 | 324 | | |
319 | 325 | | |
320 | | - | |
321 | | - | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
322 | 333 | | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
327 | 340 | | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
356 | | - | |
357 | | - | |
358 | | - | |
359 | | - | |
360 | | - | |
361 | | - | |
362 | | - | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
363 | 390 | | |
364 | 391 | | |
365 | 392 | | |
366 | | - | |
367 | | - | |
368 | | - | |
| 393 | + | |
| 394 | + | |
369 | 395 | | |
370 | | - | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
371 | 409 | | |
372 | | - | |
373 | | - | |
374 | | - | |
| 410 | + | |
| 411 | + | |
375 | 412 | | |
376 | 413 | | |
377 | 414 | | |
378 | 415 | | |
379 | 416 | | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
380 | 423 | | |
381 | | - | |
382 | | - | |
383 | | - | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
384 | 476 | | |
385 | 477 | | |
386 | 478 | | |
387 | 479 | | |
388 | 480 | | |
389 | | - | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
390 | 487 | | |
391 | 488 | | |
| 489 | + | |
| 490 | + | |
392 | 491 | | |
393 | 492 | | |
394 | 493 | | |
| |||
0 commit comments