ue-mcp 1.2.1 → 1.2.2

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 (54) hide show
  1. package/dist/context-cli.js +16 -16
  2. package/dist/engine-observer.js +68 -68
  3. package/dist/flow/guard.d.ts +26 -37
  4. package/dist/flow/guard.js +40 -25
  5. package/dist/flow/guard.js.map +1 -1
  6. package/dist/flow/guarded-bridge.d.ts +0 -10
  7. package/dist/flow/guarded-bridge.js +18 -23
  8. package/dist/flow/guarded-bridge.js.map +1 -1
  9. package/dist/flow/schema.d.ts +276 -16
  10. package/dist/flow/task-guards.d.ts +1 -1
  11. package/dist/flow/task-guards.js +44 -68
  12. package/dist/flow/task-guards.js.map +1 -1
  13. package/dist/instructions.js +130 -130
  14. package/dist/plugin-cli.js +299 -299
  15. package/dist/tool-counts.json +2 -2
  16. package/package.json +2 -2
  17. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.cpp +76 -76
  18. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.h +27 -27
  19. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +128 -128
  20. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +63 -63
  21. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +230 -230
  22. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +323 -323
  23. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +20 -20
  24. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers_Nested.cpp +537 -537
  25. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +77 -77
  26. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +353 -353
  27. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +18 -18
  28. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_InputRuntime.cpp +246 -246
  29. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +597 -597
  30. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +51 -51
  31. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +878 -878
  32. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +449 -449
  33. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Function.cpp +275 -275
  34. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Graph.cpp +551 -551
  35. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +531 -531
  36. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +28 -28
  37. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +677 -677
  38. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +822 -822
  39. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +22 -22
  40. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +218 -218
  41. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +17 -17
  42. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.cpp +46 -46
  43. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.h +23 -23
  44. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/MCPExternalRegistry.cpp +83 -83
  45. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -14
  46. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/UE_MCP_BridgeStatusModule.cpp +37 -37
  47. package/dist/manifest-signature.d.ts +0 -1
  48. package/dist/manifest-signature.js +0 -53
  49. package/dist/manifest-signature.js.map +0 -1
  50. package/dist/pie/schema.d.ts +0 -791
  51. package/dist/pie/schema.js +0 -151
  52. package/dist/pie/schema.js.map +0 -1
  53. package/dist/watch-cli.js.map +0 -1
  54. /package/plugin/ue_mcp_bridge/{ue_mcp_bridge.uplugin → UE_MCP_Bridge.uplugin} +0 -0
@@ -478,117 +478,117 @@ function writeScaffold(dir, pkgName, prefix) {
478
478
  include: ["src/**/*"],
479
479
  };
