unreal-engine-mcp-server 0.4.7 → 0.5.0

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 (438) hide show
  1. package/.env.example +26 -0
  2. package/.env.production +38 -7
  3. package/.eslintrc.json +0 -54
  4. package/.eslintrc.override.json +8 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
  6. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
  8. package/.github/copilot-instructions.md +478 -45
  9. package/.github/dependabot.yml +19 -0
  10. package/.github/labeler.yml +24 -0
  11. package/.github/labels.yml +70 -0
  12. package/.github/pull_request_template.md +42 -0
  13. package/.github/release-drafter.yml +148 -0
  14. package/.github/workflows/auto-merge.yml +38 -0
  15. package/.github/workflows/ci.yml +38 -0
  16. package/.github/workflows/dependency-review.yml +17 -0
  17. package/.github/workflows/gemini-issue-triage.yml +172 -0
  18. package/.github/workflows/greetings.yml +23 -0
  19. package/.github/workflows/labeler.yml +16 -0
  20. package/.github/workflows/links.yml +80 -0
  21. package/.github/workflows/pr-size-labeler.yml +137 -0
  22. package/.github/workflows/publish-mcp.yml +12 -7
  23. package/.github/workflows/release-drafter.yml +23 -0
  24. package/.github/workflows/release.yml +112 -0
  25. package/.github/workflows/semantic-pull-request.yml +35 -0
  26. package/.github/workflows/smoke-test.yml +36 -0
  27. package/.github/workflows/stale.yml +28 -0
  28. package/CHANGELOG.md +267 -31
  29. package/CONTRIBUTING.md +140 -0
  30. package/README.md +166 -71
  31. package/claude_desktop_config_example.json +7 -6
  32. package/dist/automation/bridge.d.ts +50 -0
  33. package/dist/automation/bridge.js +452 -0
  34. package/dist/automation/connection-manager.d.ts +23 -0
  35. package/dist/automation/connection-manager.js +107 -0
  36. package/dist/automation/handshake.d.ts +11 -0
  37. package/dist/automation/handshake.js +89 -0
  38. package/dist/automation/index.d.ts +3 -0
  39. package/dist/automation/index.js +3 -0
  40. package/dist/automation/message-handler.d.ts +12 -0
  41. package/dist/automation/message-handler.js +149 -0
  42. package/dist/automation/request-tracker.d.ts +25 -0
  43. package/dist/automation/request-tracker.js +98 -0
  44. package/dist/automation/types.d.ts +130 -0
  45. package/dist/automation/types.js +2 -0
  46. package/dist/cli.js +32 -5
  47. package/dist/config.d.ts +27 -0
  48. package/dist/config.js +60 -0
  49. package/dist/constants.d.ts +12 -0
  50. package/dist/constants.js +12 -0
  51. package/dist/graphql/resolvers.d.ts +268 -0
  52. package/dist/graphql/resolvers.js +743 -0
  53. package/dist/graphql/schema.d.ts +5 -0
  54. package/dist/graphql/schema.js +437 -0
  55. package/dist/graphql/server.d.ts +26 -0
  56. package/dist/graphql/server.js +115 -0
  57. package/dist/graphql/types.d.ts +7 -0
  58. package/dist/graphql/types.js +2 -0
  59. package/dist/handlers/resource-handlers.d.ts +20 -0
  60. package/dist/handlers/resource-handlers.js +180 -0
  61. package/dist/index.d.ts +31 -18
  62. package/dist/index.js +119 -619
  63. package/dist/prompts/index.js +4 -4
  64. package/dist/resources/actors.d.ts +17 -12
  65. package/dist/resources/actors.js +56 -76
  66. package/dist/resources/assets.d.ts +6 -14
  67. package/dist/resources/assets.js +115 -147
  68. package/dist/resources/levels.d.ts +13 -13
  69. package/dist/resources/levels.js +25 -34
  70. package/dist/server/resource-registry.d.ts +20 -0
  71. package/dist/server/resource-registry.js +37 -0
  72. package/dist/server/tool-registry.d.ts +23 -0
  73. package/dist/server/tool-registry.js +322 -0
  74. package/dist/server-setup.d.ts +21 -0
  75. package/dist/server-setup.js +111 -0
  76. package/dist/services/health-monitor.d.ts +34 -0
  77. package/dist/services/health-monitor.js +105 -0
  78. package/dist/services/metrics-server.d.ts +11 -0
  79. package/dist/services/metrics-server.js +105 -0
  80. package/dist/tools/actors.d.ts +147 -9
  81. package/dist/tools/actors.js +350 -311
  82. package/dist/tools/animation.d.ts +135 -4
  83. package/dist/tools/animation.js +510 -411
  84. package/dist/tools/assets.d.ts +117 -19
  85. package/dist/tools/assets.js +259 -284
  86. package/dist/tools/audio.d.ts +102 -42
  87. package/dist/tools/audio.js +272 -685
  88. package/dist/tools/base-tool.d.ts +17 -0
  89. package/dist/tools/base-tool.js +46 -0
  90. package/dist/tools/behavior-tree.d.ts +94 -0
  91. package/dist/tools/behavior-tree.js +39 -0
  92. package/dist/tools/blueprint/helpers.d.ts +29 -0
  93. package/dist/tools/blueprint/helpers.js +182 -0
  94. package/dist/tools/blueprint.d.ts +228 -118
  95. package/dist/tools/blueprint.js +685 -832
  96. package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
  97. package/dist/tools/consolidated-tool-definitions.js +829 -496
  98. package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
  99. package/dist/tools/consolidated-tool-handlers.js +211 -1026
  100. package/dist/tools/debug.d.ts +143 -85
  101. package/dist/tools/debug.js +234 -180
  102. package/dist/tools/dynamic-handler-registry.d.ts +11 -0
  103. package/dist/tools/dynamic-handler-registry.js +101 -0
  104. package/dist/tools/editor.d.ts +139 -18
  105. package/dist/tools/editor.js +239 -244
  106. package/dist/tools/engine.d.ts +10 -4
  107. package/dist/tools/engine.js +13 -5
  108. package/dist/tools/environment.d.ts +36 -0
  109. package/dist/tools/environment.js +267 -0
  110. package/dist/tools/foliage.d.ts +105 -14
  111. package/dist/tools/foliage.js +219 -331
  112. package/dist/tools/handlers/actor-handlers.d.ts +3 -0
  113. package/dist/tools/handlers/actor-handlers.js +232 -0
  114. package/dist/tools/handlers/animation-handlers.d.ts +3 -0
  115. package/dist/tools/handlers/animation-handlers.js +185 -0
  116. package/dist/tools/handlers/argument-helper.d.ts +16 -0
  117. package/dist/tools/handlers/argument-helper.js +80 -0
  118. package/dist/tools/handlers/asset-handlers.d.ts +3 -0
  119. package/dist/tools/handlers/asset-handlers.js +496 -0
  120. package/dist/tools/handlers/audio-handlers.d.ts +3 -0
  121. package/dist/tools/handlers/audio-handlers.js +166 -0
  122. package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
  123. package/dist/tools/handlers/blueprint-handlers.js +358 -0
  124. package/dist/tools/handlers/common-handlers.d.ts +14 -0
  125. package/dist/tools/handlers/common-handlers.js +56 -0
  126. package/dist/tools/handlers/editor-handlers.d.ts +3 -0
  127. package/dist/tools/handlers/editor-handlers.js +119 -0
  128. package/dist/tools/handlers/effect-handlers.d.ts +3 -0
  129. package/dist/tools/handlers/effect-handlers.js +171 -0
  130. package/dist/tools/handlers/environment-handlers.d.ts +3 -0
  131. package/dist/tools/handlers/environment-handlers.js +170 -0
  132. package/dist/tools/handlers/graph-handlers.d.ts +3 -0
  133. package/dist/tools/handlers/graph-handlers.js +90 -0
  134. package/dist/tools/handlers/input-handlers.d.ts +3 -0
  135. package/dist/tools/handlers/input-handlers.js +21 -0
  136. package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
  137. package/dist/tools/handlers/inspect-handlers.js +383 -0
  138. package/dist/tools/handlers/level-handlers.d.ts +3 -0
  139. package/dist/tools/handlers/level-handlers.js +237 -0
  140. package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
  141. package/dist/tools/handlers/lighting-handlers.js +144 -0
  142. package/dist/tools/handlers/performance-handlers.d.ts +3 -0
  143. package/dist/tools/handlers/performance-handlers.js +130 -0
  144. package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
  145. package/dist/tools/handlers/pipeline-handlers.js +110 -0
  146. package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
  147. package/dist/tools/handlers/sequence-handlers.js +376 -0
  148. package/dist/tools/handlers/system-handlers.d.ts +4 -0
  149. package/dist/tools/handlers/system-handlers.js +506 -0
  150. package/dist/tools/input.d.ts +19 -0
  151. package/dist/tools/input.js +89 -0
  152. package/dist/tools/introspection.d.ts +103 -40
  153. package/dist/tools/introspection.js +425 -568
  154. package/dist/tools/landscape.d.ts +97 -36
  155. package/dist/tools/landscape.js +280 -409
  156. package/dist/tools/level.d.ts +130 -10
  157. package/dist/tools/level.js +639 -675
  158. package/dist/tools/lighting.d.ts +77 -38
  159. package/dist/tools/lighting.js +441 -943
  160. package/dist/tools/logs.d.ts +3 -3
  161. package/dist/tools/logs.js +5 -57
  162. package/dist/tools/materials.d.ts +91 -24
  163. package/dist/tools/materials.js +190 -118
  164. package/dist/tools/niagara.d.ts +149 -39
  165. package/dist/tools/niagara.js +232 -182
  166. package/dist/tools/performance.d.ts +27 -12
  167. package/dist/tools/performance.js +204 -122
  168. package/dist/tools/physics.d.ts +32 -77
  169. package/dist/tools/physics.js +171 -582
  170. package/dist/tools/property-dictionary.d.ts +13 -0
  171. package/dist/tools/property-dictionary.js +82 -0
  172. package/dist/tools/sequence.d.ts +73 -48
  173. package/dist/tools/sequence.js +196 -748
  174. package/dist/tools/tool-definition-utils.d.ts +59 -0
  175. package/dist/tools/tool-definition-utils.js +35 -0
  176. package/dist/tools/ui.d.ts +66 -34
  177. package/dist/tools/ui.js +134 -214
  178. package/dist/types/env.d.ts +0 -3
  179. package/dist/types/env.js +0 -7
  180. package/dist/types/tool-interfaces.d.ts +898 -0
  181. package/dist/types/tool-interfaces.js +2 -0
  182. package/dist/types/tool-types.d.ts +183 -19
  183. package/dist/types/tool-types.js +0 -4
  184. package/dist/unreal-bridge.d.ts +24 -131
  185. package/dist/unreal-bridge.js +364 -1506
  186. package/dist/utils/command-validator.d.ts +9 -0
  187. package/dist/utils/command-validator.js +67 -0
  188. package/dist/utils/elicitation.d.ts +1 -1
  189. package/dist/utils/elicitation.js +12 -15
  190. package/dist/utils/error-handler.d.ts +2 -51
  191. package/dist/utils/error-handler.js +11 -87
  192. package/dist/utils/ini-reader.d.ts +3 -0
  193. package/dist/utils/ini-reader.js +69 -0
  194. package/dist/utils/logger.js +9 -6
  195. package/dist/utils/normalize.d.ts +3 -0
  196. package/dist/utils/normalize.js +56 -0
  197. package/dist/utils/response-factory.d.ts +7 -0
  198. package/dist/utils/response-factory.js +33 -0
  199. package/dist/utils/response-validator.d.ts +3 -24
  200. package/dist/utils/response-validator.js +130 -81
  201. package/dist/utils/result-helpers.d.ts +4 -5
  202. package/dist/utils/result-helpers.js +15 -16
  203. package/dist/utils/safe-json.js +5 -11
  204. package/dist/utils/unreal-command-queue.d.ts +24 -0
  205. package/dist/utils/unreal-command-queue.js +120 -0
  206. package/dist/utils/validation.d.ts +0 -40
  207. package/dist/utils/validation.js +1 -78
  208. package/dist/wasm/index.d.ts +70 -0
  209. package/dist/wasm/index.js +535 -0
  210. package/docs/GraphQL-API.md +888 -0
  211. package/docs/Migration-Guide-v0.5.0.md +692 -0
  212. package/docs/Roadmap.md +53 -0
  213. package/docs/WebAssembly-Integration.md +628 -0
  214. package/docs/editor-plugin-extension.md +370 -0
  215. package/docs/handler-mapping.md +242 -0
  216. package/docs/native-automation-progress.md +128 -0
  217. package/docs/testing-guide.md +423 -0
  218. package/mcp-config-example.json +6 -6
  219. package/package.json +60 -27
  220. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
  221. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
  222. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
  223. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
  224. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
  225. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
  226. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
  227. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
  228. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
  229. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
  230. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
  231. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
  232. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
  233. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
  234. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
  235. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
  236. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
  237. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
  238. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
  239. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
  240. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
  241. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
  242. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
  243. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
  244. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
  245. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
  246. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
  247. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
  248. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
  249. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
  250. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
  251. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
  252. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
  253. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
  254. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
  255. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
  256. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
  257. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
  258. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
  259. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
  260. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
  261. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
  262. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
  263. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
  264. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
  265. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
  266. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
  267. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
  268. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
  269. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
  270. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
  271. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
  272. package/scripts/check-unreal-connection.mjs +19 -0
  273. package/scripts/clean-tmp.js +23 -0
  274. package/scripts/patch-wasm.js +26 -0
  275. package/scripts/run-all-tests.mjs +131 -0
  276. package/scripts/smoke-test.ts +94 -0
  277. package/scripts/sync-mcp-plugin.js +143 -0
  278. package/scripts/test-no-plugin-alternates.mjs +113 -0
  279. package/scripts/validate-server.js +46 -0
  280. package/scripts/verify-automation-bridge.js +200 -0
  281. package/server.json +57 -21
  282. package/src/automation/bridge.ts +558 -0
  283. package/src/automation/connection-manager.ts +130 -0
  284. package/src/automation/handshake.ts +99 -0
  285. package/src/automation/index.ts +2 -0
  286. package/src/automation/message-handler.ts +167 -0
  287. package/src/automation/request-tracker.ts +123 -0
  288. package/src/automation/types.ts +107 -0
  289. package/src/cli.ts +33 -6
  290. package/src/config.ts +73 -0
  291. package/src/constants.ts +12 -0
  292. package/src/graphql/resolvers.ts +1010 -0
  293. package/src/graphql/schema.ts +452 -0
  294. package/src/graphql/server.ts +154 -0
  295. package/src/graphql/types.ts +7 -0
  296. package/src/handlers/resource-handlers.ts +186 -0
  297. package/src/index.ts +152 -663
  298. package/src/prompts/index.ts +4 -4
  299. package/src/resources/actors.ts +58 -76
  300. package/src/resources/assets.ts +147 -134
  301. package/src/resources/levels.ts +28 -33
  302. package/src/server/resource-registry.ts +47 -0
  303. package/src/server/tool-registry.ts +354 -0
  304. package/src/server-setup.ts +148 -0
  305. package/src/services/health-monitor.ts +132 -0
  306. package/src/services/metrics-server.ts +142 -0
  307. package/src/tools/actors.ts +417 -322
  308. package/src/tools/animation.ts +671 -461
  309. package/src/tools/assets.ts +353 -289
  310. package/src/tools/audio.ts +323 -766
  311. package/src/tools/base-tool.ts +52 -0
  312. package/src/tools/behavior-tree.ts +45 -0
  313. package/src/tools/blueprint/helpers.ts +189 -0
  314. package/src/tools/blueprint.ts +787 -965
  315. package/src/tools/consolidated-tool-definitions.ts +993 -515
  316. package/src/tools/consolidated-tool-handlers.ts +272 -1139
  317. package/src/tools/debug.ts +292 -187
  318. package/src/tools/dynamic-handler-registry.ts +151 -0
  319. package/src/tools/editor.ts +309 -246
  320. package/src/tools/engine.ts +14 -3
  321. package/src/tools/environment.ts +287 -0
  322. package/src/tools/foliage.ts +314 -379
  323. package/src/tools/handlers/actor-handlers.ts +271 -0
  324. package/src/tools/handlers/animation-handlers.ts +237 -0
  325. package/src/tools/handlers/argument-helper.ts +142 -0
  326. package/src/tools/handlers/asset-handlers.ts +532 -0
  327. package/src/tools/handlers/audio-handlers.ts +194 -0
  328. package/src/tools/handlers/blueprint-handlers.ts +380 -0
  329. package/src/tools/handlers/common-handlers.ts +87 -0
  330. package/src/tools/handlers/editor-handlers.ts +123 -0
  331. package/src/tools/handlers/effect-handlers.ts +220 -0
  332. package/src/tools/handlers/environment-handlers.ts +183 -0
  333. package/src/tools/handlers/graph-handlers.ts +116 -0
  334. package/src/tools/handlers/input-handlers.ts +28 -0
  335. package/src/tools/handlers/inspect-handlers.ts +450 -0
  336. package/src/tools/handlers/level-handlers.ts +252 -0
  337. package/src/tools/handlers/lighting-handlers.ts +147 -0
  338. package/src/tools/handlers/performance-handlers.ts +132 -0
  339. package/src/tools/handlers/pipeline-handlers.ts +127 -0
  340. package/src/tools/handlers/sequence-handlers.ts +415 -0
  341. package/src/tools/handlers/system-handlers.ts +564 -0
  342. package/src/tools/input.ts +101 -0
  343. package/src/tools/introspection.ts +493 -584
  344. package/src/tools/landscape.ts +394 -489
  345. package/src/tools/level.ts +752 -694
  346. package/src/tools/lighting.ts +583 -984
  347. package/src/tools/logs.ts +9 -57
  348. package/src/tools/materials.ts +231 -121
  349. package/src/tools/niagara.ts +293 -168
  350. package/src/tools/performance.ts +320 -168
  351. package/src/tools/physics.ts +268 -613
  352. package/src/tools/property-dictionary.ts +98 -0
  353. package/src/tools/sequence.ts +255 -815
  354. package/src/tools/tool-definition-utils.ts +35 -0
  355. package/src/tools/ui.ts +207 -283
  356. package/src/types/env.ts +0 -10
  357. package/src/types/tool-interfaces.ts +250 -0
  358. package/src/types/tool-types.ts +243 -21
  359. package/src/unreal-bridge.ts +460 -1550
  360. package/src/utils/command-validator.ts +75 -0
  361. package/src/utils/elicitation.ts +10 -7
  362. package/src/utils/error-handler.ts +14 -90
  363. package/src/utils/ini-reader.ts +86 -0
  364. package/src/utils/logger.ts +8 -3
  365. package/src/utils/normalize.ts +60 -0
  366. package/src/utils/response-factory.ts +39 -0
  367. package/src/utils/response-validator.ts +176 -56
  368. package/src/utils/result-helpers.ts +21 -19
  369. package/src/utils/safe-json.ts +14 -11
  370. package/src/utils/unreal-command-queue.ts +152 -0
  371. package/src/utils/validation.ts +4 -1
  372. package/src/wasm/index.ts +838 -0
  373. package/test-server.mjs +100 -0
  374. package/tests/run-unreal-tool-tests.mjs +242 -14
  375. package/tests/test-animation.mjs +44 -0
  376. package/tests/test-asset-advanced.mjs +82 -0
  377. package/tests/test-asset-errors.mjs +35 -0
  378. package/tests/test-audio.mjs +219 -0
  379. package/tests/test-automation-timeouts.mjs +98 -0
  380. package/tests/test-behavior-tree.mjs +261 -0
  381. package/tests/test-blueprint-events.mjs +35 -0
  382. package/tests/test-blueprint-graph.mjs +79 -0
  383. package/tests/test-blueprint.mjs +577 -0
  384. package/tests/test-client-mode.mjs +86 -0
  385. package/tests/test-console-command.mjs +56 -0
  386. package/tests/test-control-actor.mjs +425 -0
  387. package/tests/test-control-editor.mjs +80 -0
  388. package/tests/test-extra-tools.mjs +38 -0
  389. package/tests/test-graphql.mjs +322 -0
  390. package/tests/test-inspect.mjs +72 -0
  391. package/tests/test-landscape.mjs +60 -0
  392. package/tests/test-manage-asset.mjs +438 -0
  393. package/tests/test-manage-level.mjs +70 -0
  394. package/tests/test-materials.mjs +356 -0
  395. package/tests/test-niagara.mjs +185 -0
  396. package/tests/test-no-inline-python.mjs +122 -0
  397. package/tests/test-plugin-handshake.mjs +82 -0
  398. package/tests/test-render.mjs +33 -0
  399. package/tests/test-runner.mjs +933 -0
  400. package/tests/test-search-assets.mjs +66 -0
  401. package/tests/test-sequence.mjs +68 -0
  402. package/tests/test-system.mjs +57 -0
  403. package/tests/test-wasm.mjs +193 -0
  404. package/tests/test-world-partition.mjs +215 -0
  405. package/tsconfig.json +3 -3
  406. package/wasm/Cargo.lock +363 -0
  407. package/wasm/Cargo.toml +42 -0
  408. package/wasm/LICENSE +21 -0
  409. package/wasm/README.md +253 -0
  410. package/wasm/src/dependency_resolver.rs +377 -0
  411. package/wasm/src/lib.rs +153 -0
  412. package/wasm/src/property_parser.rs +271 -0
  413. package/wasm/src/transform_math.rs +396 -0
  414. package/wasm/tests/integration.rs +109 -0
  415. package/.github/workflows/smithery-build.yml +0 -29
  416. package/dist/tools/build_environment_advanced.d.ts +0 -65
  417. package/dist/tools/build_environment_advanced.js +0 -633
  418. package/dist/tools/rc.d.ts +0 -110
  419. package/dist/tools/rc.js +0 -437
  420. package/dist/tools/visual.d.ts +0 -40
  421. package/dist/tools/visual.js +0 -282
  422. package/dist/utils/http.d.ts +0 -6
  423. package/dist/utils/http.js +0 -151
  424. package/dist/utils/python-output.d.ts +0 -18
  425. package/dist/utils/python-output.js +0 -290
  426. package/dist/utils/python.d.ts +0 -2
  427. package/dist/utils/python.js +0 -4
  428. package/dist/utils/stdio-redirect.d.ts +0 -2
  429. package/dist/utils/stdio-redirect.js +0 -20
  430. package/docs/unreal-tool-test-cases.md +0 -574
  431. package/smithery.yaml +0 -29
  432. package/src/tools/build_environment_advanced.ts +0 -732
  433. package/src/tools/rc.ts +0 -515
  434. package/src/tools/visual.ts +0 -281
  435. package/src/utils/http.ts +0 -187
  436. package/src/utils/python-output.ts +0 -351
  437. package/src/utils/python.ts +0 -3
  438. package/src/utils/stdio-redirect.ts +0 -18
