ue-mcp 1.2.3 → 1.3.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 (255) hide show
  1. package/README.md +4 -3
  2. package/dist/action-class.js +56 -3
  3. package/dist/action-class.js.map +1 -1
  4. package/dist/bridge-timeouts.d.ts +64 -0
  5. package/dist/bridge-timeouts.js +118 -0
  6. package/dist/bridge-timeouts.js.map +1 -0
  7. package/dist/bridge.js +10 -2
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/editor-control.d.ts +72 -5
  10. package/dist/editor-control.js +164 -140
  11. package/dist/editor-control.js.map +1 -1
  12. package/dist/editor-target.d.ts +55 -1
  13. package/dist/editor-target.js +107 -10
  14. package/dist/editor-target.js.map +1 -1
  15. package/dist/engine-observer.d.ts +59 -5
  16. package/dist/engine-observer.js +249 -29
  17. package/dist/engine-observer.js.map +1 -1
  18. package/dist/engine-root.d.ts +91 -0
  19. package/dist/engine-root.js +448 -0
  20. package/dist/engine-root.js.map +1 -0
  21. package/dist/epic-enrich.js +16 -1
  22. package/dist/epic-enrich.js.map +1 -1
  23. package/dist/feedback-cli.js +4 -0
  24. package/dist/feedback-cli.js.map +1 -1
  25. package/dist/feedback-deferred.d.ts +9 -0
  26. package/dist/feedback-deferred.js +2 -0
  27. package/dist/feedback-deferred.js.map +1 -1
  28. package/dist/feedback-fallback.d.ts +99 -0
  29. package/dist/feedback-fallback.js +173 -0
  30. package/dist/feedback-fallback.js.map +1 -0
  31. package/dist/flow/write-methods.js +20 -0
  32. package/dist/flow/write-methods.js.map +1 -1
  33. package/dist/index.js +41 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/lean-context.js +8 -3
  36. package/dist/lean-context.js.map +1 -1
  37. package/dist/locking.js +11 -2
  38. package/dist/locking.js.map +1 -1
  39. package/dist/plugin/loader.d.ts +4 -0
  40. package/dist/plugin/loader.js +22 -8
  41. package/dist/plugin/loader.js.map +1 -1
  42. package/dist/plugin/manifest.d.ts +72 -52
  43. package/dist/plugin/manifest.js +118 -21
  44. package/dist/plugin/manifest.js.map +1 -1
  45. package/dist/plugin-cli.js +16 -3
  46. package/dist/plugin-cli.js.map +1 -1
  47. package/dist/project.d.ts +11 -0
  48. package/dist/project.js +23 -2
  49. package/dist/project.js.map +1 -1
  50. package/dist/python-gate.d.ts +95 -0
  51. package/dist/python-gate.js +175 -0
  52. package/dist/python-gate.js.map +1 -0
  53. package/dist/tool-counts.json +16 -16
  54. package/dist/tools/animation.js +288 -24
  55. package/dist/tools/animation.js.map +1 -1
  56. package/dist/tools/asset.js +79 -14
  57. package/dist/tools/asset.js.map +1 -1
  58. package/dist/tools/audio.js +59 -5
  59. package/dist/tools/audio.js.map +1 -1
  60. package/dist/tools/blueprint.js +29 -12
  61. package/dist/tools/blueprint.js.map +1 -1
  62. package/dist/tools/chooser.js +4 -1
  63. package/dist/tools/chooser.js.map +1 -1
  64. package/dist/tools/editor.js +81 -43
  65. package/dist/tools/editor.js.map +1 -1
  66. package/dist/tools/feedback.js +214 -48
  67. package/dist/tools/feedback.js.map +1 -1
  68. package/dist/tools/foliage.js +27 -1
  69. package/dist/tools/foliage.js.map +1 -1
  70. package/dist/tools/gameplay.js +38 -11
  71. package/dist/tools/gameplay.js.map +1 -1
  72. package/dist/tools/gas.js +17 -5
  73. package/dist/tools/gas.js.map +1 -1
  74. package/dist/tools/landscape.js +22 -7
  75. package/dist/tools/landscape.js.map +1 -1
  76. package/dist/tools/level.js +322 -51
  77. package/dist/tools/level.js.map +1 -1
  78. package/dist/tools/material.js +10 -4
  79. package/dist/tools/material.js.map +1 -1
  80. package/dist/tools/niagara.js +3 -2
  81. package/dist/tools/niagara.js.map +1 -1
  82. package/dist/tools/pcg.js +6 -5
  83. package/dist/tools/pcg.js.map +1 -1
  84. package/dist/tools/plugins.js +2 -0
  85. package/dist/tools/plugins.js.map +1 -1
  86. package/dist/tools/project.js +47 -20
  87. package/dist/tools/project.js.map +1 -1
  88. package/dist/types.d.ts +24 -0
  89. package/dist/types.js +46 -3
  90. package/dist/types.js.map +1 -1
  91. package/dist/ue-mcp.default.yml +493 -125
  92. package/package.json +2 -2
  93. package/plugin/ue_mcp_bridge/NATIVE_RUNTIME_VISIBILITY.md +53 -0
  94. package/plugin/ue_mcp_bridge/NATIVE_STATIC_MESH_USAGE_PROGRESS.md +115 -0
  95. package/plugin/ue_mcp_bridge/README_MassHandlers.md +97 -0
  96. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +14 -0
  97. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +21 -4
  98. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
  99. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +395 -69
  100. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +79 -3
  101. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +25 -0
  102. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +3 -3
  103. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRigSequencer.cpp +3061 -0
  104. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRetargeterAuthoring.cpp +961 -0
  105. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRigAuthoring.cpp +900 -0
  106. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Pose.cpp +769 -0
  107. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +44 -3
  108. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_SkeletalLive.cpp +217 -11
  109. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +551 -24
  110. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Validation.cpp +735 -0
  111. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +352 -73
  112. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +8 -0
  113. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkProperties.cpp +1 -1
  114. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.cpp +503 -0
  115. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.h +21 -0
  116. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkUpsert.cpp +2 -2
  117. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Enum.cpp +2 -2
  118. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.cpp +902 -0
  119. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.h +33 -0
  120. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +478 -134
  121. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +5 -5
  122. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.cpp +933 -0
  123. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.h +35 -0
  124. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp +478 -0
  125. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp +1 -1
  126. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +4 -4
  127. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +2 -2
  128. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp +319 -0
  129. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp +3 -3
  130. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +482 -35
  131. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +10 -0
  132. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.cpp +502 -0
  133. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.h +43 -0
  134. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +89 -7
  135. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +17 -51
  136. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +107 -0
  137. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +10 -10
  138. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Search.cpp +648 -0
  139. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +5 -1
  140. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.cpp +252 -1
  141. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.h +10 -2
  142. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +252 -41
  143. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +4 -0
  144. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +250 -27
  145. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +303 -125
  146. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +73 -50
  147. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_RuntimeVisibility.cpp +757 -0
  148. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +11 -2
  149. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +3 -0
  150. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Batch.cpp +419 -0
  151. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +39 -161
  152. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +66 -1
  153. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTAuthoring.cpp +1323 -0
  154. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BehaviorTree.cpp +1211 -0
  155. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +2 -0
  156. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +60 -0
  157. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Runtime.cpp +363 -12
  158. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/HandlerEditorState.h +84 -0
  159. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +1288 -36
  160. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +3 -0
  161. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +41 -16
  162. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +959 -213
  163. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +66 -0
  164. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_BatchWrite.cpp +1571 -0
  165. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Convert.cpp +316 -0
  166. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Inspection.cpp +280 -0
  167. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection.cpp +666 -0
  168. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection_Internal.h +63 -0
  169. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +43 -12
  170. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +13 -47
  171. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_PostProcess.cpp +527 -0
  172. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Query.cpp +1169 -0
  173. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Refresh.cpp +723 -0
  174. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Save.cpp +325 -0
  175. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Spatial.cpp +360 -0
  176. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Trace.cpp +178 -58
  177. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Transient.cpp +337 -0
  178. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Volumes.cpp +25 -12
  179. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +10 -9
  180. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartitionSettings.cpp +686 -0
  181. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.cpp +467 -0
  182. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.h +22 -0
  183. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +452 -175
  184. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +5 -0
  185. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Build.cpp +597 -0
  186. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +17 -15
  187. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +38 -168
  188. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +39 -30
  189. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +392 -78
  190. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +2 -0
  191. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers_Internal.h +83 -0
  192. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.cpp +200 -0
  193. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.h +15 -0
  194. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +19 -12
  195. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.cpp +31 -1
  196. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +307 -69
  197. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +84 -0
  198. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +8 -41
  199. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +33 -52
  200. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/ActorSelectorTests.cpp +344 -0
  201. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationControlRigTimelineTests.cpp +60 -0
  202. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationPoseTests.cpp +115 -0
  203. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetBulkReadTests.cpp +177 -0
  204. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetDeleteGuardTests.cpp +276 -0
  205. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPathResolutionTests.cpp +243 -0
  206. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPropertyPersistTests.cpp +213 -0
  207. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetSubobjectTests.cpp +235 -0
  208. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AutomationRunnerTests.cpp +72 -0
  209. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeAuthoringTests.cpp +526 -0
  210. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeNodeTests.cpp +334 -0
  211. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BlueprintHandlerSurfaceTests.cpp +362 -0
  212. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BridgeProtocolTests.cpp +14 -0
  213. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/CollisionQueryTests.cpp +288 -0
  214. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/DataTableRowWriteTests.cpp +453 -0
  215. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/EditorFunctionCallTests.cpp +223 -0
  216. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/FoliageBatchTests.cpp +147 -0
  217. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GameThreadGateTests.cpp +82 -0
  218. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GasLiveAttributeTests.cpp +183 -0
  219. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LandscapeSampleTests.cpp +119 -0
  220. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelBatchWriteTests.cpp +176 -0
  221. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelComponentTreeInstanceCountTests.cpp +189 -0
  222. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelConvertBrushesTests.cpp +100 -0
  223. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelInstanceProjectionTests.cpp +265 -0
  224. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelPostProcessOverrideTests.cpp +258 -0
  225. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelQueryComponentsTests.cpp +195 -0
  226. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelRefreshTests.cpp +142 -0
  227. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelSaveReportTests.cpp +125 -0
  228. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelScriptHandlersTests.cpp +42 -0
  229. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelStaticMeshUsageTests.cpp +412 -0
  230. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTraceWorldScopeTests.cpp +133 -0
  231. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTransientActorTests.cpp +205 -0
  232. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelWorldPartitionSettingsTests.cpp +168 -0
  233. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTestTypes.h +51 -0
  234. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTests.cpp +379 -0
  235. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MaterialBuildTests.cpp +238 -0
  236. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshBooleanTests.cpp +170 -0
  237. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshGeometryTests.cpp +116 -0
  238. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageSaveExtensionTests.cpp +161 -0
  239. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageWriteGuardTests.cpp +253 -0
  240. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/RuntimeVisibilityTests.cpp +143 -0
  241. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerHandlerTests.cpp +660 -0
  242. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerScrubTests.cpp +50 -0
  243. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SkeletonDiffTests.cpp +685 -0
  244. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/WidgetBlueprintResolveTests.cpp +145 -0
  245. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +80 -0
  246. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerFunctionCall.h +509 -0
  247. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerQuery.h +407 -0
  248. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +1008 -77
  249. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
  250. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/MCPEngineStatus.cpp +152 -14
  251. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/Tests/MCPEngineStatusTests.cpp +65 -0
  252. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Public/MCPEngineStatus.h +32 -1
  253. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/UE_MCP_BridgeStatus.Build.cs +2 -0
  254. package/skills/ue-mcp-animation/SKILL.md +154 -0
  255. package/skills/ue-mcp-blueprint/SKILL.md +71 -0
