ue-mcp 1.1.28 → 1.1.30

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # UE-MCP
2
2
 
3
- **Unreal Engine Model Context Protocol Server** - gives AI assistants deep read/write access to the Unreal Editor through <!-- count:tools -->24<!-- /count --> category tools covering <!-- count:actions -->736+<!-- /count --> actions, plus a YAML flow engine for multi-step workflows.
3
+ **Unreal Engine Model Context Protocol Server** - gives AI assistants deep read/write access to the Unreal Editor through <!-- count:tools -->24<!-- /count --> category tools covering <!-- count:actions -->738+<!-- /count --> actions, plus a YAML flow engine for multi-step workflows.
4
4
 
5
5
  ```mermaid
6
6
  flowchart LR
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "tools": 24,
3
- "actions": 736,
4
- "bridgeActions": 702,
3
+ "actions": 738,
4
+ "bridgeActions": 704,
5
5
  "localActions": 34,
6
6
  "perTool": {
7
7
  "project": 32,
@@ -13,7 +13,7 @@
13
13
  "landscape": 12,
14
14
  "pcg": 19,
15
15
  "foliage": 5,
16
- "niagara": 28,
16
+ "niagara": 30,
17
17
  "audio": 36,
18
18
  "widget": 27,
19
19
  "editor": 70,
@@ -31,6 +31,6 @@
31
31
  },
32
32
  "nativeToolsets": 52,
33
33
  "nativeToolActions": 830,
34
- "generatedAt": "2026-07-23T19:18:54.731Z",
35
- "version": "1.1.28"
34
+ "generatedAt": "2026-07-23T21:16:37.352Z",
35
+ "version": "1.1.30"
36
36
  }
@@ -11,6 +11,7 @@ export const niagaraTool = categoryTool("niagara", "Niagara VFX: systems, emitte
11
11
  create: bp("Create system. Params: name, packagePath?", "create_niagara_system"),
12
12
  create_emitter: bp("Create Niagara emitter. Params: name, packagePath?, templatePath?", "create_niagara_emitter"),
13
13
  add_emitter: bp("Add emitter to system. Params: systemPath, emitterPath", "add_emitter_to_system"),
14
+ remove_emitter: bp("Remove an emitter from a system (CRUD delete). Params: systemPath, emitterName? or emitterIndex?", "remove_emitter_from_system", (p) => ({ systemPath: p.systemPath, emitterName: p.emitterName, emitterIndex: p.emitterIndex })),
14
15
  list_emitters: bp("List emitters in system. Params: systemPath", "list_emitters_in_system"),
15
16
  set_emitter_property: bp("Set emitter property. Params: systemPath, emitterName?, propertyName, value", "set_emitter_property"),
16
17
  list_modules: bp("List Niagara modules. Params: directory?", "list_niagara_modules"),
@@ -25,6 +26,7 @@ export const niagaraTool = categoryTool("niagara", "Niagara VFX: systems, emitte
25
26
  list_system_parameters: bp("List user-exposed system parameters. Params: systemPath", "list_niagara_system_parameters"),
26
27
  list_module_inputs: bp("List modules + their input pins for an emitter. Params: systemPath, emitterName?, emitterIndex?, stackContext? (ParticleSpawn|ParticleUpdate|EmitterSpawn|EmitterUpdate|all — default all)", "list_niagara_module_inputs"),
27
28
  set_module_input: bp("Set literal default on a module input pin. Params: systemPath, moduleName, inputName, value, emitterName?, emitterIndex?, stackContext?", "set_niagara_module_input"),
29
+ add_module: bp("Add a stock /Niagara/Modules script to an emitter stack (the modules that make an emitter actually do anything). Params: systemPath, moduleScript (e.g. /Niagara/Modules/Emitter/SpawnRate), stackContext (ParticleSpawn|ParticleUpdate|EmitterSpawn|EmitterUpdate), emitterName?, emitterIndex?, targetIndex? (-1 appends). Then set_module_input to tune it.", "add_niagara_module", (p) => ({ systemPath: p.systemPath, moduleScript: p.moduleScript, stackContext: p.stackContext, emitterName: p.emitterName, emitterIndex: p.emitterIndex, targetIndex: p.targetIndex })),
28
30
  list_static_switches: bp("List static switch inputs on a module. Params: systemPath, moduleName, emitterName?, emitterIndex?, stackContext?", "list_niagara_static_switches"),
29
31
  set_static_switch: bp("Set static switch value on a module's function call node. Params: systemPath, moduleName, switchName, value, emitterName?, emitterIndex?, stackContext?", "set_niagara_static_switch"),
30
32
  create_module_from_hlsl: bp("Create a NiagaraScript module backed by a custom HLSL node. Params: name, hlsl, packagePath?, inputs?:[{name,type}], outputs?:[{name,type}]", "create_niagara_module_from_hlsl"),
@@ -88,6 +90,8 @@ export const niagaraTool = categoryTool("niagara", "Niagara VFX: systems, emitte
88
90
  emitters: z.array(z.record(z.unknown())).optional().describe("Spec: [{path:'/Game/VFX/E_Fire'}]"),
89
91
  onConflict: z.string().optional().describe("skip|error when asset exists"),
90
92
  moduleName: z.string().optional().describe("For module input / static switch ops: name of the module function call node"),
93
+ moduleScript: z.string().optional().describe("For add_module: stock module script path, e.g. /Niagara/Modules/Emitter/SpawnRate"),
94
+ targetIndex: z.number().optional().describe("For add_module: stack insert position; -1 (default) appends"),
91
95
  inputName: z.string().optional().describe("For set_module_input: module input pin name"),
92
96
  switchName: z.string().optional().describe("For set_static_switch: static switch input name"),
93
97
  stackContext: z.string().optional().describe("ParticleSpawn|ParticleUpdate|EmitterSpawn|EmitterUpdate|all (default all)"),
@@ -1 +1 @@
1
- {"version":3,"file":"niagara.js","sourceRoot":"","sources":["../../src/tools/niagara.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,EAAE,EAAiC,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,CAAC,MAAM,WAAW,GAAY,YAAY,CAC9C,SAAS,EACT,4EAA4E,EAC5E;IACE,IAAI,EAAY,EAAE,CAAC,qDAAqD,EAAE,sBAAsB,CAAC;IACjG,QAAQ,EAAQ,EAAE,CAAC,mCAAmC,EAAE,kBAAkB,CAAC;IAC3E,KAAK,EAAW,EAAE,CAAC,6JAA6J,EAAE,2BAA2B,CAAC;IAC9M,WAAW,EAAK,EAAE,CAAC,+OAA+O,EAAE,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnZ,UAAU,EAAM,EAAE,CAAC,wHAAwH,EAAE,oBAAoB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IACzM,aAAa,EAAG,EAAE,CAAC,yEAAyE,EAAE,uBAAuB,CAAC;IACtH,MAAM,EAAU,EAAE,CAAC,2CAA2C,EAAE,uBAAuB,CAAC;IACxF,cAAc,EAAE,EAAE,CAAC,mEAAmE,EAAE,wBAAwB,CAAC;IACjH,WAAW,EAAK,EAAE,CAAC,wDAAwD,EAAE,uBAAuB,CAAC;IACrG,aAAa,EAAG,EAAE,CAAC,6CAA6C,EAAE,yBAAyB,CAAC;IAC5F,oBAAoB,EAAE,EAAE,CAAC,6EAA6E,EAAE,sBAAsB,CAAC;IAC/H,YAAY,EAAI,EAAE,CAAC,0CAA0C,EAAE,sBAAsB,CAAC;IACtF,gBAAgB,EAAE,EAAE,CAAC,oCAAoC,EAAE,kBAAkB,CAAC;IAC9E,cAAc,EAAI,EAAE,CAAC,+EAA+E,EAAE,wBAAwB,CAAC;IAC/H,YAAY,EAAM,EAAE,CAAC,gHAAgH,EAAE,sBAAsB,CAAC;IAC9J,eAAe,EAAG,EAAE,CAAC,0FAA0F,EAAE,yBAAyB,CAAC;IAC3I,qBAAqB,EAAE,EAAE,CAAC,+HAA+H,EAAE,uBAAuB,CAAC;IACnL,uBAAuB,EAAE,EAAE,CAAC,qDAAqD,EAAE,wBAAwB,CAAC;IAC5G,uBAAuB,EAAE,EAAE,CAAC,0FAA0F,EAAE,iCAAiC,CAAC;IAC1J,iBAAiB,EAAE,EAAE,CAAC,8FAA8F,EAAE,2BAA2B,CAAC;IAClJ,sBAAsB,EAAE,EAAE,CAAC,yDAAyD,EAAE,gCAAgC,CAAC;IACvH,kBAAkB,EAAG,EAAE,CAAC,4LAA4L,EAAE,4BAA4B,CAAC;IACnP,gBAAgB,EAAK,EAAE,CAAC,yIAAyI,EAAE,0BAA0B,CAAC;IAC9L,oBAAoB,EAAE,EAAE,CAAC,mHAAmH,EAAE,8BAA8B,CAAC;IAC7K,iBAAiB,EAAI,EAAE,CAAC,yJAAyJ,EAAE,2BAA2B,CAAC;IAC/M,uBAAuB,EAAE,EAAE,CAAC,6IAA6I,EAAE,iCAAiC,CAAC;IAC7M,qBAAqB,EAAG,EAAE,CAAC,uHAAuH,EAAE,uBAAuB,CAAC;IAC5K,KAAK,EAAE;QACL,WAAW,EAAE,gOAAgO;QAC7O,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE;YAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC9F,MAAM,OAAO,GAAgE,EAAE,CAAC;YAChF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAsE,CAAC;gBAC9F,MAAM,MAAM,GAAG,EAAE,EAAE,MAAM,CAAC;gBAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;oBAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;gBAAC,CAAC;gBAC9H,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACzC,IAAI,CAAC,IAAI,EAAE,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,2BAA2B,MAAM,GAAG,EAAE,CAAC,CAAC;oBAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;gBAAC,CAAC;gBACvH,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;oBAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;gBAAC,CAAC;gBAC1H,IAAI,CAAC;oBACH,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,EAA6B,CAAC;oBAC9E,MAAM,MAAM,GAAG,MAAO,IAAmB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,SAAS,CAAC;2BAC9D,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;oBACjM,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;oBACtD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;gBACnC,CAAC;YACH,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACtC,CAAC;KACF;CACF,EACD,SAAS,EACT;IACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC;IAC5G,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;IAC5B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;IACrF,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACjG,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;IAC1E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;IACzH,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IACxF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IAC7F,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2EAA2E,CAAC;IACzH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IAC9E,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IACzG,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IAC1G,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;CACzF,CACF,CAAC"}
1
+ {"version":3,"file":"niagara.js","sourceRoot":"","sources":["../../src/tools/niagara.ts"],"names":[],"mappings":"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"}
@@ -2549,6 +2549,12 @@ tasks:
2549
2549
  description: "Add emitter to system. Params: systemPath, emitterPath"
2550
2550
  options:
2551
2551
  method: add_emitter_to_system
2552
+ niagara.remove_emitter:
2553
+ class_path: ue-mcp.bridge
2554
+ group: niagara
2555
+ description: "Remove an emitter from a system (CRUD delete). Params: systemPath, emitterName? or emitterIndex?"
2556
+ options:
2557
+ method: remove_emitter_from_system
2552
2558
  niagara.list_emitters:
2553
2559
  class_path: ue-mcp.bridge
2554
2560
  group: niagara
@@ -2633,6 +2639,12 @@ tasks:
2633
2639
  description: "Set literal default on a module input pin. Params: systemPath, moduleName, inputName, value, emitterName?, emitterIndex?, stackContext?"
2634
2640
  options:
2635
2641
  method: set_niagara_module_input
2642
+ niagara.add_module:
2643
+ class_path: ue-mcp.bridge
2644
+ group: niagara
2645
+ description: "Add a stock /Niagara/Modules script to an emitter stack (the modules that make an emitter actually do anything). Params: systemPath, moduleScript (e.g. /Niagara/Modules/Emitter/SpawnRate), stackContext (ParticleSpawn|ParticleUpdate|EmitterSpawn|EmitterUpdate), emitterName?, emitterIndex?, targetIndex? (-1 appends). Then set_module_input to tune it."
2646
+ options:
2647
+ method: add_niagara_module
2636
2648
  niagara.list_static_switches:
2637
2649
  class_path: ue-mcp.bridge
2638
2650
  group: niagara
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ue-mcp",
3
- "version": "1.1.28",
4
- "description": "Unreal Engine MCP server - 24 tools, 736+ actions for AI-driven editor control",
3
+ "version": "1.1.30",
4
+ "description": "Unreal Engine MCP server - 24 tools, 738+ actions for AI-driven editor control",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
@@ -25,6 +25,12 @@
25
25
  #include "NiagaraGraph.h"
26
26
  #include "NiagaraNodeFunctionCall.h"
27
27
  #include "NiagaraNodeCustomHlsl.h"
28
+ #include "NiagaraNodeOutput.h"
29
+ #include "ViewModels/Stack/NiagaraStackGraphUtilities.h"
30
+ #include "NiagaraStackFunctionInputBinder.h"
31
+ #include "NiagaraParameterMapHistory.h"
32
+ #include "NiagaraTypes.h"
33
+ #include "EdGraphSchema_Niagara.h"
28
34
  #include "NiagaraEmitterHandle.h"
29
35
  #include "NiagaraEditorUtilities.h"
30
36
  #include "NiagaraEmitterFactoryNew.h"
@@ -79,6 +85,8 @@ void FNiagaraHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
79
85
  // v0.7.14 — module inputs, static switches, HLSL modules
80
86
  Registry.RegisterHandler(TEXT("list_niagara_module_inputs"), &ListModuleInputs);
81
87
  Registry.RegisterHandler(TEXT("set_niagara_module_input"), &SetModuleInput);
88
+ Registry.RegisterHandler(TEXT("add_niagara_module"), &AddModule);
89
+ Registry.RegisterHandler(TEXT("remove_emitter_from_system"), &RemoveEmitterFromSystem);
82
90
  Registry.RegisterHandler(TEXT("list_niagara_static_switches"), &ListStaticSwitches);
83
91
  Registry.RegisterHandler(TEXT("set_niagara_static_switch"), &SetStaticSwitch);
84
92
  Registry.RegisterHandler(TEXT("create_niagara_module_from_hlsl"), &CreateModuleFromHlsl);
@@ -1250,6 +1258,62 @@ namespace
1250
1258
  O->SetBoolField(TEXT("linked"), Pin->LinkedTo.Num() > 0);
1251
1259
  return O;
1252
1260
  }
1261
+
1262
+ ENiagaraScriptUsage UsageOfContext(const FString& Ctx)
1263
+ {
1264
+ if (Ctx.Equals(TEXT("ParticleUpdate"), ESearchCase::IgnoreCase)) return ENiagaraScriptUsage::ParticleUpdateScript;
1265
+ if (Ctx.Equals(TEXT("EmitterSpawn"), ESearchCase::IgnoreCase)) return ENiagaraScriptUsage::EmitterSpawnScript;
1266
+ if (Ctx.Equals(TEXT("EmitterUpdate"), ESearchCase::IgnoreCase)) return ENiagaraScriptUsage::EmitterUpdateScript;
1267
+ return ENiagaraScriptUsage::ParticleSpawnScript;
1268
+ }
1269
+
1270
+ // Parse a string into the raw byte layout of a Niagara input type. Covers the
1271
+ // scalar/vector/color types module inputs almost always use. Returns false
1272
+ // with a reason for unsupported types.
1273
+ bool FillNiagaraValueBytes(const FNiagaraTypeDefinition& T, const FString& Value, TArray<uint8>& Out, FString& OutErr)
1274
+ {
1275
+ auto ParseFloats = [](const FString& S, int32 N, TArray<float>& F)
1276
+ {
1277
+ TArray<FString> Parts;
1278
+ S.ParseIntoArray(Parts, TEXT(","), true);
1279
+ if (Parts.Num() == 1) S.ParseIntoArray(Parts, TEXT(" "), true);
1280
+ for (const FString& P : Parts) F.Add(FCString::Atof(*P.TrimStartAndEnd()));
1281
+ return F.Num() >= N;
1282
+ };
1283
+
1284
+ if (T == FNiagaraTypeDefinition::GetFloatDef())
1285
+ {
1286
+ float V = FCString::Atof(*Value);
1287
+ Out.SetNumUninitialized(sizeof(float)); FMemory::Memcpy(Out.GetData(), &V, sizeof(float)); return true;
1288
+ }
1289
+ if (T == FNiagaraTypeDefinition::GetIntDef())
1290
+ {
1291
+ int32 V = FCString::Atoi(*Value);
1292
+ Out.SetNumUninitialized(sizeof(int32)); FMemory::Memcpy(Out.GetData(), &V, sizeof(int32)); return true;
1293
+ }
1294
+ if (T == FNiagaraTypeDefinition::GetBoolDef())
1295
+ {
1296
+ FNiagaraBool B; B.SetValue(Value.ToBool() || Value == TEXT("1"));
1297
+ Out.SetNumUninitialized(sizeof(FNiagaraBool)); FMemory::Memcpy(Out.GetData(), &B, sizeof(FNiagaraBool)); return true;
1298
+ }
1299
+ if (T == FNiagaraTypeDefinition::GetVec2Def())
1300
+ {
1301
+ TArray<float> F; if (!ParseFloats(Value, 2, F)) { OutErr = TEXT("expected 2 comma-separated floats"); return false; }
1302
+ FVector2f V(F[0], F[1]); Out.SetNumUninitialized(sizeof(V)); FMemory::Memcpy(Out.GetData(), &V, sizeof(V)); return true;
1303
+ }
1304
+ if (T == FNiagaraTypeDefinition::GetVec3Def())
1305
+ {
1306
+ TArray<float> F; if (!ParseFloats(Value, 3, F)) { OutErr = TEXT("expected 3 comma-separated floats"); return false; }
1307
+ FVector3f V(F[0], F[1], F[2]); Out.SetNumUninitialized(sizeof(V)); FMemory::Memcpy(Out.GetData(), &V, sizeof(V)); return true;
1308
+ }
1309
+ if (T == FNiagaraTypeDefinition::GetVec4Def() || T == FNiagaraTypeDefinition::GetColorDef())
1310
+ {
1311
+ TArray<float> F; if (!ParseFloats(Value, 4, F)) { OutErr = TEXT("expected 4 comma-separated floats"); return false; }
1312
+ FVector4f V(F[0], F[1], F[2], F[3]); Out.SetNumUninitialized(sizeof(V)); FMemory::Memcpy(Out.GetData(), &V, sizeof(V)); return true;
1313
+ }
1314
+ OutErr = FString::Printf(TEXT("unsupported input type '%s' for override-map set"), *T.GetName());
1315
+ return false;
1316
+ }
1253
1317
  }
1254
1318
 
1255
1319
  TSharedPtr<FJsonValue> FNiagaraHandlers::ListModuleInputs(const TSharedPtr<FJsonObject>& Params)
@@ -1350,6 +1414,62 @@ TSharedPtr<FJsonValue> FNiagaraHandlers::SetModuleInput(const TSharedPtr<FJsonOb
1350
1414
  if (!FC) continue;
1351
1415
  SeenModules.AddUnique(FC->GetFunctionName());
1352
1416
  if (!FC->GetFunctionName().Equals(ModuleName, ESearchCase::IgnoreCase)) continue;
1417
+
1418
+ // Primary path: the real settable module inputs (SpawnRate, Lifetime,
1419
+ // sprite size, colour, ...) come from the module SCRIPT, not the
1420
+ // function-call node's pins, and their values live in the override /
1421
+ // rapid-iteration map. Enumerate the module's inputs, match by name,
1422
+ // then set the value through the stack input binder. Falls through to
1423
+ // the pin-default path only when this can't bind.
1424
+ {
1425
+ FCompileConstantResolver Resolver(FVersionedNiagaraEmitter(Emitter, Version), UsageOfContext(Slot.Context));
1426
+ TArray<FNiagaraVariable> InputVars;
1427
+ FNiagaraStackGraphUtilities::GetStackFunctionInputs(
1428
+ *FC, InputVars, Resolver,
1429
+ FNiagaraStackGraphUtilities::ENiagaraGetStackFunctionInputPinsOptions::ModuleInputsOnly, false);
1430
+
1431
+ auto LeafOf = [](const FString& N)
1432
+ {
1433
+ FString Head, Leaf;
1434
+ return N.Split(TEXT("."), &Head, &Leaf, ESearchCase::IgnoreCase, ESearchDir::FromEnd) ? Leaf : N;
1435
+ };
1436
+ const FNiagaraVariable* Found = InputVars.FindByPredicate([&](const FNiagaraVariable& V)
1437
+ {
1438
+ const FString N = V.GetName().ToString();
1439
+ return N.Equals(InputName, ESearchCase::IgnoreCase) || LeafOf(N).Equals(InputName, ESearchCase::IgnoreCase);
1440
+ });
1441
+
1442
+ if (Found)
1443
+ {
1444
+ const FString Leaf = LeafOf(Found->GetName().ToString());
1445
+ FNiagaraStackFunctionInputBinder Binder;
1446
+ TArray<UNiagaraScript*> Dependents;
1447
+ for (const FScriptSlot& Dep : Scripts)
1448
+ {
1449
+ if (Dep.Script) Dependents.Add(Dep.Script);
1450
+ }
1451
+ FText BindErr;
1452
+ if (Binder.TryBind(Slot.Script, Dependents, Resolver, Emitter->GetUniqueEmitterName(), FC,
1453
+ FName(*Leaf), TOptional<FNiagaraTypeDefinition>(Found->GetType()), true, BindErr))
1454
+ {
1455
+ TArray<uint8> Bytes;
1456
+ FString VErr;
1457
+ if (FillNiagaraValueBytes(Found->GetType(), Value, Bytes, VErr))
1458
+ {
1459
+ FC->Modify();
1460
+ Graph->Modify();
1461
+ Binder.SetData(Bytes.GetData(), Bytes.Num());
1462
+ if (SetCount == 0) PrevValue = TEXT("(override)");
1463
+ MatchedContext = Slot.Context;
1464
+ ++SetCount;
1465
+ FC->MarkNodeRequiresSynchronization(TEXT("MCP_SetModuleInput"), true);
1466
+ Graph->NotifyGraphChanged();
1467
+ continue;
1468
+ }
1469
+ }
1470
+ }
1471
+ }
1472
+
1353
1473
  for (UEdGraphPin* Pin : FC->Pins)
1354
1474
  {
1355
1475
  if (!Pin || Pin->Direction != EGPD_Input) continue;
@@ -1376,6 +1496,7 @@ TSharedPtr<FJsonValue> FNiagaraHandlers::SetModuleInput(const TSharedPtr<FJsonOb
1376
1496
  }
1377
1497
 
1378
1498
  Emitter->PostEditChange();
1499
+ System->RequestCompile(false);
1379
1500
  UEditorAssetLibrary::SaveLoadedAsset(System);
1380
1501
 
1381
1502
  TSharedPtr<FJsonObject> Res = MCPSuccess();
@@ -1401,6 +1522,151 @@ TSharedPtr<FJsonValue> FNiagaraHandlers::SetModuleInput(const TSharedPtr<FJsonOb
1401
1522
  return MCPResult(Res);
1402
1523
  }
1403
1524
 
1525
+ namespace
1526
+ {
1527
+ // Map a stack-context string to its script-usage enum and pull the matching
1528
+ // UNiagaraScript off the emitter data. Returns false for an unknown context.
1529
+ bool ResolveStackTarget(FVersionedNiagaraEmitterData* Data, const FString& Ctx, ENiagaraScriptUsage& OutUsage, UNiagaraScript*& OutScript)
1530
+ {
1531
+ if (!Data) return false;
1532
+ if (Ctx.Equals(TEXT("ParticleSpawn"), ESearchCase::IgnoreCase)) { OutUsage = ENiagaraScriptUsage::ParticleSpawnScript; OutScript = Data->SpawnScriptProps.Script; return true; }
1533
+ if (Ctx.Equals(TEXT("ParticleUpdate"), ESearchCase::IgnoreCase)) { OutUsage = ENiagaraScriptUsage::ParticleUpdateScript; OutScript = Data->UpdateScriptProps.Script; return true; }
1534
+ if (Ctx.Equals(TEXT("EmitterSpawn"), ESearchCase::IgnoreCase)) { OutUsage = ENiagaraScriptUsage::EmitterSpawnScript; OutScript = Data->EmitterSpawnScriptProps.Script; return true; }
1535
+ if (Ctx.Equals(TEXT("EmitterUpdate"), ESearchCase::IgnoreCase)) { OutUsage = ENiagaraScriptUsage::EmitterUpdateScript; OutScript = Data->EmitterUpdateScriptProps.Script; return true; }
1536
+ return false;
1537
+ }
1538
+
1539
+ // Normalise a module-script reference to a full object path. Accepts a bare
1540
+ // package path ("/Niagara/Modules/Emitter/SpawnRate") and appends the
1541
+ // ".AssetName" object suffix Niagara scripts require to load.
1542
+ FString NormaliseModulePath(const FString& In)
1543
+ {
1544
+ if (In.Contains(TEXT("."))) return In;
1545
+ FString Left, AssetName;
1546
+ if (In.Split(TEXT("/"), &Left, &AssetName, ESearchCase::IgnoreCase, ESearchDir::FromEnd) && !AssetName.IsEmpty())
1547
+ {
1548
+ return In + TEXT(".") + AssetName;
1549
+ }
1550
+ return In;
1551
+ }
1552
+ }
1553
+
1554
+ TSharedPtr<FJsonValue> FNiagaraHandlers::AddModule(const TSharedPtr<FJsonObject>& Params)
1555
+ {
1556
+ FString SystemPath;
1557
+ if (auto Err = RequireString(Params, TEXT("systemPath"), SystemPath)) return Err;
1558
+ FString ModuleScriptRef;
1559
+ if (auto Err = RequireString(Params, TEXT("moduleScript"), ModuleScriptRef)) return Err;
1560
+ FString StackContext;
1561
+ if (auto Err = RequireString(Params, TEXT("stackContext"), StackContext)) return Err;
1562
+ FString EmitterName = OptionalString(Params, TEXT("emitterName"), TEXT(""));
1563
+ int32 EmitterIndex = OptionalInt(Params, TEXT("emitterIndex"), 0);
1564
+ // -1 (default) appends to the end of the stack; >=0 inserts at that index.
1565
+ int32 TargetIndex = OptionalInt(Params, TEXT("targetIndex"), -1);
1566
+
1567
+ UNiagaraSystem* System = Cast<UNiagaraSystem>(UEditorAssetLibrary::LoadAsset(SystemPath));
1568
+ if (!System) return MCPError(FString::Printf(TEXT("System not found: %s"), *SystemPath));
1569
+
1570
+ UNiagaraEmitter* Emitter = nullptr;
1571
+ FGuid Version;
1572
+ FVersionedNiagaraEmitterData* Data = ResolveEmitter(System, EmitterName, EmitterIndex, Emitter, Version);
1573
+ if (!Data) return MCPError(TEXT("Emitter not resolved"));
1574
+
1575
+ ENiagaraScriptUsage Usage;
1576
+ UNiagaraScript* Script = nullptr;
1577
+ if (!ResolveStackTarget(Data, StackContext, Usage, Script) || !Script)
1578
+ {
1579
+ return MCPError(FString::Printf(TEXT("Invalid stackContext '%s'. Use ParticleSpawn|ParticleUpdate|EmitterSpawn|EmitterUpdate."), *StackContext));
1580
+ }
1581
+
1582
+ UNiagaraGraph* Graph = GraphOfScript(Script);
1583
+ if (!Graph) return MCPError(TEXT("Emitter script has no source graph"));
1584
+
1585
+ // FindEquivalentOutputNode is the NIAGARAEDITOR_API-exported variant
1586
+ // (plain FindOutputNode is not exported and won't link).
1587
+ UNiagaraNodeOutput* OutputNode = Graph->FindEquivalentOutputNode(Usage);
1588
+ if (!OutputNode) return MCPError(FString::Printf(TEXT("No output node for usage in context '%s'"), *StackContext));
1589
+
1590
+ const FString ModulePath = NormaliseModulePath(ModuleScriptRef);
1591
+ UNiagaraScript* ModuleScript = LoadObject<UNiagaraScript>(nullptr, *ModulePath);
1592
+ if (!ModuleScript)
1593
+ {
1594
+ return MCPError(FString::Printf(TEXT("Module script not found: %s (try a /Niagara/Modules/... path)"), *ModulePath));
1595
+ }
1596
+
1597
+ Graph->Modify();
1598
+ UNiagaraNodeFunctionCall* NewModule =
1599
+ FNiagaraStackGraphUtilities::AddScriptModuleToStack(ModuleScript, *OutputNode, TargetIndex);
1600
+ if (!NewModule)
1601
+ {
1602
+ return MCPError(FString::Printf(TEXT("Failed to add module '%s' to %s stack"), *ModulePath, *StackContext));
1603
+ }
1604
+
1605
+ Graph->NotifyGraphChanged();
1606
+ if (Emitter) Emitter->PostEditChange();
1607
+ System->PostEditChange();
1608
+ // Force a compile so the emitter is immediately usable (e.g. a verify step
1609
+ // that spawns it and reads particle count).
1610
+ System->RequestCompile(false);
1611
+ UEditorAssetLibrary::SaveLoadedAsset(System);
1612
+
1613
+ TSharedPtr<FJsonObject> Res = MCPSuccess();
1614
+ MCPSetCreated(Res);
1615
+ Res->SetStringField(TEXT("systemPath"), SystemPath);
1616
+ Res->SetStringField(TEXT("emitter"), Emitter ? Emitter->GetName() : TEXT(""));
1617
+ Res->SetStringField(TEXT("stackContext"), StackContext);
1618
+ Res->SetStringField(TEXT("moduleScript"), ModulePath);
1619
+ Res->SetStringField(TEXT("moduleName"), NewModule->GetFunctionName());
1620
+ Res->SetNumberField(TEXT("targetIndex"), TargetIndex);
1621
+ Res->SetStringField(TEXT("note"), TEXT("Module node added and wired into the parameter map. Set its inputs with set_niagara_module_input."));
1622
+ return MCPResult(Res);
1623
+ }
1624
+
1625
+ TSharedPtr<FJsonValue> FNiagaraHandlers::RemoveEmitterFromSystem(const TSharedPtr<FJsonObject>& Params)
1626
+ {
1627
+ FString SystemPath;
1628
+ if (auto Err = RequireString(Params, TEXT("systemPath"), SystemPath)) return Err;
1629
+ FString EmitterName = OptionalString(Params, TEXT("emitterName"), TEXT(""));
1630
+ int32 EmitterIndex = OptionalInt(Params, TEXT("emitterIndex"), -1);
1631
+
1632
+ UNiagaraSystem* System = Cast<UNiagaraSystem>(UEditorAssetLibrary::LoadAsset(SystemPath));
1633
+ if (!System) return MCPError(FString::Printf(TEXT("System not found: %s"), *SystemPath));
1634
+
1635
+ const TArray<FNiagaraEmitterHandle>& Handles = System->GetEmitterHandles();
1636
+ int32 TargetIdx = -1;
1637
+ if (!EmitterName.IsEmpty())
1638
+ {
1639
+ for (int32 i = 0; i < Handles.Num(); ++i)
1640
+ {
1641
+ if (Handles[i].GetName().ToString().Equals(EmitterName, ESearchCase::IgnoreCase)) { TargetIdx = i; break; }
1642
+ }
1643
+ }
1644
+ else if (EmitterIndex >= 0 && EmitterIndex < Handles.Num())
1645
+ {
1646
+ TargetIdx = EmitterIndex;
1647
+ }
1648
+ if (TargetIdx < 0)
1649
+ {
1650
+ return MCPError(FString::Printf(TEXT("Emitter not found (name='%s', index=%d) in %s"), *EmitterName, EmitterIndex, *SystemPath));
1651
+ }
1652
+
1653
+ const FString RemovedName = Handles[TargetIdx].GetName().ToString();
1654
+ const FGuid RemovedId = Handles[TargetIdx].GetId();
1655
+
1656
+ System->Modify();
1657
+ System->RemoveEmitterHandlesById({ RemovedId });
1658
+ System->RequestCompile(false);
1659
+ System->PostEditChange();
1660
+ UEditorAssetLibrary::SaveLoadedAsset(System);
1661
+
1662
+ TSharedPtr<FJsonObject> Res = MCPSuccess();
1663
+ MCPSetUpdated(Res);
1664
+ Res->SetStringField(TEXT("systemPath"), SystemPath);
1665
+ Res->SetStringField(TEXT("removedEmitter"), RemovedName);
1666
+ Res->SetNumberField(TEXT("remainingEmitters"), System->GetEmitterHandles().Num());
1667
+ return MCPResult(Res);
1668
+ }
1669
+
1404
1670
  TSharedPtr<FJsonValue> FNiagaraHandlers::ListStaticSwitches(const TSharedPtr<FJsonObject>& Params)
1405
1671
  {
1406
1672
  FString SystemPath;
@@ -37,6 +37,10 @@ private:
37
37
  // v0.7.14 — module inputs, static switches, HLSL modules
38
38
  static TSharedPtr<FJsonValue> ListModuleInputs(const TSharedPtr<FJsonObject>& Params);
39
39
  static TSharedPtr<FJsonValue> SetModuleInput(const TSharedPtr<FJsonObject>& Params);
40
+ // Add a stock /Niagara/Modules script to an emitter's stack context.
41
+ static TSharedPtr<FJsonValue> AddModule(const TSharedPtr<FJsonObject>& Params);
42
+ // Remove an emitter handle from a system (CRUD delete).
43
+ static TSharedPtr<FJsonValue> RemoveEmitterFromSystem(const TSharedPtr<FJsonObject>& Params);
40
44
  static TSharedPtr<FJsonValue> ListStaticSwitches(const TSharedPtr<FJsonObject>& Params);
41
45
  static TSharedPtr<FJsonValue> SetStaticSwitch(const TSharedPtr<FJsonObject>& Params);
42
46
  static TSharedPtr<FJsonValue> CreateModuleFromHlsl(const TSharedPtr<FJsonObject>& Params);