unreal-engine-mcp-server 0.4.0 → 0.4.4

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 (135) hide show
  1. package/.env.production +1 -1
  2. package/.github/copilot-instructions.md +45 -0
  3. package/.github/workflows/publish-mcp.yml +3 -2
  4. package/README.md +21 -5
  5. package/dist/index.js +124 -31
  6. package/dist/prompts/index.d.ts +10 -3
  7. package/dist/prompts/index.js +186 -7
  8. package/dist/resources/actors.d.ts +19 -1
  9. package/dist/resources/actors.js +55 -64
  10. package/dist/resources/assets.js +46 -62
  11. package/dist/resources/levels.d.ts +21 -3
  12. package/dist/resources/levels.js +29 -54
  13. package/dist/tools/actors.d.ts +3 -14
  14. package/dist/tools/actors.js +246 -302
  15. package/dist/tools/animation.d.ts +57 -102
  16. package/dist/tools/animation.js +429 -450
  17. package/dist/tools/assets.d.ts +13 -2
  18. package/dist/tools/assets.js +52 -44
  19. package/dist/tools/audio.d.ts +22 -13
  20. package/dist/tools/audio.js +467 -121
  21. package/dist/tools/blueprint.d.ts +32 -13
  22. package/dist/tools/blueprint.js +699 -448
  23. package/dist/tools/build_environment_advanced.d.ts +0 -1
  24. package/dist/tools/build_environment_advanced.js +190 -45
  25. package/dist/tools/consolidated-tool-definitions.js +78 -252
  26. package/dist/tools/consolidated-tool-handlers.js +506 -133
  27. package/dist/tools/debug.d.ts +72 -10
  28. package/dist/tools/debug.js +167 -31
  29. package/dist/tools/editor.d.ts +9 -2
  30. package/dist/tools/editor.js +30 -44
  31. package/dist/tools/foliage.d.ts +34 -15
  32. package/dist/tools/foliage.js +97 -107
  33. package/dist/tools/introspection.js +19 -21
  34. package/dist/tools/landscape.d.ts +1 -2
  35. package/dist/tools/landscape.js +311 -168
  36. package/dist/tools/level.d.ts +3 -28
  37. package/dist/tools/level.js +642 -192
  38. package/dist/tools/lighting.d.ts +14 -3
  39. package/dist/tools/lighting.js +236 -123
  40. package/dist/tools/materials.d.ts +25 -7
  41. package/dist/tools/materials.js +102 -79
  42. package/dist/tools/niagara.d.ts +10 -12
  43. package/dist/tools/niagara.js +74 -94
  44. package/dist/tools/performance.d.ts +12 -4
  45. package/dist/tools/performance.js +38 -79
  46. package/dist/tools/physics.d.ts +34 -10
  47. package/dist/tools/physics.js +364 -292
  48. package/dist/tools/rc.js +97 -23
  49. package/dist/tools/sequence.d.ts +1 -0
  50. package/dist/tools/sequence.js +125 -22
  51. package/dist/tools/ui.d.ts +31 -4
  52. package/dist/tools/ui.js +83 -66
  53. package/dist/tools/visual.d.ts +11 -0
  54. package/dist/tools/visual.js +245 -30
  55. package/dist/types/tool-types.d.ts +0 -6
  56. package/dist/types/tool-types.js +1 -8
  57. package/dist/unreal-bridge.d.ts +32 -2
  58. package/dist/unreal-bridge.js +621 -127
  59. package/dist/utils/elicitation.d.ts +57 -0
  60. package/dist/utils/elicitation.js +104 -0
  61. package/dist/utils/error-handler.d.ts +0 -33
  62. package/dist/utils/error-handler.js +4 -111
  63. package/dist/utils/http.d.ts +2 -22
  64. package/dist/utils/http.js +12 -75
  65. package/dist/utils/normalize.d.ts +4 -4
  66. package/dist/utils/normalize.js +15 -7
  67. package/dist/utils/python-output.d.ts +18 -0
  68. package/dist/utils/python-output.js +290 -0
  69. package/dist/utils/python.d.ts +2 -0
  70. package/dist/utils/python.js +4 -0
  71. package/dist/utils/response-validator.js +28 -2
  72. package/dist/utils/result-helpers.d.ts +27 -0
  73. package/dist/utils/result-helpers.js +147 -0
  74. package/dist/utils/safe-json.d.ts +0 -2
  75. package/dist/utils/safe-json.js +0 -43
  76. package/dist/utils/validation.d.ts +16 -0
  77. package/dist/utils/validation.js +70 -7
  78. package/mcp-config-example.json +2 -2
  79. package/package.json +10 -9
  80. package/server.json +37 -14
  81. package/src/index.ts +130 -33
  82. package/src/prompts/index.ts +211 -13
  83. package/src/resources/actors.ts +59 -44
  84. package/src/resources/assets.ts +48 -51
  85. package/src/resources/levels.ts +35 -45
  86. package/src/tools/actors.ts +269 -313
  87. package/src/tools/animation.ts +556 -539
  88. package/src/tools/assets.ts +53 -43
  89. package/src/tools/audio.ts +507 -113
  90. package/src/tools/blueprint.ts +778 -462
  91. package/src/tools/build_environment_advanced.ts +266 -64
  92. package/src/tools/consolidated-tool-definitions.ts +90 -264
  93. package/src/tools/consolidated-tool-handlers.ts +630 -121
  94. package/src/tools/debug.ts +176 -33
  95. package/src/tools/editor.ts +35 -37
  96. package/src/tools/foliage.ts +110 -104
  97. package/src/tools/introspection.ts +24 -22
  98. package/src/tools/landscape.ts +334 -181
  99. package/src/tools/level.ts +683 -182
  100. package/src/tools/lighting.ts +244 -123
  101. package/src/tools/materials.ts +114 -83
  102. package/src/tools/niagara.ts +87 -81
  103. package/src/tools/performance.ts +49 -88
  104. package/src/tools/physics.ts +393 -299
  105. package/src/tools/rc.ts +102 -24
  106. package/src/tools/sequence.ts +136 -28
  107. package/src/tools/ui.ts +101 -70
  108. package/src/tools/visual.ts +250 -29
  109. package/src/types/tool-types.ts +0 -9
  110. package/src/unreal-bridge.ts +658 -140
  111. package/src/utils/elicitation.ts +129 -0
  112. package/src/utils/error-handler.ts +4 -159
  113. package/src/utils/http.ts +16 -115
  114. package/src/utils/normalize.ts +20 -10
  115. package/src/utils/python-output.ts +351 -0
  116. package/src/utils/python.ts +3 -0
  117. package/src/utils/response-validator.ts +25 -2
  118. package/src/utils/result-helpers.ts +193 -0
  119. package/src/utils/safe-json.ts +0 -50
  120. package/src/utils/validation.ts +94 -7
  121. package/tests/run-unreal-tool-tests.mjs +720 -0
  122. package/tsconfig.json +2 -2
  123. package/dist/python-utils.d.ts +0 -29
  124. package/dist/python-utils.js +0 -54
  125. package/dist/types/index.d.ts +0 -323
  126. package/dist/types/index.js +0 -28
  127. package/dist/utils/cache-manager.d.ts +0 -64
  128. package/dist/utils/cache-manager.js +0 -176
  129. package/dist/utils/errors.d.ts +0 -133
  130. package/dist/utils/errors.js +0 -256
  131. package/src/python/editor_compat.py +0 -181
  132. package/src/python-utils.ts +0 -57
  133. package/src/types/index.ts +0 -414
  134. package/src/utils/cache-manager.ts +0 -213
  135. package/src/utils/errors.ts +0 -312