@@ -0,0 +1,401 @@
1
+ #include "McpAutomationBridgeGlobals.h"
2
+ #include "McpAutomationBridgeHelpers.h"
3
+ #include "McpAutomationBridgeSubsystem.h"
4
+
5
+
6
+ #if WITH_EDITOR
7
+ #include "Editor/UnrealEd/Public/Editor.h"
8
+ #include "EngineUtils.h"
9
+ #include "HAL/FileManager.h"
10
+ #include "IMergeActorsModule.h"
11
+ #include "IMergeActorsTool.h"
12
+ #include "Kismet/GameplayStatics.h"
13
+ #include "LevelEditor.h"
14
+ #include "ProfilingDebugging/ScopedTimers.h"
15
+ #include "Subsystems/EditorActorSubsystem.h"
16
+
17
+ #endif
18
+
19
+ bool UMcpAutomationBridgeSubsystem::HandlePerformanceAction(
20
+ const FString &RequestId, const FString &Action,
21
+ const TSharedPtr<FJsonObject> &Payload,
22
+ TSharedPtr<FMcpBridgeWebSocket> RequestingSocket) {
23
+ const FString Lower = Action.ToLower();
24
+ if (!Lower.StartsWith(TEXT("generate_memory_report")) &&
25
+ !Lower.StartsWith(TEXT("configure_texture_streaming")) &&
26
+ !Lower.StartsWith(TEXT("merge_actors")) &&
27
+ !Lower.StartsWith(TEXT("start_profiling")) &&
28
+ !Lower.StartsWith(TEXT("stop_profiling")) &&
29
+ !Lower.StartsWith(TEXT("show_fps")) &&
30
+ !Lower.StartsWith(TEXT("show_stats")) &&
31
+ !Lower.StartsWith(TEXT("set_scalability")) &&
32
+ !Lower.StartsWith(TEXT("set_resolution_scale")) &&
33
+ !Lower.StartsWith(TEXT("set_vsync")) &&
34
+ !Lower.StartsWith(TEXT("set_frame_rate_limit")) &&
35
+ !Lower.StartsWith(TEXT("configure_nanite")) &&
36
+ !Lower.StartsWith(TEXT("configure_lod"))) {
37
+ return false;
38
+ }
39
+
40
+ #if WITH_EDITOR
41
+ if (!Payload.IsValid()) {
42
+ SendAutomationError(RequestingSocket, RequestId,
43
+ TEXT("Performance payload missing"),
44
+ TEXT("INVALID_PAYLOAD"));
45
+ return true;
46
+ }
47
+
48
+ if (Lower == TEXT("generate_memory_report")) {
49
+ bool bDetailed = false;
50
+ Payload->TryGetBoolField(TEXT("detailed"), bDetailed);
51
+
52
+ FString OutputPath;
53
+ Payload->TryGetStringField(TEXT("outputPath"), OutputPath);
54
+
55
+ // Execute memreport command
56
+ FString Cmd = bDetailed ? TEXT("memreport -full") : TEXT("memreport");
57
+ GEngine->Exec(GEditor->GetEditorWorldContext().World(), *Cmd);
58
+
59
+ // If output path provided, we might want to move the log file, but
60
+ // memreport writes to a specific location. For now, just acknowledge
61
+ // execution.
62
+
63
+ SendAutomationResponse(RequestingSocket, RequestId, true,
64
+ TEXT("Memory report generated"), nullptr);
65
+ return true;
66
+ } else if (Lower == TEXT("start_profiling")) {
67
+ // "stat startfile"
68
+ GEngine->Exec(GEditor->GetEditorWorldContext().World(),
69
+ TEXT("stat startfile"));
70
+ SendAutomationResponse(RequestingSocket, RequestId, true,
71
+ TEXT("Profiling started"), nullptr);
72
+ return true;
73
+ } else if (Lower == TEXT("stop_profiling")) {
74
+ // "stat stopfile"
75
+ GEngine->Exec(GEditor->GetEditorWorldContext().World(),
76
+ TEXT("stat stopfile"));
77
+ SendAutomationResponse(RequestingSocket, RequestId, true,
78
+ TEXT("Profiling stopped"), nullptr);
79
+ return true;
80
+ } else if (Lower == TEXT("show_fps")) {
81
+ bool bEnabled = true;
82
+ Payload->TryGetBoolField(TEXT("enabled"), bEnabled);
83
+ FString Cmd = bEnabled ? TEXT("stat fps") : TEXT("stat none");
84
+ // Note: "stat fps" toggles, so we might need check, but mostly users just
85
+ // want to run the command. For explicit set, we can use "stat fps 1" or
86
+ // "stat fps 0" if supported, but typically it's a toggle. Better: use
87
+ // GAreyouSure? No, just exec.
88
+ GEngine->Exec(GEditor->GetEditorWorldContext().World(), TEXT("stat fps"));
89
+ SendAutomationResponse(RequestingSocket, RequestId, true,
90
+ TEXT("FPS stat toggled"), nullptr);
91
+ return true;
92
+ } else if (Lower == TEXT("show_stats")) {
93
+ FString Category;
94
+ if (Payload->TryGetStringField(TEXT("category"), Category) &&
95
+ !Category.IsEmpty()) {
96
+ GEngine->Exec(GEditor->GetEditorWorldContext().World(),
97
+ *FString::Printf(TEXT("stat %s"), *Category));
98
+ SendAutomationResponse(
99
+ RequestingSocket, RequestId, true,
100
+ FString::Printf(TEXT("Stat '%s' toggled"), *Category), nullptr);
101
+ } else {
102
+ SendAutomationResponse(RequestingSocket, RequestId, false,
103
+ TEXT("Category required"), nullptr,
104
+ TEXT("INVALID_ARGUMENT"));
105
+ }
106
+ return true;
107
+ } else if (Lower == TEXT("set_scalability")) {
108
+ int32 Level = 3; // Epic
109
+ Payload->TryGetNumberField(TEXT("level"), Level);
110
+
111
+ // simple batch scalability
112
+ Scalability::FQualityLevels Quals;
113
+ Quals.SetFromSingleQualityLevel(Level);
114
+ Scalability::SetQualityLevels(Quals);
115
+ Scalability::SaveState(GEditorIni);
116
+
117
+ SendAutomationResponse(RequestingSocket, RequestId, true,
118
+ TEXT("Scalability set"), nullptr);
119
+ return true;
120
+ } else if (Lower == TEXT("set_resolution_scale")) {
121
+ double Scale = 100.0;
122
+ if (Payload->TryGetNumberField(TEXT("scale"), Scale)) {
123
+ IConsoleVariable *CVar = IConsoleManager::Get().FindConsoleVariable(
124
+ TEXT("r.ScreenPercentage"));
125
+ if (CVar)
126
+ CVar->Set((float)Scale);
127
+ SendAutomationResponse(RequestingSocket, RequestId, true,
128
+ TEXT("Resolution scale set"), nullptr);
129
+ } else {
130
+ SendAutomationResponse(RequestingSocket, RequestId, false,
131
+ TEXT("Scale required"), nullptr,
132
+ TEXT("INVALID_ARGUMENT"));
133
+ }
134
+ return true;
135
+ } else if (Lower == TEXT("set_vsync")) {
136
+ bool bEnabled = true;
137
+ Payload->TryGetBoolField(TEXT("enabled"), bEnabled);
138
+ IConsoleVariable *CVar =
139
+ IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
140
+ if (CVar)
141
+ CVar->Set(bEnabled ? 1 : 0);
142
+ SendAutomationResponse(RequestingSocket, RequestId, true,
143
+ TEXT("VSync configured"), nullptr);
144
+ return true;
145
+ } else if (Lower == TEXT("set_frame_rate_limit")) {
146
+ double Limit = 0.0;
147
+ if (Payload->TryGetNumberField(TEXT("maxFPS"), Limit)) {
148
+ GEngine->SetMaxFPS((float)Limit);
149
+ SendAutomationResponse(RequestingSocket, RequestId, true,
150
+ TEXT("Max FPS set"), nullptr);
151
+ } else {
152
+ SendAutomationResponse(RequestingSocket, RequestId, false,
153
+ TEXT("maxFPS required"), nullptr,
154
+ TEXT("INVALID_ARGUMENT"));
155
+ }
156
+ return true;
157
+ } else if (Lower == TEXT("configure_nanite")) {
158
+ bool bEnabled = true;
159
+ Payload->TryGetBoolField(TEXT("enabled"), bEnabled);
160
+ IConsoleVariable *CVar =
161
+ IConsoleManager::Get().FindConsoleVariable(TEXT("r.Nanite"));
162
+ if (CVar)
163
+ CVar->Set(bEnabled ? 1 : 0);
164
+ SendAutomationResponse(RequestingSocket, RequestId, true,
165
+ TEXT("Nanite configured"), nullptr);
166
+ return true;
167
+ } else if (Lower == TEXT("configure_lod")) {
168
+ double LODBias = 0.0;
169
+ if (Payload->TryGetNumberField(TEXT("lodBias"), LODBias)) {
170
+ IConsoleVariable *CVar =
171
+ IConsoleManager::Get().FindConsoleVariable(TEXT("r.MipMapLODBias"));
172
+ if (CVar)
173
+ CVar->Set((float)LODBias);
174
+ }
175
+
176
+ double ForceLOD = -1.0;
177
+ if (Payload->TryGetNumberField(TEXT("forceLOD"), ForceLOD)) {
178
+ IConsoleVariable *CVar =
179
+ IConsoleManager::Get().FindConsoleVariable(TEXT("r.ForceLOD"));
180
+ if (CVar)
181
+ CVar->Set((int32)ForceLOD);
182
+ }
183
+
184
+ SendAutomationResponse(RequestingSocket, RequestId, true,
185
+ TEXT("LOD settings configured"), nullptr);
186
+ return true;
187
+ } else if (Lower == TEXT("configure_texture_streaming")) {
188
+ bool bEnabled = true;
189
+ Payload->TryGetBoolField(TEXT("enabled"), bEnabled);
190
+
191
+ double PoolSize = 0;
192
+ if (Payload->TryGetNumberField(TEXT("poolSize"), PoolSize)) {
193
+ IConsoleVariable *CVar = IConsoleManager::Get().FindConsoleVariable(
194
+ TEXT("r.Streaming.PoolSize"));
195
+ if (CVar)
196
+ CVar->Set((float)PoolSize);
197
+ }
198
+
199
+ bool bBoost = false;
200
+ if (Payload->TryGetBoolField(TEXT("boostPlayerLocation"), bBoost) &&
201
+ bBoost) {
202
+ // Logic to boost streaming around player
203
+ if (GEditor && GEditor->GetEditorWorldContext().World()) {
204
+ APlayerCameraManager *Cam = UGameplayStatics::GetPlayerCameraManager(
205
+ GEditor->GetEditorWorldContext().World(), 0);
206
+ if (Cam) {
207
+ IStreamingManager::Get().AddViewLocation(Cam->GetCameraLocation());
208
+ }
209
+ }
210
+ }
211
+
212
+ IConsoleVariable *CVarStream =
213
+ IConsoleManager::Get().FindConsoleVariable(TEXT("r.TextureStreaming"));
214
+ if (CVarStream)
215
+ CVarStream->Set(bEnabled ? 1 : 0);
216
+
217
+ SendAutomationResponse(RequestingSocket, RequestId, true,
218
+ TEXT("Texture streaming configured"), nullptr);
219
+ return true;
220
+ } else if (Lower == TEXT("merge_actors")) {
221
+ // merge_actors: drive the editor's Merge Actors tools by selecting the
222
+ // requested actors in the current editor world and invoking
223
+ // IMergeActorsTool::RunMergeFromSelection(). This relies on the
224
+ // MergeActors module and registered tools, but never reports success
225
+ // unless a real merge was requested and executed.
226
+
227
+ const TArray<TSharedPtr<FJsonValue>> *NamesArray = nullptr;
228
+ if (!Payload->TryGetArrayField(TEXT("actors"), NamesArray) || !NamesArray ||
229
+ NamesArray->Num() < 2) {
230
+ SendAutomationResponse(RequestingSocket, RequestId, false,
231
+ TEXT("merge_actors requires an 'actors' array "
232
+ "with at least 2 entries"),
233
+ nullptr, TEXT("INVALID_ARGUMENT"));
234
+ return true;
235
+ }
236
+
237
+ if (!GEditor || !GEditor->GetEditorWorldContext().World()) {
238
+ SendAutomationResponse(
239
+ RequestingSocket, RequestId, false,
240
+ TEXT("Editor world not available for merge_actors"), nullptr,
241
+ TEXT("EDITOR_NOT_AVAILABLE"));
242
+ return true;
243
+ }
244
+
245
+ UWorld *World = GEditor->GetEditorWorldContext().World();
246
+ TArray<AActor *> ActorsToMerge;
247
+
248
+ auto ResolveActorByName = [World](const FString &Name) -> AActor * {
249
+ if (Name.IsEmpty()) {
250
+ return nullptr;
251
+ }
252
+
253
+ // Try to resolve by full object path first
254
+ if (AActor *ByPath = FindObject<AActor>(nullptr, *Name)) {
255
+ return ByPath;
256
+ }
257
+
258
+ // Fallback: search the current editor world by label and by name
259
+ for (TActorIterator<AActor> It(World); It; ++It) {
260
+ AActor *Actor = *It;
261
+ if (!Actor) {
262
+ continue;
263
+ }
264
+
265
+ const FString Label = Actor->GetActorLabel();
266
+ const FString ObjName = Actor->GetName();
267
+ if (Label.Equals(Name, ESearchCase::IgnoreCase) ||
268
+ ObjName.Equals(Name, ESearchCase::IgnoreCase)) {
269
+ return Actor;
270
+ }
271
+ }
272
+
273
+ return nullptr;
274
+ };
275
+
276
+ for (const TSharedPtr<FJsonValue> &Val : *NamesArray) {
277
+ if (!Val.IsValid() || Val->Type != EJson::String) {
278
+ continue;
279
+ }
280
+
281
+ const FString RawName = Val->AsString().TrimStartAndEnd();
282
+ if (RawName.IsEmpty()) {
283
+ continue;
284
+ }
285
+
286
+ if (AActor *Resolved = ResolveActorByName(RawName)) {
287
+ ActorsToMerge.AddUnique(Resolved);
288
+ }
289
+ }
290
+
291
+ if (ActorsToMerge.Num() < 2) {
292
+ SendAutomationResponse(
293
+ RequestingSocket, RequestId, false,
294
+ TEXT("merge_actors resolved fewer than 2 valid actors"), nullptr,
295
+ TEXT("INVALID_ARGUMENT"));
296
+ return true;
297
+ }
298
+
299
+ // Prepare selection for the Merge Actors tool
300
+ GEditor->SelectNone(true, true, false);
301
+ for (AActor *Actor : ActorsToMerge) {
302
+ if (Actor) {
303
+ GEditor->SelectActor(Actor, true, true, true);
304
+ }
305
+ }
306
+
307
+ IMergeActorsModule &MergeModule = IMergeActorsModule::Get();
308
+ TArray<IMergeActorsTool *> Tools;
309
+ MergeModule.GetRegisteredMergeActorsTools(Tools);
310
+
311
+ if (Tools.Num() == 0) {
312
+ SendAutomationResponse(
313
+ RequestingSocket, RequestId, false,
314
+ TEXT("No Merge Actors tools are registered in this editor"), nullptr,
315
+ TEXT("MERGE_TOOL_MISSING"));
316
+ return true;
317
+ }
318
+
319
+ FString RequestedToolName;
320
+ Payload->TryGetStringField(TEXT("toolName"), RequestedToolName);
321
+ IMergeActorsTool *ChosenTool = nullptr;
322
+
323
+ // Prefer a tool whose display name matches the requested toolName
324
+ if (!RequestedToolName.IsEmpty()) {
325
+ for (IMergeActorsTool *Tool : Tools) {
326
+ if (!Tool) {
327
+ continue;
328
+ }
329
+
330
+ const FText ToolNameText = Tool->GetToolNameText();
331
+ if (ToolNameText.ToString().Equals(RequestedToolName,
332
+ ESearchCase::IgnoreCase)) {
333
+ ChosenTool = Tool;
334
+ break;
335
+ }
336
+ }
337
+ }
338
+
339
+ // Fallback: first tool that can merge from the current selection
340
+ if (!ChosenTool) {
341
+ for (IMergeActorsTool *Tool : Tools) {
342
+ if (Tool && Tool->CanMergeFromSelection()) {
343
+ ChosenTool = Tool;
344
+ break;
345
+ }
346
+ }
347
+ }
348
+
349
+ if (!ChosenTool) {
350
+ SendAutomationResponse(
351
+ RequestingSocket, RequestId, false,
352
+ TEXT("No Merge Actors tool can operate on the current selection"),
353
+ nullptr, TEXT("MERGE_TOOL_UNAVAILABLE"));
354
+ return true;
355
+ }
356
+
357
+ bool bReplaceSources = false;
358
+ if (Payload->TryGetBoolField(TEXT("replaceSourceActors"),
359
+ bReplaceSources)) {
360
+ ChosenTool->SetReplaceSourceActors(bReplaceSources);
361
+ }
362
+
363
+ if (!ChosenTool->CanMergeFromSelection()) {
364
+ SendAutomationResponse(
365
+ RequestingSocket, RequestId, false,
366
+ TEXT("Merge operation is not valid for the current selection"),
367
+ nullptr, TEXT("MERGE_NOT_POSSIBLE"));
368
+ return true;
369
+ }
370
+
371
+ const FString DefaultPackageName = ChosenTool->GetDefaultPackageName();
372
+ const bool bMerged = ChosenTool->RunMergeFromSelection();
373
+ if (!bMerged) {
374
+ SendAutomationResponse(RequestingSocket, RequestId, false,
375
+ TEXT("Actor merge operation failed"), nullptr,
376
+ TEXT("MERGE_FAILED"));
377
+ return true;
378
+ }
379
+
380
+ TSharedPtr<FJsonObject> Resp = MakeShared<FJsonObject>();
381
+ Resp->SetNumberField(TEXT("mergedActorCount"), ActorsToMerge.Num());
382
+ Resp->SetBoolField(TEXT("replaceSourceActors"),
383
+ ChosenTool->GetReplaceSourceActors());
384
+ if (!DefaultPackageName.IsEmpty()) {
385
+ Resp->SetStringField(TEXT("defaultPackageName"), DefaultPackageName);
386
+ }
387
+
388
+ SendAutomationResponse(RequestingSocket, RequestId, true,
389
+ TEXT("Actors merged using Merge Actors tool"), Resp,
390
+ FString());
391
+ return true;
392
+ }
393
+
394
+ return false;
395
+ #else
396
+ SendAutomationResponse(RequestingSocket, RequestId, false,
397
+ TEXT("Performance actions require editor build"),
398
+ nullptr, TEXT("NOT_IMPLEMENTED"));
399
+ return true;
400
+ #endif
401
+ }
@@ -0,0 +1,67 @@
1
+ #include "McpAutomationBridgeSubsystem.h"
2
+ #include "McpAutomationBridgeHelpers.h"
3
+ #include "McpAutomationBridgeGlobals.h"
4
+ #include "HAL/PlatformProcess.h"
5
+ #include "Misc/Paths.h"
6
+
7
+ bool UMcpAutomationBridgeSubsystem::HandlePipelineAction(const FString& RequestId, const FString& Action, const TSharedPtr<FJsonObject>& Payload, TSharedPtr<FMcpBridgeWebSocket> RequestingSocket)
8
+ {
9
+ if (Action != TEXT("manage_pipeline"))
10
+ {
11
+ return false;
12
+ }
13
+
14
+ if (!Payload.IsValid())
15
+ {
16
+ SendAutomationError(RequestingSocket, RequestId, TEXT("Missing payload."), TEXT("INVALID_PAYLOAD"));
17
+ return true;
18
+ }
19
+
20
+ FString SubAction = Payload->GetStringField(TEXT("subAction"));
21
+
22
+ if (SubAction == TEXT("run_ubt"))
23
+ {
24
+ FString Target;
25
+ Payload->TryGetStringField(TEXT("target"), Target);
26
+ FString Platform;
27
+ Payload->TryGetStringField(TEXT("platform"), Platform);
28
+ FString Configuration;
29
+ Payload->TryGetStringField(TEXT("configuration"), Configuration);
30
+ FString ExtraArgs;
31
+ Payload->TryGetStringField(TEXT("extraArgs"), ExtraArgs);
32
+
33
+ // Construct UBT command line
34
+ // Path to UBT... usually in Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe
35
+ FString UBTPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe"));
36
+
37
+ FString Params = FString::Printf(TEXT("%s %s %s %s"), *Target, *Platform, *Configuration, *ExtraArgs);
38
+
39
+ // Spawn process
40
+ FProcHandle ProcHandle = FPlatformProcess::CreateProc(
41
+ *UBTPath,
42
+ *Params,
43
+ true, // bLaunchDetached
44
+ false, // bLaunchHidden
45
+ false, // bLaunchReallyHidden
46
+ nullptr, // ProcessID
47
+ 0, // PriorityModifier
48
+ nullptr, // OptionalWorkingDirectory
49
+ nullptr // PipeWriteChild
50
+ );
51
+
52
+ if (ProcHandle.IsValid())
53
+ {
54
+ // We can't easily get the PID on all platforms from the handle immediately without more code,
55
+ // but we know it started.
56
+ SendAutomationResponse(RequestingSocket, RequestId, true, TEXT("UBT process started."));
57
+ }
58
+ else
59
+ {
60
+ SendAutomationError(RequestingSocket, RequestId, TEXT("Failed to launch UBT."), TEXT("LAUNCH_FAILED"));
61
+ }
62
+ return true;
63
+ }
64
+
65
+ SendAutomationError(RequestingSocket, RequestId, TEXT("Unknown subAction."), TEXT("INVALID_SUBACTION"));
66
+ return true;
67
+ }