480
480
  fs.writeFileSync(path.join(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
481
- const manifestYaml = `actionPrefix: ${prefix}
482
- minServerVersion: ${minServer}
483
-
484
- # This scaffold is a SUPERSET: it shows every way a plugin can extend ue-mcp.
485
- # Keep the shapes you need and delete the rest.
486
- # 1) inject - add actions onto a built-in category (names are prefixed)
487
- # 2) provides - own a brand-new top-level category (names are NOT prefixed)
488
- # 3) flows - chain tasks/actions into one orchestrated call
489
- # 4) nativeModule (commented, at the bottom) - ship C++ handlers on the bridge
490
-
491
- # 1) inject: '${prefix}_hello' lands on the built-in 'project' tool, reached as
492
- # project(action="${prefix}_hello").
493
- inject:
494
- project:
495
- hello:
496
- task: ${prefix}.hello
497
- description: "Greet by name - a stand-in inject action this scaffold ships with"
498
- schema:
499
- name: { type: string, description: "Who to greet (default: world)" }
500
-
501
- # 2) provides: a category the plugin owns. Actions are NOT prefixed - the
502
- # category name is the namespace, e.g. ${prefix}(action="greet").
503
- provides:
504
- ${prefix}:
505
- description: "${pkgName} - example plugin-owned category"
506
- actions:
507
- greet:
508
- task: ${prefix}.greet
509
- description: "Greet by name from a plugin-owned category"
510
- schema:
511
- name: { type: string, description: "Who to greet (default: world)" }
512
-
513
- tasks:
514
- ${prefix}.hello:
515
- class_path: tasks/${helloClass}
516
- ${prefix}.greet:
517
- class_path: tasks/${greetClass}
518
-
519
- # 3) flows: chain tasks/actions into one call. This one just runs the hello
520
- # task; expand 'steps' to orchestrate real multi-step work.
521
- flows:
522
- ${prefix}_demo:
523
- description: "Example flow: run the hello task"
524
- steps:
525
- 1:
526
- task: ${prefix}.hello
527
- options:
528
- name: world
529
-
530
- # 4) nativeModule: ship C++ handlers that register on the bridge. DORMANT by
531
- # default - the C++ skeleton already lives under ue/Plugins/${uePlugin}/, but
532
- # it is not deployed or compiled until you UNCOMMENT this block. Activating it
533
- # makes 'ue-mcp plugin install' deploy the module and require a UE rebuild.
534
- # The handlers then surface unprefixed under a '${nativeCategory}' category,
535
- # e.g. ${nativeCategory}(action="echo").
536
- # nativeModule:
537
- # uePluginName: ${uePlugin}
538
- # minBridgeApi: 1
539
- # source: ue/Plugins/${uePlugin}
540
- # category: ${nativeCategory}
541
- # categoryDescription: "${pkgName} native C++ handlers"
542
- # handlers:
543
- # echo:
544
- # description: "Echo a name back from native C++ (required: name)"
545
- # schema:
546
- # name: { type: string, description: "Name to echo" }
481
+ const manifestYaml = `actionPrefix: ${prefix}
482
+ minServerVersion: ${minServer}
483
+
484
+ # This scaffold is a SUPERSET: it shows every way a plugin can extend ue-mcp.
485
+ # Keep the shapes you need and delete the rest.
486
+ # 1) inject - add actions onto a built-in category (names are prefixed)
487
+ # 2) provides - own a brand-new top-level category (names are NOT prefixed)
488
+ # 3) flows - chain tasks/actions into one orchestrated call
489
+ # 4) nativeModule (commented, at the bottom) - ship C++ handlers on the bridge
490
+
491
+ # 1) inject: '${prefix}_hello' lands on the built-in 'project' tool, reached as
492
+ # project(action="${prefix}_hello").
493
+ inject:
494
+ project:
495
+ hello:
496
+ task: ${prefix}.hello
497
+ description: "Greet by name - a stand-in inject action this scaffold ships with"
498
+ schema:
499
+ name: { type: string, description: "Who to greet (default: world)" }
500
+
501
+ # 2) provides: a category the plugin owns. Actions are NOT prefixed - the
502
+ # category name is the namespace, e.g. ${prefix}(action="greet").
503
+ provides:
504
+ ${prefix}:
505
+ description: "${pkgName} - example plugin-owned category"
506
+ actions:
507
+ greet:
508
+ task: ${prefix}.greet
509
+ description: "Greet by name from a plugin-owned category"
510
+ schema:
511
+ name: { type: string, description: "Who to greet (default: world)" }
512
+
513
+ tasks:
514
+ ${prefix}.hello:
515
+ class_path: tasks/${helloClass}
516
+ ${prefix}.greet:
517
+ class_path: tasks/${greetClass}
518
+
519
+ # 3) flows: chain tasks/actions into one call. This one just runs the hello
520
+ # task; expand 'steps' to orchestrate real multi-step work.
521
+ flows:
522
+ ${prefix}_demo:
523
+ description: "Example flow: run the hello task"
524
+ steps:
525
+ 1:
526
+ task: ${prefix}.hello
527
+ options:
528
+ name: world
529
+
530
+ # 4) nativeModule: ship C++ handlers that register on the bridge. DORMANT by
531
+ # default - the C++ skeleton already lives under ue/Plugins/${uePlugin}/, but
532
+ # it is not deployed or compiled until you UNCOMMENT this block. Activating it
533
+ # makes 'ue-mcp plugin install' deploy the module and require a UE rebuild.
534
+ # The handlers then surface unprefixed under a '${nativeCategory}' category,
535
+ # e.g. ${nativeCategory}(action="echo").
536
+ # nativeModule:
537
+ # uePluginName: ${uePlugin}
538
+ # minBridgeApi: 1
539
+ # source: ue/Plugins/${uePlugin}
540
+ # category: ${nativeCategory}
541
+ # categoryDescription: "${pkgName} native C++ handlers"
542
+ # handlers:
543
+ # echo:
544
+ # description: "Echo a name back from native C++ (required: name)"
545
+ # schema:
546
+ # name: { type: string, description: "Name to echo" }
547
547
  `;
548
548
  fs.writeFileSync(path.join(dir, "ue-mcp.plugin.yml"), manifestYaml);
549
549
  // ── TypeScript: index stub + the two example tasks ──────────────────────
550
550
  fs.mkdirSync(path.join(dir, "src", "tasks"), { recursive: true });
551
- const indexTs = `// Entry point for the npm package. ue-mcp loads tasks by their manifest
552
- // class_path, not through this file, so it can stay empty - but package.json's
553
- // "main" points here, so the build must emit it.
554
- export {};
551
+ const indexTs = `// Entry point for the npm package. ue-mcp loads tasks by their manifest
552
+ // class_path, not through this file, so it can stay empty - but package.json's
553
+ // "main" points here, so the build must emit it.
554
+ export {};
555
555
  `;
556
556
  fs.writeFileSync(path.join(dir, "src", "index.ts"), indexTs);
557
- const helloTs = `import { UeMcpTask, type TaskResult } from "ue-mcp/task";
558
-
559
- interface Options {
560
- name?: string;
561
- }
562
-
563
- /** Backs project(action="${prefix}_hello") and the ${prefix}_demo flow. */
564
- export default class ${helloClass} extends UeMcpTask<Options> {
565
- get taskName() { return "${prefix}.hello"; }
566
-
567
- async execute(): Promise<TaskResult> {
568
- const who = this.options.name ?? "world";
569
- return { success: true, data: { greeting: \`hello, \${who}\` } };
570
- }
571
- }
557
+ const helloTs = `import { UeMcpTask, type TaskResult } from "ue-mcp/task";
558
+
559
+ interface Options {
560
+ name?: string;
561
+ }
562
+
563
+ /** Backs project(action="${prefix}_hello") and the ${prefix}_demo flow. */
564
+ export default class ${helloClass} extends UeMcpTask<Options> {
565
+ get taskName() { return "${prefix}.hello"; }
566
+
567
+ async execute(): Promise<TaskResult> {
568
+ const who = this.options.name ?? "world";
569
+ return { success: true, data: { greeting: \`hello, \${who}\` } };
570
+ }
571
+ }
572
572
  `;
573
573
  fs.writeFileSync(path.join(dir, "src", "tasks", `${helloClass}.ts`), helloTs);
574
- const greetTs = `import { UeMcpTask, type TaskResult } from "ue-mcp/task";
575
-
576
- interface Options {
577
- name?: string;
578
- }
579
-
580
- /**
581
- * Backs ${prefix}(action="greet") - the plugin-owned category. Swap the body
582
- * for real work; compose built-ins with \`this.call("level.get_outliner", {})\`.
583
- */
584
- export default class ${greetClass} extends UeMcpTask<Options> {
585
- get taskName() { return "${prefix}.greet"; }
586
-
587
- async execute(): Promise<TaskResult> {
588
- const who = this.options.name ?? "world";
589
- return { success: true, data: { greeting: \`greetings, \${who}\` } };
590
- }
591
- }
574
+ const greetTs = `import { UeMcpTask, type TaskResult } from "ue-mcp/task";
575
+
576
+ interface Options {
577
+ name?: string;
578
+ }
579
+
580
+ /**
581
+ * Backs ${prefix}(action="greet") - the plugin-owned category. Swap the body
582
+ * for real work; compose built-ins with \`this.call("level.get_outliner", {})\`.
583
+ */
584
+ export default class ${greetClass} extends UeMcpTask<Options> {
585
+ get taskName() { return "${prefix}.greet"; }
586
+
587
+ async execute(): Promise<TaskResult> {
588
+ const who = this.options.name ?? "world";
589
+ return { success: true, data: { greeting: \`greetings, \${who}\` } };
590
+ }
591
+ }
592
592
  `;
593
593
  fs.writeFileSync(path.join(dir, "src", "tasks", `${greetClass}.ts`), greetTs);
594
594
  // ── Pre-publish sanity check ────────────────────────────────────────────
@@ -600,66 +600,66 @@ export default class ${greetClass} extends UeMcpTask<Options> {
600
600
  // ── Dormant native C++ module ────────────────────────────────────────────
601
601
  writeNativeSkeleton(dir, uePlugin, pkgName);
602
602
  // ── README / LICENSE / .gitignore ────────────────────────────────────────
603
- const readme = `# ${pkgName}
604
-
605
- A ue-mcp plugin. Install with:
606
-
607
- \`\`\`bash
608
- ue-mcp plugin install ${pkgName}
609
- \`\`\`
610
-
611
- ## What this scaffold ships
612
-
613
- It is a **superset** - every way a plugin can extend ue-mcp, wired and working.
614
- Keep what you want, delete the rest.
615
-
616
- - **inject** -> \`project(action="${prefix}_hello")\` (an action added onto a built-in category)
617
- - **provides** -> \`${prefix}(action="greet")\` (a new top-level category this plugin owns)
618
- - **flows** -> \`${prefix}_demo\` (a chained, one-call orchestration)
619
- - **nativeModule** -> a C++ handler skeleton under \`ue/Plugins/${uePlugin}/\`, **dormant** until you activate it
620
-
621
- ## Activate the native C++ module
622
-
623
- The C++ source is already on disk but inert. To turn it on:
624
-
625
- 1. Uncomment the \`nativeModule:\` block at the bottom of \`ue-mcp.plugin.yml\`.
626
- 2. Reinstall (\`ue-mcp plugin install ${pkgName}\`) - this deploys the module into
627
- your project's \`Plugins/\` and requires a UE rebuild before the editor starts.
628
-
629
- The handler then surfaces as \`${prefix}_native(action="echo")\`.
630
-
631
- ## Develop
632
-
633
- \`\`\`bash
634
- npm install
635
- npm run build
636
- npm run check # validate the manifest + task wiring
637
- \`\`\`
638
-
639
- See https://ue-mcp.com/docs/plugins/ for the full author contract.
603
+ const readme = `# ${pkgName}
604
+
605
+ A ue-mcp plugin. Install with:
606
+
607
+ \`\`\`bash
608
+ ue-mcp plugin install ${pkgName}
609
+ \`\`\`
610
+
611
+ ## What this scaffold ships
612
+
613
+ It is a **superset** - every way a plugin can extend ue-mcp, wired and working.
614
+ Keep what you want, delete the rest.
615
+
616
+ - **inject** -> \`project(action="${prefix}_hello")\` (an action added onto a built-in category)
617
+ - **provides** -> \`${prefix}(action="greet")\` (a new top-level category this plugin owns)
618
+ - **flows** -> \`${prefix}_demo\` (a chained, one-call orchestration)
619
+ - **nativeModule** -> a C++ handler skeleton under \`ue/Plugins/${uePlugin}/\`, **dormant** until you activate it
620
+
621
+ ## Activate the native C++ module
622
+
623
+ The C++ source is already on disk but inert. To turn it on:
624
+
625
+ 1. Uncomment the \`nativeModule:\` block at the bottom of \`ue-mcp.plugin.yml\`.
626
+ 2. Reinstall (\`ue-mcp plugin install ${pkgName}\`) - this deploys the module into
627
+ your project's \`Plugins/\` and requires a UE rebuild before the editor starts.
628
+
629
+ The handler then surfaces as \`${prefix}_native(action="echo")\`.
630
+
631
+ ## Develop
632
+
633
+ \`\`\`bash
634
+ npm install
635
+ npm run build
636
+ npm run check # validate the manifest + task wiring
637
+ \`\`\`
638
+
639
+ See https://ue-mcp.com/docs/plugins/ for the full author contract.
640
640
  `;
641
641
  fs.writeFileSync(path.join(dir, "README.md"), readme);
642
- fs.writeFileSync(path.join(dir, "LICENSE"), `MIT License
643
-
644
- Copyright (c) ${year} ${pkgName} authors
645
-
646
- Permission is hereby granted, free of charge, to any person obtaining a copy
647
- of this software and associated documentation files (the "Software"), to deal
648
- in the Software without restriction, including without limitation the rights
649
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
650
- copies of the Software, and to permit persons to whom the Software is
651
- furnished to do so, subject to the following conditions:
652
-
653
- The above copyright notice and this permission notice shall be included in all
654
- copies or substantial portions of the Software.
655
-
656
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
657
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
658
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
659
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
660
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
661
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
662
- SOFTWARE.
642
+ fs.writeFileSync(path.join(dir, "LICENSE"), `MIT License
643
+
644
+ Copyright (c) ${year} ${pkgName} authors
645
+
646
+ Permission is hereby granted, free of charge, to any person obtaining a copy
647
+ of this software and associated documentation files (the "Software"), to deal
648
+ in the Software without restriction, including without limitation the rights
649
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
650
+ copies of the Software, and to permit persons to whom the Software is
651
+ furnished to do so, subject to the following conditions:
652
+
653
+ The above copyright notice and this permission notice shall be included in all
654
+ copies or substantial portions of the Software.
655
+
656
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
657
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
658
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
659
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
660
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
661
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
662
+ SOFTWARE.
663
663
  `);
664
664
  fs.writeFileSync(path.join(dir, ".gitignore"), `node_modules/\ndist/\n*.tgz\n.DS_Store\n`);
665
665
  }
@@ -704,96 +704,96 @@ function writeNativeSkeleton(dir, uePlugin, pkgName) {
704
704
  ],
705
705
  };
706
706
  fs.writeFileSync(path.join(base, `${uePlugin}.uplugin`), JSON.stringify(uplugin, null, 2) + "\n");
707
- fs.writeFileSync(path.join(moduleDir, `${uePlugin}.Build.cs`), `using UnrealBuildTool;
708
-
709
- public class ${uePlugin} : ModuleRules
710
- {
711
- \tpublic ${uePlugin}(ReadOnlyTargetRules Target) : base(Target)
712
- \t{
713
- \t\tPCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
714
-
715
- \t\tPublicDependencyModuleNames.AddRange(new string[]
716
- \t\t{
717
- \t\t\t"Core",
718
- \t\t\t"CoreUObject",
719
- \t\t\t"Engine",
720
- \t\t\t"Json",
721
- \t\t\t"JsonUtilities",
722
- \t\t});
723
-
724
- \t\t// UE_MCP_Bridge exposes UEMCP::RegisterExternalHandler (MCPHandlerRegistration.h).
725
- \t\tPrivateDependencyModuleNames.AddRange(new string[]
726
- \t\t{
727
- \t\t\t"UE_MCP_Bridge",
728
- \t\t});
729
- \t}
730
- }
707
+ fs.writeFileSync(path.join(moduleDir, `${uePlugin}.Build.cs`), `using UnrealBuildTool;
708
+
709
+ public class ${uePlugin} : ModuleRules
710
+ {
711
+ \tpublic ${uePlugin}(ReadOnlyTargetRules Target) : base(Target)
712
+ \t{
713
+ \t\tPCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
714
+
715
+ \t\tPublicDependencyModuleNames.AddRange(new string[]
716
+ \t\t{
717
+ \t\t\t"Core",
718
+ \t\t\t"CoreUObject",
719
+ \t\t\t"Engine",
720
+ \t\t\t"Json",
721
+ \t\t\t"JsonUtilities",
722
+ \t\t});
723
+
724
+ \t\t// UE_MCP_Bridge exposes UEMCP::RegisterExternalHandler (MCPHandlerRegistration.h).
725
+ \t\tPrivateDependencyModuleNames.AddRange(new string[]
726
+ \t\t{
727
+ \t\t\t"UE_MCP_Bridge",
728
+ \t\t});
729
+ \t}
730
+ }
731
731
  `);
732
- fs.writeFileSync(path.join(publicDir, `${uePlugin}Module.h`), `#pragma once
733
-
734
- #include "CoreMinimal.h"
735
- #include "Modules/ModuleManager.h"
736
-
737
- DECLARE_LOG_CATEGORY_EXTERN(Log${uePlugin}, Log, All);
738
-
739
- class F${uePlugin}Module : public IModuleInterface
740
- {
741
- public:
742
- \tvirtual void StartupModule() override;
743
- \tvirtual void ShutdownModule() override;
744
- };
732
+ fs.writeFileSync(path.join(publicDir, `${uePlugin}Module.h`), `#pragma once
733
+
734
+ #include "CoreMinimal.h"
735
+ #include "Modules/ModuleManager.h"
736
+
737
+ DECLARE_LOG_CATEGORY_EXTERN(Log${uePlugin}, Log, All);
738
+
739
+ class F${uePlugin}Module : public IModuleInterface
740
+ {
741
+ public:
742
+ \tvirtual void StartupModule() override;
743
+ \tvirtual void ShutdownModule() override;
744
+ };
745
745
  `);
746
- fs.writeFileSync(path.join(privateDir, `${uePlugin}Module.cpp`), `#include "${uePlugin}Module.h"
747
- #include "Modules/ModuleManager.h"
748
- #include "MCPHandlerRegistration.h"
749
- #include "Handlers/ExampleHandlers.h"
750
-
751
- DEFINE_LOG_CATEGORY(Log${uePlugin});
752
- IMPLEMENT_MODULE(F${uePlugin}Module, ${uePlugin})
753
-
754
- void F${uePlugin}Module::StartupModule()
755
- {
756
- \t// Bare method names. When this module is surfaced via nativeModule.category
757
- \t// in ue-mcp.plugin.yml, ue-mcp routes <category>(action="echo") to "echo".
758
- \tUEMCP::RegisterExternalHandler(TEXT("echo"), &FExampleHandlers::Echo);
759
-
760
- \tUE_LOG(Log${uePlugin}, Log, TEXT("[${uePlugin}] Registered 1 handler"));
761
- }
762
-
763
- void F${uePlugin}Module::ShutdownModule()
764
- {
765
- \tUEMCP::UnregisterExternalHandler(TEXT("echo"));
766
- }
746
+ fs.writeFileSync(path.join(privateDir, `${uePlugin}Module.cpp`), `#include "${uePlugin}Module.h"
747
+ #include "Modules/ModuleManager.h"
748
+ #include "MCPHandlerRegistration.h"
749
+ #include "Handlers/ExampleHandlers.h"
750
+
751
+ DEFINE_LOG_CATEGORY(Log${uePlugin});
752
+ IMPLEMENT_MODULE(F${uePlugin}Module, ${uePlugin})
753
+
754
+ void F${uePlugin}Module::StartupModule()
755
+ {
756
+ \t// Bare method names. When this module is surfaced via nativeModule.category
757
+ \t// in ue-mcp.plugin.yml, ue-mcp routes <category>(action="echo") to "echo".
758
+ \tUEMCP::RegisterExternalHandler(TEXT("echo"), &FExampleHandlers::Echo);
759
+
760
+ \tUE_LOG(Log${uePlugin}, Log, TEXT("[${uePlugin}] Registered 1 handler"));
761
+ }
762
+
763
+ void F${uePlugin}Module::ShutdownModule()
764
+ {
765
+ \tUEMCP::UnregisterExternalHandler(TEXT("echo"));
766
+ }
767
767
  `);
768
- fs.writeFileSync(path.join(handlersDir, "ExampleHandlers.h"), `#pragma once
769
-
770
- #include "CoreMinimal.h"
771
- #include "Dom/JsonObject.h"
772
- #include "Dom/JsonValue.h"
773
-
774
- /** Example external handler registered on the UE-MCP bridge. */
775
- class FExampleHandlers
776
- {
777
- public:
778
- \t/** Echo a 'name' param back. Bridge method: "echo". */
779
- \tstatic TSharedPtr<FJsonValue> Echo(const TSharedPtr<FJsonObject>& Params);
780
- };
768
+ fs.writeFileSync(path.join(handlersDir, "ExampleHandlers.h"), `#pragma once
769
+
770
+ #include "CoreMinimal.h"
771
+ #include "Dom/JsonObject.h"
772
+ #include "Dom/JsonValue.h"
773
+
774
+ /** Example external handler registered on the UE-MCP bridge. */
775
+ class FExampleHandlers
776
+ {
777
+ public:
778
+ \t/** Echo a 'name' param back. Bridge method: "echo". */
779
+ \tstatic TSharedPtr<FJsonValue> Echo(const TSharedPtr<FJsonObject>& Params);
780
+ };
781
781
  `);
782
- fs.writeFileSync(path.join(handlersDir, "ExampleHandlers.cpp"), `#include "Handlers/ExampleHandlers.h"
783
-
784
- TSharedPtr<FJsonValue> FExampleHandlers::Echo(const TSharedPtr<FJsonObject>& Params)
785
- {
786
- \tFString Name = TEXT("world");
787
- \tif (Params.IsValid())
788
- \t{
789
- \t\tParams->TryGetStringField(TEXT("name"), Name);
790
- \t}
791
-
792
- \tTSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
793
- \tResult->SetBoolField(TEXT("success"), true);
794
- \tResult->SetStringField(TEXT("echo"), FString::Printf(TEXT("hello, %s"), *Name));
795
- \treturn MakeShared<FJsonValueObject>(Result);
796
- }
782
+ fs.writeFileSync(path.join(handlersDir, "ExampleHandlers.cpp"), `#include "Handlers/ExampleHandlers.h"
783
+
784
+ TSharedPtr<FJsonValue> FExampleHandlers::Echo(const TSharedPtr<FJsonObject>& Params)
785
+ {
786
+ \tFString Name = TEXT("world");
787
+ \tif (Params.IsValid())
788
+ \t{
789
+ \t\tParams->TryGetStringField(TEXT("name"), Name);
790
+ \t}
791
+
792
+ \tTSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
793
+ \tResult->SetBoolField(TEXT("success"), true);
794
+ \tResult->SetStringField(TEXT("echo"), FString::Printf(TEXT("hello, %s"), *Name));
795
+ \treturn MakeShared<FJsonValueObject>(Result);
796
+ }
797
797
  `);
798
798
  }
799
799
  /**
@@ -802,58 +802,58 @@ TSharedPtr<FJsonValue> FExampleHandlers::Echo(const TSharedPtr<FJsonObject>& Par
802
802
  * resolves to a tasks: entry, and every tasks: class_path points at a real
803
803
  * source/built file. No build step required - runs on plain node.
804
804
  */
805
- const CHECK_SCRIPT = `#!/usr/bin/env node
806
- // Sanity-check a ue-mcp plugin: manifest parses, task references resolve, and
807
- // every class_path points at a real source or built file.
808
- import fs from "node:fs";
809
- import path from "node:path";
810
- import yaml from "js-yaml";
811
-
812
- const root = process.cwd();
813
- const manifestPath = path.join(root, "ue-mcp.plugin.yml");
814
- let errors = 0;
815
- const fail = (m) => { console.error(" x " + m); errors++; };
816
-
817
- if (!fs.existsSync(manifestPath)) {
818
- console.error("ue-mcp.plugin.yml not found");
819
- process.exit(1);
820
- }
821
- const m = yaml.load(fs.readFileSync(manifestPath, "utf8")) ?? {};
822
- const tasks = m.tasks ?? {};
823
-
824
- // Collect every task reference from inject + provides + flows.
825
- const refs = [];
826
- for (const [cat, actions] of Object.entries(m.inject ?? {}))
827
- for (const [a, def] of Object.entries(actions))
828
- if (def?.task) refs.push(["inject " + cat + "." + a, def.task]);
829
- for (const [cat, spec] of Object.entries(m.provides ?? {}))
830
- for (const [a, def] of Object.entries(spec?.actions ?? {}))
831
- if (def?.task) refs.push(["provides " + cat + "." + a, def.task]);
832
- for (const [fname, fdef] of Object.entries(m.flows ?? {}))
833
- for (const [s, step] of Object.entries(fdef?.steps ?? {}))
834
- if (step?.task) refs.push(["flow " + fname + "." + s, step.task]);
835
-
836
- for (const [where, task] of refs)
837
- if (!tasks[task]) fail(where + " references task '" + task + "' with no tasks: entry");
838
-
839
- for (const [name, def] of Object.entries(tasks)) {
840
- const seg = String(def.class_path).replace(/\\./g, "/");
841
- const candidates = [
842
- path.join(root, "src", seg + ".ts"),
843
- path.join(root, "dist", seg + ".js"),
844
- ];
845
- if (!candidates.some((c) => fs.existsSync(c)))
846
- fail("task '" + name + "' class_path '" + def.class_path + "' resolves to no src/*.ts or dist/*.js");
847
- }
848
-
849
- if (m.nativeModule?.source && !fs.existsSync(path.join(root, m.nativeModule.source)))
850
- fail("nativeModule.source '" + m.nativeModule.source + "' does not exist");
851
-
852
- if (errors) {
853
- console.error("\\n" + errors + " problem(s) found.");
854
- process.exit(1);
855
- }
856
- console.log("ue-mcp plugin check: OK");
805
+ const CHECK_SCRIPT = `#!/usr/bin/env node
806
+ // Sanity-check a ue-mcp plugin: manifest parses, task references resolve, and
807
+ // every class_path points at a real source or built file.
808
+ import fs from "node:fs";
809
+ import path from "node:path";
810
+ import yaml from "js-yaml";
811
+
812
+ const root = process.cwd();
813
+ const manifestPath = path.join(root, "ue-mcp.plugin.yml");
814
+ let errors = 0;
815
+ const fail = (m) => { console.error(" x " + m); errors++; };
816
+
817
+ if (!fs.existsSync(manifestPath)) {
818
+ console.error("ue-mcp.plugin.yml not found");
819
+ process.exit(1);
820
+ }
821
+ const m = yaml.load(fs.readFileSync(manifestPath, "utf8")) ?? {};
822
+ const tasks = m.tasks ?? {};
823
+
824
+ // Collect every task reference from inject + provides + flows.
825
+ const refs = [];
826
+ for (const [cat, actions] of Object.entries(m.inject ?? {}))
827
+ for (const [a, def] of Object.entries(actions))
828
+ if (def?.task) refs.push(["inject " + cat + "." + a, def.task]);
829
+ for (const [cat, spec] of Object.entries(m.provides ?? {}))
830
+ for (const [a, def] of Object.entries(spec?.actions ?? {}))
831
+ if (def?.task) refs.push(["provides " + cat + "." + a, def.task]);
832
+ for (const [fname, fdef] of Object.entries(m.flows ?? {}))
833
+ for (const [s, step] of Object.entries(fdef?.steps ?? {}))
834
+ if (step?.task) refs.push(["flow " + fname + "." + s, step.task]);
835
+
836
+ for (const [where, task] of refs)
837
+ if (!tasks[task]) fail(where + " references task '" + task + "' with no tasks: entry");
838
+
839
+ for (const [name, def] of Object.entries(tasks)) {
840
+ const seg = String(def.class_path).replace(/\\./g, "/");
841
+ const candidates = [
842
+ path.join(root, "src", seg + ".ts"),
843
+ path.join(root, "dist", seg + ".js"),
844
+ ];
845
+ if (!candidates.some((c) => fs.existsSync(c)))
846
+ fail("task '" + name + "' class_path '" + def.class_path + "' resolves to no src/*.ts or dist/*.js");
847
+ }
848
+
849
+ if (m.nativeModule?.source && !fs.existsSync(path.join(root, m.nativeModule.source)))
850
+ fail("nativeModule.source '" + m.nativeModule.source + "' does not exist");
851
+
852
+ if (errors) {
853
+ console.error("\\n" + errors + " problem(s) found.");
854
+ process.exit(1);
855
+ }
856
+ console.log("ue-mcp plugin check: OK");
857
857
  `;
858
858
  function uePluginEnabled(projectDir, name) {
859
859
  const files = fs.readdirSync(projectDir).filter((f) => f.endsWith(".uproject"));
@@ -31,6 +31,6 @@
31
31
  },
32
32
  "nativeToolsets": 52,
33
33
  "nativeToolActions": 830,
34
- "generatedAt": "2026-08-06T17:34:12.491Z",
35
- "version": "1.2.1"
34
+ "generatedAt": "2026-08-07T17:54:44.285Z",
35
+ "version": "1.2.2"
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ue-mcp",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Unreal Engine MCP server - 24 tools, 783+ actions for AI-driven editor control",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -89,7 +89,7 @@
89
89
  "prepare": "husky"
90
90
  },
91
91
  "dependencies": {
92
- "@db-lyon/flowkit": "~0.5.3",
92
+ "@db-lyon/flowkit": "^0.14.0",
93
93
  "@modelcontextprotocol/sdk": "^1.12.1",
94
94
  "js-yaml": "^4.1.0",
95
95
  "ws": "^8.18.0",