unreal-engine-mcp-server 0.4.6 → 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 +269 -22
  29. package/CONTRIBUTING.md +140 -0
  30. package/README.md +166 -72
  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 -604
  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 +5475 -1627
  97. package/dist/tools/consolidated-tool-definitions.js +829 -482
  98. package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
  99. package/dist/tools/consolidated-tool-handlers.js +211 -1009
  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 +45 -0
  161. package/dist/tools/logs.js +210 -0
  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 +195 -11
  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 -649
  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 -500
  316. package/src/tools/consolidated-tool-handlers.ts +272 -1122
  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 +219 -0
  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 +250 -13
  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 -572
  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,9 @@
1
+ export declare class CommandValidator {
2
+ private static readonly DANGEROUS_COMMANDS;
3
+ private static readonly FORBIDDEN_TOKENS;
4
+ private static readonly INVALID_PATTERNS;
5
+ static validate(command: string): void;
6
+ static isLikelyInvalid(command: string): boolean;
7
+ static getPriority(command: string): number;
8
+ }
9
+ //# sourceMappingURL=command-validator.d.ts.map
@@ -0,0 +1,67 @@
1
+ export class CommandValidator {
2
+ static DANGEROUS_COMMANDS = [
3
+ 'quit', 'exit', 'delete', 'destroy', 'kill', 'crash',
4
+ 'viewmode visualizebuffer basecolor',
5
+ 'viewmode visualizebuffer worldnormal',
6
+ 'r.gpucrash',
7
+ 'buildpaths',
8
+ 'rebuildnavigation'
9
+ ];
10
+ static FORBIDDEN_TOKENS = [
11
+ 'rm ', 'rm-', 'del ', 'format ', 'shutdown', 'reboot',
12
+ 'rmdir', 'mklink', 'copy ', 'move ', 'start "', 'system(',
13
+ 'import os', 'import subprocess', 'subprocess.', 'os.system',
14
+ 'exec(', 'eval(', '__import__', 'import sys', 'import importlib',
15
+ 'with open', 'open('
16
+ ];
17
+ static INVALID_PATTERNS = [
18
+ /^\d+$/,
19
+ /^invalid_command/i,
20
+ /^this_is_not_a_valid/i,
21
+ ];
22
+ static validate(command) {
23
+ if (!command || typeof command !== 'string') {
24
+ throw new Error('Invalid command: must be a non-empty string');
25
+ }
26
+ const cmdTrimmed = command.trim();
27
+ if (cmdTrimmed.length === 0) {
28
+ return;
29
+ }
30
+ if (cmdTrimmed.includes('\n') || cmdTrimmed.includes('\r')) {
31
+ throw new Error('Multi-line console commands are not allowed. Send one command per call.');
32
+ }
33
+ const cmdLower = cmdTrimmed.toLowerCase();
34
+ if (cmdLower === 'py' || cmdLower.startsWith('py ')) {
35
+ throw new Error('Python console commands are blocked from external calls for safety.');
36
+ }
37
+ if (this.DANGEROUS_COMMANDS.some(dangerous => cmdLower.includes(dangerous))) {
38
+ throw new Error(`Dangerous command blocked: ${command}`);
39
+ }
40
+ if (cmdLower.includes('&&') || cmdLower.includes('||')) {
41
+ throw new Error('Command chaining with && or || is blocked for safety.');
42
+ }
43
+ if (this.FORBIDDEN_TOKENS.some(token => cmdLower.includes(token))) {
44
+ throw new Error(`Command contains unsafe token and was blocked: ${command}`);
45
+ }
46
+ }
47
+ static isLikelyInvalid(command) {
48
+ const cmdTrimmed = command.trim();
49
+ return this.INVALID_PATTERNS.some(pattern => pattern.test(cmdTrimmed));
50
+ }
51
+ static getPriority(command) {
52
+ if (command.includes('BuildLighting') || command.includes('BuildPaths')) {
53
+ return 1;
54
+ }
55
+ else if (command.includes('summon') || command.includes('spawn')) {
56
+ return 5;
57
+ }
58
+ else if (command.startsWith('stat')) {
59
+ return 8;
60
+ }
61
+ else if (command.startsWith('show')) {
62
+ return 9;
63
+ }
64
+ return 7;
65
+ }
66
+ }
67
+ //# sourceMappingURL=command-validator.js.map
@@ -36,7 +36,7 @@ export interface ElicitSchema {
36
36
  }