@@ -4,6 +4,7 @@
4
4
  // stays in BlueprintHandlers.cpp::RegisterHandlers.
5
5
 
6
6
  #include "BlueprintHandlers.h"
7
+ #include "BlueprintHandlers_Internal.h"
7
8
  #include "HandlerRegistry.h"
8
9
  #include "HandlerUtils.h"
9
10
  #include "Kismet2/BlueprintEditorUtils.h"
@@ -13,6 +14,10 @@
13
14
  #include "EdGraph/EdGraph.h"
14
15
  #include "EdGraph/EdGraphPin.h"
15
16
  #include "EdGraphSchema_K2.h"
17
+ // #894: an animation layer override must be created as an AnimationGraph on
18
+ // the animation schema, not as a K2 function graph.
19
+ #include "AnimationGraph.h"
20
+ #include "AnimationGraphSchema.h"
16
21
  #include "K2Node_FunctionEntry.h"
17
22
  #include "K2Node_EditablePinBase.h"
18
23
  #include "K2Node_CustomEvent.h"
@@ -94,7 +99,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::CreateFunction(const TSharedPtr<FJson
94
99
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
95
100
  if (!Blueprint)
96
101
  {
97
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
102
+ return BlueprintNotFoundError(AssetPath);
98
103
  }
99
104
 
100
105
  // Idempotency: existing function graph short-circuits.
@@ -223,7 +228,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ListBlueprintFunctions(const TSharedP
223
228
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
224
229
  if (!Blueprint)
225
230
  {
226
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
231
+ return BlueprintNotFoundError(AssetPath);
227
232
  }
228
233
 
229
234
  // Skeleton class super is the reliable parent during an in-editor edit; fall
@@ -556,7 +561,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::RenameFunction(const TSharedPtr<FJson
556
561
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
557
562
  if (!Blueprint)
558
563
  {
559
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
564
+ return BlueprintNotFoundError(AssetPath);
560
565
  }
561
566
 
562
567
  // Find the function graph
@@ -608,7 +613,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::DeleteFunction(const TSharedPtr<FJson
608
613
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
609
614
  if (!Blueprint)
610
615
  {
611
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
616
+ return BlueprintNotFoundError(AssetPath);
612
617
  }
613
618
 
614
619
  UEdGraph* FoundGraph = nullptr;
@@ -726,7 +731,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::OverrideFunction(const TSharedPtr<FJs
726
731
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
727
732
  if (!Blueprint)
728
733
  {
729
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
734
+ return BlueprintNotFoundError(AssetPath);
730
735
  }
731
736
 
732
737
  const FName FuncName(*FunctionName);
@@ -850,12 +855,65 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::OverrideFunction(const TSharedPtr<FJs
850
855
  return MCPResult(Result);
851
856
  }
852
857
 
858
+ // #894: an animation layer override has to be an AnimationGraph. Creating a
859
+ // plain K2 function graph for one produces a graph the anim compiler never
860
+ // evaluates, so the override binds to nothing and the layer is inert while
861
+ // every read of the Blueprint says the override is there.
862
+ //
863
+ // The declaration is the authority on the graph's type, so mirror it rather
864
+ // than keeping a list of which functions happen to be layers: find the graph
865
+ // the override function was declared in and reuse its graph class and
866
+ // schema. One rule covers a layer declared on an Animation Layer Interface
867
+ // and one inherited from a parent Anim Blueprint, and it stays correct if
868
+ // Epic adds another graph-backed override kind.
869
+ //
870
+ // The predicate is deliberately the narrowest one that can be CHECKED
871
+ // rather than inferred. Both halves have to hold: the Blueprint answers
872
+ // SupportsAnimLayers (which only UAnimBlueprint does), and the graph that
873
+ // declared the function is a UAnimationGraph. Reading the declaration is
874
+ // stronger than testing the signature for a pose parameter, because it asks
875
+ // what the layer IS instead of what it looks like, and it cannot turn an
876
+ // ordinary function override on an Anim Blueprint into an animation graph.
877
+ //
878
+ // The cost of that narrowness is one case it does not cover: a layer
879
+ // declared on a native class has no declaring Blueprint graph to read, so
880
+ // it falls through to the K2 default. That is the false negative, and it is
881
+ // the right direction to be wrong in. Anim layers are authored on Animation
882
+ // Layer Interfaces and on parent Anim Blueprints, both of which are covered.
883
+ TSubclassOf<UEdGraph> GraphClass = UEdGraph::StaticClass();
884
+ TSubclassOf<UEdGraphSchema> SchemaClass = UEdGraphSchema_K2::StaticClass();
885
+ FString MirroredFromGraph;
886
+ if (Blueprint->SupportsAnimLayers())
887
+ {
888
+ if (UBlueprint* DeclaringBlueprint = UBlueprint::GetBlueprintFromClass(OverrideFuncClass))
889
+ {
890
+ for (UEdGraph* SourceGraph : DeclaringBlueprint->FunctionGraphs)
891
+ {
892
+ if (!SourceGraph || SourceGraph->GetFName() != FuncName) continue;
893
+ if (SourceGraph->IsA<UAnimationGraph>())
894
+ {
895
+ GraphClass = SourceGraph->GetClass();
896
+ MirroredFromGraph = SourceGraph->GetPathName();
897
+ if (UClass* SourceSchema = SourceGraph->Schema.Get())
898
+ {
899
+ SchemaClass = SourceSchema;
900
+ }
901
+ else
902
+ {
903
+ SchemaClass = UAnimationGraphSchema::StaticClass();
904
+ }
905
+ }
906
+ break;
907
+ }
908
+ }
909
+ }
910
+
853
911
  // Function-form override: create the graph seeded from the override class so
854
912
  // the entry/result terminators carry the base function's exact signature.
855
913
  // (This is the fix for #688 - create_function produced a blank graph that
856
914
  // never bound as the override.)
857
915
  UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(
858
- Blueprint, FuncName, UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
916
+ Blueprint, FuncName, GraphClass, SchemaClass);
859
917
  if (!NewGraph)
860
918
  {
861
919
  return MCPError(FString::Printf(TEXT("Failed to create override graph: %s"), *FunctionName));
@@ -863,6 +921,17 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::OverrideFunction(const TSharedPtr<FJs
863
921
 
864
922
  FBlueprintEditorUtils::AddFunctionGraph<UClass>(Blueprint, NewGraph, /*bIsUserCreated=*/false, OverrideFuncClass);
865
923
 
924
+ // #894: creating the graph with the right class and schema is only half of
925
+ // it. CreateFunctionGraph gives an AnimationGraph its result node, but the
926
+ // layer's input pose nodes come from the interface function's own pose
927
+ // parameters, and only ConformAnimGraphToInterface seeds those. Without
928
+ // this the override is correctly typed and still unusable: an empty layer
929
+ // with nothing to plug a pose into.
930
+ if (!MirroredFromGraph.IsEmpty())
931
+ {
932
+ UAnimationGraphSchema::ConformAnimGraphToInterface(Blueprint, *NewGraph, OverrideFunc);
933
+ }
934
+
866
935
  FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint);
867
936
  FKismetEditorUtilities::CompileBlueprint(Blueprint);
868
937
  SaveAssetPackage(Blueprint);
@@ -875,6 +944,19 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::OverrideFunction(const TSharedPtr<FJs
875
944
  Result->SetStringField(TEXT("graphName"), NewGraph->GetName());
876
945
  Result->SetStringField(TEXT("sourceClass"), OverrideFuncClass->GetPathName());
877
946
  Result->SetStringField(TEXT("source"), Source);
947
+ // #894: report the graph's actual type. An anim layer override that came
948
+ // back as an EdGraph on the K2 schema was the whole bug, and it was
949
+ // invisible from the response.
950
+ Result->SetStringField(TEXT("graphClass"), NewGraph->GetClass()->GetName());
951
+ if (UClass* AppliedSchema = NewGraph->Schema.Get())
952
+ {
953
+ Result->SetStringField(TEXT("schemaClass"), AppliedSchema->GetName());
954
+ }
955
+ if (!MirroredFromGraph.IsEmpty())
956
+ {
957
+ Result->SetBoolField(TEXT("animationGraph"), true);
958
+ Result->SetStringField(TEXT("mirroredFromGraph"), MirroredFromGraph);
959
+ }
878
960
 
879
961
  TSharedPtr<FJsonObject> Payload = MakeShared<FJsonObject>();
880
962
  Payload->SetStringField(TEXT("path"), AssetPath);
@@ -896,7 +978,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ListOverridableFunctions(const TShare
896
978
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
897
979
  if (!Blueprint)
898
980
  {
899
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
981
+ return BlueprintNotFoundError(AssetPath);
900
982
  }
901
983
 
902
984
  FBlueprintEditorUtils::ConformImplementedInterfaces(Blueprint);
@@ -89,46 +89,6 @@ namespace
89
89
  PinObj->SetStringField(TEXT("defaultObject"), Pin->DefaultObject->GetPathName());
90
90
  }
91
91
  }
92
-
93
- FString MakeDefaultGraphDumpPath(const FString& AssetPath, const FString& GraphName)
94
- {
95
- const FString AssetName = FPackageName::GetLongPackageAssetName(AssetPath);
96
- const FString PathHash = FString::Printf(TEXT("%08x"), GetTypeHash(AssetPath + TEXT(":") + GraphName));
97
- const FString BaseName = FPaths::MakeValidFileName(AssetName + TEXT("_") + GraphName + TEXT("_") + PathHash);
98
- return FPaths::Combine(FPaths::ProjectSavedDir(), TEXT("UE_MCP"), TEXT("GraphDumps"), BaseName + TEXT(".json"));
99
- }
100
-
101
- bool WriteJsonObjectToFile(const TSharedPtr<FJsonObject>& JsonObject, const FString& RequestedPath, const FString& AssetPath, const FString& GraphName, FString& OutResolvedPath, FString& OutError)
102
- {
103
- OutResolvedPath = RequestedPath.IsEmpty() ? MakeDefaultGraphDumpPath(AssetPath, GraphName) : RequestedPath;
104
- if (FPaths::IsRelative(OutResolvedPath))
105
- {
106
- OutResolvedPath = FPaths::Combine(FPaths::ProjectSavedDir(), OutResolvedPath);
107
- }
108
-
109
- const FString Directory = FPaths::GetPath(OutResolvedPath);
110
- if (!Directory.IsEmpty() && !IFileManager::Get().MakeDirectory(*Directory, true))
111
- {
112
- OutError = FString::Printf(TEXT("Failed to create dump directory: %s"), *Directory);
113
- return false;
114
- }
115
-
116
- FString JsonText;
117
- const TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonText);
118
- if (!FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer))
119
- {
120
- OutError = TEXT("Failed to serialize graph JSON");
121
- return false;
122
- }
123
-
124
- if (!FFileHelper::SaveStringToFile(JsonText, *OutResolvedPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
125
- {
126
- OutError = FString::Printf(TEXT("Failed to write graph dump: %s"), *OutResolvedPath);
127
- return false;
128
- }
129
-
130
- return true;
131
- }
132
92
  }
133
93
 
134
94
 
@@ -145,7 +105,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::AddNode(const TSharedPtr<FJsonObject>
145
105
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
146
106
  if (!Blueprint)
147
107
  {
148
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
108
+ return BlueprintNotFoundError(AssetPath);
149
109
  }
150
110
 
151
111
  // Find the target graph
@@ -184,6 +144,10 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::AddNode(const TSharedPtr<FJsonObject>
184
144
  else if (NodeClass == TEXT("SwitchEnum")) ResolvedClass = TEXT("K2Node_SwitchEnum");
185
145
  else if (NodeClass == TEXT("SwitchString")) ResolvedClass = TEXT("K2Node_SwitchString");
186
146
  else if (NodeClass == TEXT("MakeStruct")) ResolvedClass = TEXT("K2Node_MakeStruct");
147
+ // #981: UMG "Create Widget". The literal K2Node_CreateWidget already
148
+ // resolved through the UEdGraphNode lookup below; this is the short form
149
+ // callers reach for first, matching every other alias here.
150
+ else if (NodeClass == TEXT("CreateWidget")) ResolvedClass = TEXT("K2Node_CreateWidget");
187
151
  else if (NodeClass == TEXT("BreakStruct")) ResolvedClass = TEXT("K2Node_BreakStruct");
188
152
  else if (NodeClass == TEXT("MakeArray")) ResolvedClass = TEXT("K2Node_MakeArray");
189
153
  else if (NodeClass == TEXT("Return") || NodeClass == TEXT("FunctionResult")) ResolvedClass = TEXT("K2Node_FunctionResult");
@@ -815,7 +779,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ReadBlueprintGraph(const TSharedPtr<F
815
779
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
816
780
  if (!Blueprint)
817
781
  {
818
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
782
+ return BlueprintNotFoundError(AssetPath);
819
783
  }
820
784
 
821
785
  // Find the graph in UbergraphPages and FunctionGraphs
@@ -904,6 +868,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ReadBlueprintGraph(const TSharedPtr<F
904
868
 
905
869
  auto Result = MCPSuccess();
906
870
  Result->SetStringField(TEXT("path"), AssetPath);
871
+ AnnotateResolvedBlueprint(Result, Blueprint);
907
872
  Result->SetStringField(TEXT("graphName"), GraphName);
908
873
  Result->SetArrayField(TEXT("nodes"), Nodes);
909
874
  Result->SetNumberField(TEXT("nodeCount"), Nodes.Num());
@@ -952,6 +917,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ReadBlueprintGraph(const TSharedPtr<F
952
917
 
953
918
  auto Result = MCPSuccess();
954
919
  Result->SetStringField(TEXT("path"), AssetPath);
920
+ AnnotateResolvedBlueprint(Result, Blueprint);
955
921
  Result->SetStringField(TEXT("graphName"), GraphName);
956
922
  Result->SetBoolField(TEXT("dumpedToFile"), true);
957
923
  Result->SetStringField(TEXT("outputPath"), ResolvedDumpPath);
@@ -999,7 +965,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ConnectPins(const TSharedPtr<FJsonObj
999
965
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1000
966
  if (!Blueprint)
1001
967
  {
1002
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
968
+ return BlueprintNotFoundError(AssetPath);
1003
969
  }
1004
970
 
1005
971
  UEdGraph* TargetGraph = FindGraph(Blueprint, GraphName);
@@ -1215,7 +1181,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::DeleteNode(const TSharedPtr<FJsonObje
1215
1181
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1216
1182
  if (!Blueprint)
1217
1183
  {
1218
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1184
+ return BlueprintNotFoundError(AssetPath);
1219
1185
  }
1220
1186
 
1221
1187
  UEdGraph* TargetGraph = FindGraph(Blueprint, GraphName);
@@ -1270,7 +1236,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetNodeProperty(const TSharedPtr<FJso
1270
1236
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1271
1237
  if (!Blueprint)
1272
1238
  {
1273
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1239
+ return BlueprintNotFoundError(AssetPath);
1274
1240
  }
1275
1241
 
1276
1242
  UEdGraph* TargetGraph = FindGraph(Blueprint, GraphName);
@@ -1681,7 +1647,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ExportNodesT3D(const TSharedPtr<FJson
1681
1647
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1682
1648
  if (!Blueprint)
1683
1649
  {
1684
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1650
+ return BlueprintNotFoundError(AssetPath);
1685
1651
  }
1686
1652
 
1687
1653
  UEdGraph* TargetGraph = FindGraph(Blueprint, GraphName);
@@ -1775,7 +1741,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ImportNodesT3D(const TSharedPtr<FJson
1775
1741
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1776
1742
  if (!Blueprint)
1777
1743
  {
1778
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1744
+ return BlueprintNotFoundError(AssetPath);
1779
1745
  }
1780
1746
 
1781
1747
  UEdGraph* TargetGraph = FindGraph(Blueprint, GraphName);
@@ -1923,7 +1889,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::CleanupGraph(const TSharedPtr<FJsonOb
1923
1889
  if (auto Err = RequireStringAlt(Params, TEXT("path"), TEXT("assetPath"), AssetPath)) return Err;
1924
1890
 
1925
1891
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1926
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1892
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
1927
1893
 
1928
1894
  const FString GraphName = OptionalString(Params, TEXT("graphName"));
1929
1895
 
@@ -1999,7 +1965,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ConnectPinsBatch(const TSharedPtr<FJs
1999
1965
  }
2000
1966
 
2001
1967
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
2002
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1968
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
2003
1969
 
2004
1970
  UEdGraph* TargetGraph = FindGraph(Blueprint, GraphName);
2005
1971
  if (!TargetGraph) return MCPError(FString::Printf(TEXT("Graph not found: %s"), *GraphName));
@@ -2104,7 +2070,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetNodePosition(const TSharedPtr<FJso
2104
2070
  int32 PosY = OptionalInt(Params, TEXT("posY"), 0);
2105
2071
 
2106
2072
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
2107
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
2073
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
2108
2074
  UEdGraph* Graph = FindGraph(Blueprint, GraphName);
2109
2075
  if (!Graph) return MCPError(FString::Printf(TEXT("Graph not found: %s"), *GraphName));
2110
2076
  UEdGraphNode* Node = FindNodeByGuidOrName(Graph, NodeId);
@@ -2137,7 +2103,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::AutoLayoutGraph(const TSharedPtr<FJso
2137
2103
  int32 RowGap = OptionalInt(Params, TEXT("rowGap"), 200);
2138
2104
 
2139
2105
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
2140
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
2106
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
2141
2107
  UEdGraph* Graph = FindGraph(Blueprint, GraphName);
2142
2108
  if (!Graph) return MCPError(FString::Printf(TEXT("Graph not found: %s"), *GraphName));
2143
2109
 
@@ -5,10 +5,100 @@
5
5
  // plugin - no downstream code is expected to include this.
6
6
 
7
7
  #include "CoreMinimal.h"
8
+ #include "Dom/JsonValue.h"
9
+ #include "Dom/JsonObject.h"
10
+ #include "EdGraph/EdGraph.h"
11
+ #include "HAL/FileManager.h"
12
+ #include "Misc/FileHelper.h"
13
+ #include "Misc/PackageName.h"
14
+ #include "Misc/Paths.h"
15
+ #include "Serialization/JsonSerializer.h"
16
+ #include "Serialization/JsonWriter.h"
8
17
 
9
18
  class UBlueprint;
10
19
  class UActorComponent;
11
20
 
21
+ // ── Graph selectors ─────────────────────────────────────────────────────────
22
+ //
23
+ // list_blueprint_graphs hands callers a `selector` they can pass back as
24
+ // graphName, and duplicate names (AnimBP "Transition", "Locomotion") get an
25
+ // index suffix. search_call_sites has to report the same selector for the same
26
+ // graph or the two disagree about how to address one graph, so the rule lives
27
+ // here rather than being restated per caller.
28
+
29
+ /** "Locomotion" when the name is unique, "Locomotion[3]" when it is not. */
30
+ inline FString MakeGraphSelector(const FString& Name, int32 DuplicateIndex, int32 DuplicateCount)
31
+ {
32
+ return DuplicateCount > 1
33
+ ? FString::Printf(TEXT("%s[%d]"), *Name, DuplicateIndex)
34
+ : Name;
35
+ }
36
+
37
+ /** How many graphs share each name, which is what decides whether a selector
38
+ * needs its index suffix. */
39
+ inline void CountGraphNames(const TArray<UEdGraph*>& Graphs, TMap<FString, int32>& OutNameCounts)
40
+ {
41
+ for (UEdGraph* Graph : Graphs)
42
+ {
43
+ if (Graph)
44
+ {
45
+ ++OutNameCounts.FindOrAdd(Graph->GetName());
46
+ }
47
+ }
48
+ }
49
+
50
+ // ── Graph dump files ────────────────────────────────────────────────────────
51
+ //
52
+ // read_graph writes an oversized result to a file under Saved/UE_MCP rather
53
+ // than returning it inline. search_call_sites follows the same convention, so
54
+ // both use the same path builder and the same writer.
55
+
56
+ inline FString MakeDefaultGraphDumpPath(const FString& AssetPath, const FString& GraphName)
57
+ {
58
+ const FString AssetName = FPackageName::GetLongPackageAssetName(AssetPath);
59
+ const FString PathHash = FString::Printf(TEXT("%08x"), GetTypeHash(AssetPath + TEXT(":") + GraphName));
60
+ const FString BaseName = FPaths::MakeValidFileName(AssetName + TEXT("_") + GraphName + TEXT("_") + PathHash);
61
+ return FPaths::Combine(FPaths::ProjectSavedDir(), TEXT("UE_MCP"), TEXT("GraphDumps"), BaseName + TEXT(".json"));
62
+ }
63
+
64
+ inline bool WriteJsonObjectToFile(
65
+ const TSharedPtr<FJsonObject>& JsonObject,
66
+ const FString& RequestedPath,
67
+ const FString& AssetPath,
68
+ const FString& GraphName,
69
+ FString& OutResolvedPath,
70
+ FString& OutError)
71
+ {
72
+ OutResolvedPath = RequestedPath.IsEmpty() ? MakeDefaultGraphDumpPath(AssetPath, GraphName) : RequestedPath;
73
+ if (FPaths::IsRelative(OutResolvedPath))
74
+ {
75
+ OutResolvedPath = FPaths::Combine(FPaths::ProjectSavedDir(), OutResolvedPath);
76
+ }
77
+
78
+ const FString Directory = FPaths::GetPath(OutResolvedPath);
79
+ if (!Directory.IsEmpty() && !IFileManager::Get().MakeDirectory(*Directory, true))
80
+ {
81
+ OutError = FString::Printf(TEXT("Failed to create dump directory: %s"), *Directory);
82
+ return false;
83
+ }
84
+
85
+ FString JsonText;
86
+ const TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonText);
87
+ if (!FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer))
88
+ {
89
+ OutError = TEXT("Failed to serialize graph JSON");
90
+ return false;
91
+ }
92
+
93
+ if (!FFileHelper::SaveStringToFile(JsonText, *OutResolvedPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
94
+ {
95
+ OutError = FString::Printf(TEXT("Failed to write graph dump: %s"), *OutResolvedPath);
96
+ return false;
97
+ }
98
+
99
+ return true;
100
+ }
101
+
12
102
  // Resolve the named component template on a blueprint, honouring inheritance.
13
103
  // See definition in BlueprintHandlers_Graph.cpp for the full contract (bForWrite
14
104
  // semantics, ICH-override creation on write, CDO fallback on read, etc.).
@@ -18,3 +108,20 @@ UActorComponent* ResolveComponentTemplate(
18
108
  bool bForWrite,
19
109
  bool& bOutIsInherited,
20
110
  TArray<FString>& OutAvailable);
111
+
112
+ // #942: a level script Blueprint is not an asset of its own. It lives inside
113
+ // the map package at "<Map>.<Map>:PersistentLevel.<Map>", so every Blueprint
114
+ // action handed the umap path a caller actually has answered "Blueprint not
115
+ // found". FBlueprintHandlers::LoadBlueprint now resolves a World path to that
116
+ // object; the two helpers below carry the shared reporting around it, so read,
117
+ // list_graphs, read_graph and get_execution_flow behave identically.
118
+ //
119
+ // Builds the "not found" response for a failed Blueprint lookup. When the path
120
+ // names a World whose level script has never been created, the message says so
121
+ // and prints the object path, rather than claiming the Blueprint is missing.
122
+ TSharedPtr<FJsonValue> BlueprintNotFoundError(const FString& AssetPath);
123
+
124
+ // Record which object actually answered the request. A caller that passed a
125
+ // umap path gets back the level script Blueprint's object path, so the alias it
126
+ // used is visible rather than implied.
127
+ void AnnotateResolvedBlueprint(const TSharedPtr<FJsonObject>& Result, UBlueprint* Blueprint);
@@ -58,7 +58,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetVariableProperties(const TSharedPt
58
58
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
59
59
  if (!Blueprint)
60
60
  {
61
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
61
+ return BlueprintNotFoundError(AssetPath);
62
62
  }
63
63
 
64
64
  // Find the variable
@@ -315,7 +315,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetComponentProperty(const TSharedPtr
315
315
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
316
316
  if (!Blueprint)
317
317
  {
318
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
318
+ return BlueprintNotFoundError(AssetPath);
319
319
  }
320
320
 
321
321
  bool bIsInherited = false;
@@ -531,7 +531,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetClassDefault(const TSharedPtr<FJso
531
531
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
532
532
  if (!Blueprint)
533
533
  {
534
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
534
+ return BlueprintNotFoundError(AssetPath);
535
535
  }
536
536
 
537
537
  UClass* GenClass = Blueprint->GeneratedClass;
@@ -660,7 +660,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::AddFunctionParameter(const TSharedPtr
660
660
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
661
661
  if (!Blueprint)
662
662
  {
663
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
663
+ return BlueprintNotFoundError(AssetPath);
664
664
  }
665
665
 
666
666
  // Find the function graph
@@ -845,7 +845,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetVariableDefault(const TSharedPtr<F
845
845
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
846
846
  if (!Blueprint)
847
847
  {
848
- return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
848
+ return BlueprintNotFoundError(AssetPath);
849
849
  }
850
850
 
851
851
  // Find the variable description
@@ -970,7 +970,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::ReadComponentProperties(const TShared
970
970
  if (auto Err = RequireString(Params, TEXT("componentName"), ComponentName)) return Err;
971
971
 
972
972
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
973
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
973
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
974
974
 
975
975
  bool bIsInherited = false;
976
976
  TArray<FString> Available;
@@ -1080,7 +1080,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::GetComponentProperty(const TSharedPtr
1080
1080
  if (auto Err = RequireString(Params, TEXT("propertyName"), PropertyName)) return Err;
1081
1081
 
1082
1082
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1083
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1083
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
1084
1084
 
1085
1085
  bool bIsInherited = false;
1086
1086
  TArray<FString> Available;
@@ -1354,7 +1354,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetComponentOverrideMaterials(const T
1354
1354
  }
1355
1355
 
1356
1356
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1357
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1357
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
1358
1358
 
1359
1359
  bool bIsInherited = false;
1360
1360
  TArray<FString> Available;
@@ -1444,7 +1444,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::AddTimelineTrack(const TSharedPtr<FJs
1444
1444
  const FString TrackType = OptionalString(Params, TEXT("trackType"), TEXT("float")).ToLower();
1445
1445
 
1446
1446
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1447
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1447
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
1448
1448
 
1449
1449
  // Find or create the UTimelineTemplate that backs the K2Node_Timeline.
1450
1450
  const FName TimelineFName(*TimelineName);
@@ -1620,7 +1620,7 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetCapsuleSize(const TSharedPtr<FJson
1620
1620
  }
1621
1621
 
1622
1622
  UBlueprint* Blueprint = LoadBlueprint(AssetPath);
1623
- if (!Blueprint) return MCPError(FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
1623
+ if (!Blueprint) return BlueprintNotFoundError(AssetPath);
1624
1624
 
1625
1625
  bool bIsInherited = false;
1626
1626
  TArray<FString> Available;