@@ -2,6 +2,8 @@
2
2
  * Validation and sanitization utilities for Unreal Engine assets
3
3
  */
4
4
 
5
+ import { toRotTuple, toVec3Tuple } from './normalize.js';
6
+
5
7
  /**
6
8
  * Maximum path length allowed in Unreal Engine
7
9
  */
@@ -78,13 +80,27 @@ export function sanitizePath(path: string): string {
78
80
  return '/Game';
79
81
  }
80
82
 
83
+ // Normalize slashes
84
+ path = path.replace(/\\/g, '/');
85
+
81
86
  // Ensure path starts with /
82
87
  if (!path.startsWith('/')) {
83
88
  path = `/${path}`;
84
89
  }
85
90
 
86
91
  // Split path into segments and sanitize each
87
- const segments = path.split('/').filter(s => s.length > 0);
92
+ let segments = path.split('/').filter(s => s.length > 0);
93
+
94
+ if (segments.length === 0) {
95
+ return '/Game';
96
+ }
97
+
98
+ // Ensure the first segment is a valid root (Game, Engine, Script, Temp)
99
+ const ROOTS = new Set(['Game', 'Engine', 'Script', 'Temp']);
100
+ if (!ROOTS.has(segments[0])) {
101
+ segments = ['Game', ...segments];
102
+ }
103
+
88
104
  const sanitizedSegments = segments.map(segment => {
89
105
  // Don't sanitize Game, Engine, or other root folders
90
106
  if (['Game', 'Engine', 'Script', 'Temp'].includes(segment)) {
@@ -174,10 +190,14 @@ export function resolveSkeletalMeshPath(input: string): string | null {
174
190
 
175
191
  // Common skeleton to mesh mappings
176
192
  const skeletonToMeshMap: { [key: string]: string } = {
177
- '/Game/Mannequin/Character/Mesh/UE4_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Manny',
178
- '/Game/Characters/Mannequins/Meshes/SK_Mannequin': '/Game/Characters/Mannequins/Meshes/SKM_Manny',
179
- '/Game/Mannequin/Character/Mesh/SK_Mannequin': '/Game/Characters/Mannequins/Meshes/SKM_Manny',
180
- '/Game/Characters/Mannequin_UE4/Meshes/UE4_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Quinn',
193
+ '/Game/Mannequin/Character/Mesh/UE4_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple',
194
+ '/Game/Characters/Mannequins/Meshes/SK_Mannequin': '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple',
195
+ '/Game/Mannequin/Character/Mesh/SK_Mannequin': '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple',
196
+ '/Game/Characters/Mannequin_UE4/Meshes/UE4_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Quinn_Simple',
197
+ '/Game/Characters/Mannequins/Skeletons/UE5_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple',
198
+ '/Game/Characters/Mannequins/Skeletons/UE5_Female_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Quinn_Simple',
199
+ '/Game/Characters/Mannequins/Skeletons/UE5_Manny_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple',
200
+ '/Game/Characters/Mannequins/Skeletons/UE5_Quinn_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Quinn_Simple'
181
201
  };
182
202
 
183
203
  // Check if this is a known skeleton path
@@ -189,8 +209,19 @@ export function resolveSkeletalMeshPath(input: string): string | null {
189
209
  if (input.includes('_Skeleton')) {
190
210
  // Try common replacements
191
211
  let meshPath = input.replace('_Skeleton', '');
192
- meshPath = meshPath.replace('/SK_', '/SKM_');
193
- meshPath = meshPath.replace('UE4_Mannequin', 'SKM_Manny');
212
+ // Mapping for replacements
213
+ const replacements: { [key: string]: string } = {
214
+ '/SK_': '/SKM_',
215
+ 'UE4_Mannequin': 'SKM_Manny',
216
+ 'UE5_Mannequin': 'SKM_Manny',
217
+ 'UE5_Manny': 'SKM_Manny',
218
+ 'UE5_Quinn': 'SKM_Quinn'
219
+ };
220
+ // Apply all replacements using regex
221
+ meshPath = meshPath.replace(
222
+ new RegExp(Object.keys(replacements).join('|'), 'g'),
223
+ match => replacements[match]
224
+ );
194
225
  return meshPath;
195
226
  }
196
227
 
@@ -210,3 +241,59 @@ export function resolveSkeletalMeshPath(input: string): string | null {
210
241
  export async function concurrencyDelay(ms: number = 100): Promise<void> {
211
242
  return new Promise(resolve => setTimeout(resolve, ms));
212
243
  }
244
+
245
+ /**
246
+ * Ensure the provided value is a finite number within optional bounds.
247
+ * @throws if the value is not a finite number or violates bounds
248
+ */
249
+ export function validateNumber(
250
+ value: unknown,
251
+ label: string,
252
+ {
253
+ min,
254
+ max,
255
+ allowZero = true
256
+ }: { min?: number; max?: number; allowZero?: boolean } = {}
257
+ ): number {
258
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
259
+ throw new Error(`Invalid ${label}: expected a finite number`);
260
+ }
261
+
262
+ if (!allowZero && value === 0) {
263
+ throw new Error(`Invalid ${label}: zero is not allowed`);
264
+ }
265
+
266
+ if (typeof min === 'number' && value < min) {
267
+ throw new Error(`Invalid ${label}: must be >= ${min}`);
268
+ }
269
+
270
+ if (typeof max === 'number' && value > max) {
271
+ throw new Error(`Invalid ${label}: must be <= ${max}`);
272
+ }
273
+
274
+ return value;
275
+ }
276
+
277
+ /**
278
+ * Validate an array (tuple) of finite numbers, preserving the original shape.
279
+ * @throws if the tuple has the wrong length or contains invalid values
280
+ */
281
+ export function ensureVector3(value: unknown, label: string): [number, number, number] {
282
+ const tuple = toVec3Tuple(value);
283
+ if (!tuple) {
284
+ throw new Error(`Invalid ${label}: expected an object with x,y,z or an array of 3 numbers`);
285
+ }
286
+ return tuple;
287
+ }
288
+
289
+ export function ensureColorRGB(value: unknown, label: string): [number, number, number] {
290
+ return ensureVector3(value, label);
291
+ }
292
+
293
+ export function ensureRotation(value: unknown, label: string): [number, number, number] {
294
+ const tuple = toRotTuple(value);
295
+ if (!tuple) {
296
+ throw new Error(`Invalid ${label}: expected an object with pitch,yaw,roll or an array of 3 numbers`);
297
+ }
298
+ return tuple;
299
+ }