37
37
  export interface ElicitOptions {
38
38
  timeoutMs?: number;
39
- fallback?: () => Promise<{
39
+ alternate?: () => Promise<{
40
40
  ok: boolean;
41
41
  value?: any;
42
42
  error?: string;
@@ -1,7 +1,5 @@
1
1
  export function createElicitationHelper(server, log) {
2
- // We do not require explicit capability detection: we optimistically try once
3
- // and disable on a Method-not-found (-32601) error for the session.
4
- let supported = true; // optimistic; will be set false on first failure
2
+ let supported = true;
5
3
  const MIN_TIMEOUT_MS = 30_000;
6
4
  const MAX_TIMEOUT_MS = 10 * 60 * 1000;
7
5
  const DEFAULT_TIMEOUT_MS = 3 * 60 * 1000;
@@ -31,9 +29,9 @@ export function createElicitationHelper(server, log) {
31
29
  return propertyEntries.every(([, rawSchema]) => {
32
30
  if (!rawSchema || typeof rawSchema !== 'object')
33
31
  return false;
34
- const primitive = rawSchema; // narrow for guards
32
+ const primitive = rawSchema;
35
33
  if ('properties' in primitive || 'items' in primitive)
36
- return false; // nested schemas unsupported
34
+ return false;
37
35
  if (Array.isArray(primitive.enum)) {
38
36
  const enumValues = primitive.enum;
39
37
  const allStrings = enumValues.every((value) => typeof value === 'string');
@@ -52,8 +50,8 @@ export function createElicitationHelper(server, log) {
52
50
  }
53
51
  async function elicit(message, requestedSchema, opts = {}) {
54
52
  if (!supported || !isSafeSchema(requestedSchema)) {
55
- if (opts.fallback)
56
- return opts.fallback();
53
+ if (opts.alternate)
54
+ return opts.alternate();
57
55
  return { ok: false, error: 'elicitation-unsupported' };
58
56
  }
59
57
  const params = { message, requestedSchema };
@@ -71,27 +69,26 @@ export function createElicitationHelper(server, log) {
71
69
  if (action === 'accept')
72
70
  return { ok: true, value: content };
73
71
  if (action === 'decline' || action === 'cancel') {
74
- if (opts.fallback)
75
- return opts.fallback();
72
+ if (opts.alternate)
73
+ return opts.alternate();
76
74
  return { ok: false, error: action };
77
75
  }
78
- if (opts.fallback)
79
- return opts.fallback();
76
+ if (opts.alternate)
77
+ return opts.alternate();
80
78
  return { ok: false, error: 'unexpected-response' };
81
79
  }
82
80
  catch (e) {
83
81
  const msg = String(e?.message || e);
84
82
  const code = e?.code ?? e?.error?.code;
85
- // If client doesn't support it, don’t try again this session
86
83
  if (msg.includes('Method not found') ||
87
84
  msg.includes('elicitInput-not-available') ||
88
85
  msg.includes('request-not-available') ||
89
86
  String(code) === '-32601') {
90
87
  supported = false;
91
88
  }
92
- log.debug('Elicitation failed; falling back', { error: msg, code });
93
- if (opts.fallback)
94
- return opts.fallback();
89
+ log.debug('Elicitation failed; using alternate handler', { error: msg, code });
90
+ if (opts.alternate)
91
+ return opts.alternate();
95
92
  return { ok: false, error: msg.includes('timeout') ? 'timeout' : 'rpc-failed' };
96
93
  }
97
94
  }
@@ -1,7 +1,4 @@
1
1
  import { BaseToolResponse } from '../types/tool-types.js';
2
- /**
3
- * Error types for categorization
4
- */
5
2
  export declare enum ErrorType {
6
3
  VALIDATION = "VALIDATION",
7
4
  CONNECTION = "CONNECTION",
@@ -11,63 +8,17 @@ export declare enum ErrorType {
11
8
  TIMEOUT = "TIMEOUT",
12
9
  UNKNOWN = "UNKNOWN"
13
10
  }
14
- /**
15
- * Consistent error handling for all tools
16
- */
17
11
  export declare class ErrorHandler {
18
- /**
19
- * Create a standardized error response
20
- */
21
12
  static createErrorResponse(error: any, toolName: string, context?: any): BaseToolResponse;
22
- /**
23
- * Categorize error by type
24
- */
25
13
  private static categorizeError;
26
- /**
27
- * Get user-friendly error message
28
- */
29
14
  private static getUserFriendlyMessage;
30
- /** Determine if an error is likely retriable */
31
15
  private static isRetriable;
32
- /**
33
- * Retry an async operation with exponential backoff
34
- * Best practice from TypeScript async programming patterns
35
- * @param operation - Async operation to retry
36
- * @param options - Retry configuration
37
- * @returns Result of the operation
38
- */
39
- static retryWithBackoff<T>(operation: () => Promise<T>, options?: {
16
+ static retryWithBackoff<T>(fn: () => Promise<T>, options?: {
40
17
  maxRetries?: number;
41
18
  initialDelay?: number;
42
19
  maxDelay?: number;
43
20
  backoffMultiplier?: number;
44
- shouldRetry?: (error: unknown) => boolean;
21
+ shouldRetry?: (error: any) => boolean;
45
22
  }): Promise<T>;
46
- /**
47
- * Add timeout to any promise
48
- * @param promise - Promise to add timeout to
49
- * @param timeoutMs - Timeout in milliseconds
50
- * @param errorMessage - Custom error message for timeout
51
- * @returns Promise that rejects on timeout
52
- */
53
- static withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage?: string): Promise<T>;
54
- /**
55
- * Execute multiple operations with Promise.allSettled for better error handling
56
- * Returns detailed results for each operation, including failures
57
- * @param operations - Array of async operations to execute
58
- * @returns Object with successful and failed operations separated
59
- */
60
- static batchExecute<T>(operations: Array<() => Promise<T>>): Promise<{
61
- successful: Array<{
62
- index: number;
63
- value: T;
64
- }>;
65
- failed: Array<{
66
- index: number;
67
- reason: unknown;
68
- }>;
69
- successCount: number;
70
- failureCount: number;
71
- }>;
72
23
  }
73
24
  //# sourceMappingURL=error-handler.d.ts.map
@@ -1,8 +1,5 @@
1
1
  import { Logger } from './logger.js';
2
2
  const log = new Logger('ErrorHandler');
3
- /**
4
- * Error types for categorization
5
- */
6
3
  export var ErrorType;
7
4
  (function (ErrorType) {
8
5
  ErrorType["VALIDATION"] = "VALIDATION";
@@ -13,13 +10,7 @@ export var ErrorType;
13
10
  ErrorType["TIMEOUT"] = "TIMEOUT";
14
11
  ErrorType["UNKNOWN"] = "UNKNOWN";
15
12
  })(ErrorType || (ErrorType = {}));
16
- /**
17
- * Consistent error handling for all tools
18
- */
19
13
  export class ErrorHandler {
20
- /**
21
- * Create a standardized error response
22
- */
23
14
  static createErrorResponse(error, toolName, context) {
24
15
  const errorType = this.categorizeError(error);
25
16
  const userMessage = this.getUserFriendlyMessage(errorType, error);
@@ -38,7 +29,6 @@ export class ErrorHandler {
38
29
  message: `Failed to execute ${toolName}: ${userMessage}`,
39
30
  retriable: retriable,
40
31
  scope: scope,
41
- // Add debug info in development
42
32
  ...(process.env.NODE_ENV === 'development' && {
43
33
  _debug: {
44
34
  errorType,
@@ -51,57 +41,46 @@ export class ErrorHandler {
51
41
  })
52
42
  };
53
43
  }
54
- /**
55
- * Categorize error by type
56
- */
57
44
  static categorizeError(error) {
58
45
  const explicitType = (error?.type || error?.errorType || '').toString().toUpperCase();
59
46
  if (explicitType && Object.values(ErrorType).includes(explicitType)) {
60
47
  return explicitType;
61
48
  }
62
49
  const errorMessage = error?.message?.toLowerCase() || String(error).toLowerCase();
63
- // Connection errors
64
50
  if (errorMessage.includes('econnrefused') ||
65
51
  errorMessage.includes('timeout') ||
66
52
  errorMessage.includes('connection') ||
67
53
  errorMessage.includes('network')) {
68
54
  return ErrorType.CONNECTION;
69
55
  }
70
- // Validation errors
71
56
  if (errorMessage.includes('invalid') ||
72
57
  errorMessage.includes('required') ||
73
58
  errorMessage.includes('must be') ||
74
59
  errorMessage.includes('validation')) {
75
60
  return ErrorType.VALIDATION;
76
61
  }
77
- // Unreal Engine specific errors
78
62
  if (errorMessage.includes('unreal') ||
79
- errorMessage.includes('remote control') ||
63
+ errorMessage.includes('connection failed') ||
80
64
  errorMessage.includes('blueprint') ||
81
65
  errorMessage.includes('actor') ||
82
66
  errorMessage.includes('asset')) {
83
67
  return ErrorType.UNREAL_ENGINE;
84
68
  }
85
- // Parameter errors
86
69
  if (errorMessage.includes('parameter') ||
87
70
  errorMessage.includes('argument') ||
88
71
  errorMessage.includes('missing')) {
89
72
  return ErrorType.PARAMETER;
90
73
  }
91
- // Timeout errors
92
74
  if (errorMessage.includes('timeout')) {
93
75
  return ErrorType.TIMEOUT;
94
76
  }
95
77
  return ErrorType.UNKNOWN;
96
78
  }
97
- /**
98
- * Get user-friendly error message
99
- */
100
79
  static getUserFriendlyMessage(type, error) {
101
80
  const originalMessage = error.message || String(error);
102
81
  switch (type) {
103
82
  case ErrorType.CONNECTION:
104
- return 'Failed to connect to Unreal Engine. Please ensure Remote Control is enabled and the engine is running.';
83
+ return 'Failed to connect to Unreal Engine. Please ensure the Automation Bridge plugin is active and the editor is running.';
105
84
  case ErrorType.VALIDATION:
106
85
  return `Invalid input: ${originalMessage}`;
107
86
  case ErrorType.UNREAL_ENGINE:
@@ -116,7 +95,6 @@ export class ErrorHandler {
116
95
  return originalMessage;
117
96
  }
118
97
  }
119
- /** Determine if an error is likely retriable */
120
98
  static isRetriable(error) {
121
99
  try {
122
100
  const code = (error?.code || '').toString().toUpperCase();
@@ -132,80 +110,26 @@ export class ErrorHandler {
132
110
  catch { }
133
111
  return false;
134
112
  }
135
- /**
136
- * Retry an async operation with exponential backoff
137
- * Best practice from TypeScript async programming patterns
138
- * @param operation - Async operation to retry
139
- * @param options - Retry configuration
140
- * @returns Result of the operation
141
- */
142
- static async retryWithBackoff(operation, options = {}) {
143
- const { maxRetries = 3, initialDelay = 100, maxDelay = 10000, backoffMultiplier = 2, shouldRetry = (error) => this.isRetriable(error) } = options;
144
- let lastError;
113
+ static async retryWithBackoff(fn, options = {}) {
114
+ const maxRetries = options.maxRetries ?? 3;
115
+ const initialDelay = options.initialDelay ?? 1000;
116
+ const maxDelay = options.maxDelay ?? 10000;
117
+ const multiplier = options.backoffMultiplier ?? 2;
118
+ const shouldRetry = options.shouldRetry ?? ((err) => this.isRetriable(err));
145
119
  let delay = initialDelay;
146
120
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
147
121
  try {
148
- return await operation();
122
+ return await fn();
149
123
  }
150
124
  catch (error) {
151
- lastError = error;
152
125
  if (attempt === maxRetries || !shouldRetry(error)) {
153
126
  throw error;
154
127
  }
155
- log.debug(`Retry attempt ${attempt + 1}/${maxRetries} after ${delay}ms`);
156
128
  await new Promise(resolve => setTimeout(resolve, delay));
157
- delay = Math.min(delay * backoffMultiplier, maxDelay);
129
+ delay = Math.min(delay * multiplier, maxDelay);
158
130
  }
159
131
  }
160
- throw lastError;
161
- }
162
- /**
163
- * Add timeout to any promise
164
- * @param promise - Promise to add timeout to
165
- * @param timeoutMs - Timeout in milliseconds
166
- * @param errorMessage - Custom error message for timeout
167
- * @returns Promise that rejects on timeout
168
- */
169
- static async withTimeout(promise, timeoutMs, errorMessage = 'Operation timed out') {
170
- let timeoutHandle;
171
- const timeoutPromise = new Promise((_, reject) => {
172
- timeoutHandle = setTimeout(() => {
173
- reject(new Error(errorMessage));
174
- }, timeoutMs);
175
- });
176
- try {
177
- return await Promise.race([promise, timeoutPromise]);
178
- }
179
- finally {
180
- if (timeoutHandle !== undefined) {
181
- clearTimeout(timeoutHandle);
182
- }
183
- }
184
- }
185
- /**
186
- * Execute multiple operations with Promise.allSettled for better error handling
187
- * Returns detailed results for each operation, including failures
188
- * @param operations - Array of async operations to execute
189
- * @returns Object with successful and failed operations separated
190
- */
191
- static async batchExecute(operations) {
192
- const results = await Promise.allSettled(operations.map(op => op()));
193
- const successful = [];
194
- const failed = [];
195
- results.forEach((result, index) => {
196
- if (result.status === 'fulfilled') {
197
- successful.push({ index, value: result.value });
198
- }
199
- else {
200
- failed.push({ index, reason: result.reason });
201
- }
202
- });
203
- return {
204
- successful,
205
- failed,
206
- successCount: successful.length,
207
- failureCount: failed.length
208
- };
132
+ throw new Error('Max retries exceeded');
209
133
  }
210
134
  }
211
135
  //# sourceMappingURL=error-handler.js.map
@@ -0,0 +1,3 @@
1
+ export declare function readIniFile(filePath: string): Promise<Record<string, Record<string, string>>>;
2
+ export declare function getProjectSetting(projectPath: string, category: string, sectionName: string, key?: string): Promise<any>;
3
+ //# sourceMappingURL=ini-reader.d.ts.map
@@ -0,0 +1,69 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ export async function readIniFile(filePath) {
4
+ try {
5
+ const content = await fs.readFile(filePath, 'utf-8');
6
+ const result = {};
7
+ let currentSection = '';
8
+ const lines = content.split(/\r?\n/);
9
+ for (const line of lines) {
10
+ const trimmed = line.trim();
11
+ if (!trimmed || trimmed.startsWith(';') || trimmed.startsWith('#')) {
12
+ continue;
13
+ }
14
+ if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
15
+ currentSection = trimmed.substring(1, trimmed.length - 1);
16
+ result[currentSection] = {};
17
+ }
18
+ else if (currentSection) {
19
+ const parts = trimmed.split('=');
20
+ if (parts.length >= 2) {
21
+ const key = parts[0].trim();
22
+ const value = parts.slice(1).join('=').trim();
23
+ result[currentSection][key] = value;
24
+ }
25
+ }
26
+ }
27
+ return result;
28
+ }
29
+ catch (error) {
30
+ throw new Error(`Failed to read INI file at ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
31
+ }
32
+ }
33
+ export async function getProjectSetting(projectPath, category, sectionName, key) {
34
+ let dirPath = projectPath;
35
+ if (dirPath.toLowerCase().endsWith('.uproject')) {
36
+ dirPath = path.dirname(dirPath);
37
+ }
38
+ const cleanCategory = category.replace(/^Default/, '');
39
+ const candidates = [
40
+ path.join(dirPath, 'Config', `Default${cleanCategory}.ini`),
41
+ path.join(dirPath, 'Saved', 'Config', 'WindowsEditor', `${cleanCategory}.ini`),
42
+ path.join(dirPath, 'Saved', 'Config', 'Windows', `${cleanCategory}.ini`),
43
+ path.join(dirPath, 'Saved', 'Config', 'Mac', `${cleanCategory}.ini`),
44
+ path.join(dirPath, 'Saved', 'Config', 'Linux', `${cleanCategory}.ini`)
45
+ ];
46
+ for (const configPath of candidates) {
47
+ try {
48
+ const iniData = await readIniFile(configPath);
49
+ if (sectionName) {
50
+ const section = iniData[sectionName];
51
+ if (section) {
52
+ if (key) {
53
+ return section[key];
54
+ }
55
+ return section;
56
+ }
57
+ }
58
+ else {
59
+ if (Object.keys(iniData).length > 0) {
60
+ return iniData;
61
+ }
62
+ }
63
+ }
64
+ catch (_e) {
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ //# sourceMappingURL=ini-reader.js.map
@@ -13,16 +13,19 @@ export class Logger {
13
13
  return order.indexOf(level) >= order.indexOf(this.level);
14
14
  }
15
15
  debug(...args) {
16
- if (this.shouldLog('debug'))
17
- console.error(`[${this.scope}]`, ...args);
16
+ if (!this.shouldLog('debug'))
17
+ return;
18
+ console.error(`[${this.scope}]`, ...args);
18
19
  }
19
20
  info(...args) {
20
- if (this.shouldLog('info'))
21
- console.error(`[${this.scope}]`, ...args);
21
+ if (!this.shouldLog('info'))
22
+ return;
23
+ console.error(`[${this.scope}]`, ...args);
22
24
  }
23
25
  warn(...args) {
24
- if (this.shouldLog('warn'))
25
- console.error(`[${this.scope}]`, ...args);
26
+ if (!this.shouldLog('warn'))
27
+ return;
28
+ console.warn(`[${this.scope}]`, ...args);
26
29
  }
27
30
  error(...args) {
28
31
  if (this.shouldLog('error'))
@@ -14,4 +14,7 @@ export declare function toVec3Object(input: any): Vec3Obj | null;
14
14
  export declare function toRotObject(input: any): Rot3Obj | null;
15
15
  export declare function toVec3Tuple(input: any): Vec3Tuple | null;
16
16
  export declare function toRotTuple(input: any): Rot3Tuple | null;
17
+ export declare function toFiniteNumber(raw: unknown): number | undefined;
18
+ export declare function normalizePartialVector(value: any, alternateKeys?: string[]): Record<string, number> | undefined;
19
+ export declare function normalizeTransformInput(transform: any): Record<string, unknown> | undefined;
17
20
  //# sourceMappingURL=normalize.d.ts.map
@@ -54,4 +54,60 @@ export function toRotTuple(input) {
54
54
  const { pitch, yaw, roll } = rot;
55
55
  return [pitch, yaw, roll];
56
56
  }
57
+ export function toFiniteNumber(raw) {
58
+ if (typeof raw === 'number' && Number.isFinite(raw))
59
+ return raw;
60
+ if (typeof raw === 'string') {
61
+ const trimmed = raw.trim();
62
+ if (trimmed.length === 0)
63
+ return undefined;
64
+ const parsed = Number(trimmed);
65
+ if (Number.isFinite(parsed))
66
+ return parsed;
67
+ }
68
+ return undefined;
69
+ }
70
+ export function normalizePartialVector(value, alternateKeys = ['x', 'y', 'z']) {
71
+ if (value === undefined || value === null)
72
+ return undefined;
73
+ const result = {};
74
+ const assignIfPresent = (component, raw) => {
75
+ const num = toFiniteNumber(raw);
76
+ if (num !== undefined)
77
+ result[component] = num;
78
+ };
79
+ if (Array.isArray(value)) {
80
+ if (value.length > 0)
81
+ assignIfPresent('x', value[0]);
82
+ if (value.length > 1)
83
+ assignIfPresent('y', value[1]);
84
+ if (value.length > 2)
85
+ assignIfPresent('z', value[2]);
86
+ }
87
+ else if (typeof value === 'object') {
88
+ const obj = value;
89
+ assignIfPresent('x', obj.x ?? obj[alternateKeys[0]]);
90
+ assignIfPresent('y', obj.y ?? obj[alternateKeys[1]]);
91
+ assignIfPresent('z', obj.z ?? obj[alternateKeys[2]]);
92
+ }
93
+ else {
94
+ assignIfPresent('x', value);
95
+ }
96
+ return Object.keys(result).length > 0 ? result : undefined;
97
+ }
98
+ export function normalizeTransformInput(transform) {
99
+ if (!transform || typeof transform !== 'object')
100
+ return undefined;
101
+ const result = {};
102
+ const location = normalizePartialVector(transform.location);
103
+ if (location)
104
+ result.location = location;
105
+ const rotation = normalizePartialVector(transform.rotation, ['pitch', 'yaw', 'roll']);
106
+ if (rotation)
107
+ result.rotation = rotation;
108
+ const scale = normalizePartialVector(transform.scale);
109
+ if (scale)
110
+ result.scale = scale;
111
+ return Object.keys(result).length > 0 ? result : undefined;
112
+ }
57
113
  //# sourceMappingURL=normalize.js.map
@@ -0,0 +1,7 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare class ResponseFactory {
3
+ static success(message: string, data?: unknown): CallToolResult;
4
+ static error(message: string, error?: unknown): CallToolResult;
5
+ static json(data: unknown): CallToolResult;
6
+ }
7
+ //# sourceMappingURL=response-factory.d.ts.map
@@ -0,0 +1,33 @@
1
+ export class ResponseFactory {
2
+ static success(message, data) {
3
+ const content = [{ type: 'text', text: message }];
4
+ if (data) {
5
+ content.push({
6
+ type: 'text',
7
+ text: JSON.stringify(data, null, 2)
8
+ });
9
+ }
10
+ return {
11
+ content,
12
+ isError: false
13
+ };
14
+ }
15
+ static error(message, error) {
16
+ const errorText = error instanceof Error ? error.message : String(error);
17
+ const fullMessage = error ? `${message}: ${errorText}` : message;
18
+ return {
19
+ content: [{ type: 'text', text: fullMessage }],
20
+ isError: true
21
+ };
22
+ }
23
+ static json(data) {
24
+ return {
25
+ content: [{
26
+ type: 'text',
27
+ text: JSON.stringify(data, null, 2)
28
+ }],
29
+ isError: false
30
+ };
31
+ }
32
+ }
33
+ //# sourceMappingURL=response-factory.js.map
@@ -1,35 +1,14 @@
1
- /**
2
- * Response Validator for MCP Tool Outputs
3
- * Validates tool responses against their defined output schemas
4
- */
5
1
  export declare class ResponseValidator {
6
2
  private ajv;
7
3
  private validators;
8
4
  constructor();
9
- /**
10
- * Register a tool's output schema for validation
11
- */
12
5
  registerSchema(toolName: string, outputSchema: any): void;
13
- /**
14
- * Validate a tool's response against its schema
15
- */
16
- validateResponse(toolName: string, response: any): {
6
+ validateResponse(toolName: string, response: any): Promise<{
17
7
  valid: boolean;
18
8
  errors?: string[];
19
9
  structuredContent?: any;
20
- };
21
- /**
22
- * Wrap a tool response with validation and MCP-compliant content shape.
23
- *
24
- * MCP tools/call responses must contain a `content` array. Many internal
25
- * handlers return structured JSON objects (e.g., { success, message, ... }).
26
- * This wrapper serializes such objects into a single text block while keeping
27
- * existing `content` responses intact.
28
- */
29
- wrapResponse(toolName: string, response: any): any;
30
- /**
31
- * Get validation statistics
32
- */
10
+ }>;
11
+ wrapResponse(toolName: string, response: any): Promise<any>;
33
12
  getStats(): {
34
13
  totalSchemas: number;
35
14
  tools: string[];