unreal-engine-mcp-server 0.4.4 → 0.4.6

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.
@@ -21,13 +21,13 @@ Supported actions: list, import, create_material.`,
21
21
  description: 'Action to perform'
22
22
  },
23
23
  // For list
24
- directory: { type: 'string', description: 'Directory path to list (shows immediate children only)' },
24
+ directory: { type: 'string', description: 'Directory path to list (shows immediate children only). Automatically maps /Content to /Game. Example: "/Game/MyAssets"' },
25
25
  // For import
26
- sourcePath: { type: 'string', description: 'Source file path' },
27
- destinationPath: { type: 'string', description: 'Destination path' },
26
+ sourcePath: { type: 'string', description: 'Source file path on disk to import (FBX, PNG, WAV, EXR supported). Example: "C:/MyAssets/mesh.fbx"' },
27
+ destinationPath: { type: 'string', description: 'Destination path in project content where asset will be imported. Example: "/Game/ImportedAssets"' },
28
28
  // For create_material
29
- name: { type: 'string', description: 'Asset name' },
30
- path: { type: 'string', description: 'Save path' }
29
+ name: { type: 'string', description: 'Name for the new material asset. Example: "MyMaterial"' },
30
+ path: { type: 'string', description: 'Content path where material will be saved. Example: "/Game/Materials"' }
31
31
  },
32
32
  required: ['action']
33
33
  },
@@ -76,35 +76,38 @@ Supported actions: spawn, delete, apply_force.`,
76
76
  description: 'Action to perform'
77
77
  },
78
78
  // Common
79
- actorName: { type: 'string', description: 'Actor name (optional for spawn, auto-generated if not provided)' },
79
+ actorName: { type: 'string', description: 'Actor label/name (optional for spawn, auto-generated if not provided; required for delete). Case-insensitive for delete action.' },
80
80
  classPath: {
81
81
  type: 'string',
82
- description: 'Actor class (e.g., "StaticMeshActor", "CameraActor") OR asset path (e.g., "/Engine/BasicShapes/Cube", "/Game/MyMesh"). Asset paths will automatically spawn as StaticMeshActor with the mesh applied'
82
+ description: 'Actor class (e.g., "StaticMeshActor", "CameraActor") OR asset path (e.g., "/Engine/BasicShapes/Cube", "/Game/MyMesh"). Asset paths will automatically spawn as StaticMeshActor with the mesh applied. Required for spawn action.'
83
83
  },
84
84
  // Transform
85
85
  location: {
86
86
  type: 'object',
87
+ description: 'World space location in centimeters (Unreal units). Optional for spawn, defaults to origin.',
87
88
  properties: {
88
- x: { type: 'number' },
89
- y: { type: 'number' },
90
- z: { type: 'number' }
89
+ x: { type: 'number', description: 'X coordinate (forward axis in Unreal)' },
90
+ y: { type: 'number', description: 'Y coordinate (right axis in Unreal)' },
91
+ z: { type: 'number', description: 'Z coordinate (up axis in Unreal)' }
91
92
  }
92
93
  },
93
94
  rotation: {
94
95
  type: 'object',
96
+ description: 'World space rotation in degrees. Optional for spawn, defaults to zero rotation.',
95
97
  properties: {
96
- pitch: { type: 'number' },
97
- yaw: { type: 'number' },
98
- roll: { type: 'number' }
98
+ pitch: { type: 'number', description: 'Pitch rotation in degrees (Y-axis rotation)' },
99
+ yaw: { type: 'number', description: 'Yaw rotation in degrees (Z-axis rotation)' },
100
+ roll: { type: 'number', description: 'Roll rotation in degrees (X-axis rotation)' }
99
101
  }
100
102
  },
101
103
  // Physics
102
104
  force: {
103
105
  type: 'object',
106
+ description: 'Force vector to apply in Newtons. Required for apply_force action. Actor must have physics simulation enabled.',
104
107
  properties: {
105
- x: { type: 'number' },
106
- y: { type: 'number' },
107
- z: { type: 'number' }
108
+ x: { type: 'number', description: 'Force magnitude along X-axis' },
109
+ y: { type: 'number', description: 'Force magnitude along Y-axis' },
110
+ z: { type: 'number', description: 'Force magnitude along Z-axis' }
108
111
  }
109
112
  }
110
113
  },
@@ -145,24 +148,26 @@ Supported actions: play, stop, set_camera, set_view_mode (with validation).`,
145
148
  // Camera
146
149
  location: {
147
150
  type: 'object',
151
+ description: 'World space camera location for set_camera action. All coordinates required.',
148
152
  properties: {
149
- x: { type: 'number' },
150
- y: { type: 'number' },
151
- z: { type: 'number' }
153
+ x: { type: 'number', description: 'X coordinate in centimeters' },
154
+ y: { type: 'number', description: 'Y coordinate in centimeters' },
155
+ z: { type: 'number', description: 'Z coordinate in centimeters' }
152
156
  }
153
157
  },
154
158
  rotation: {
155
159
  type: 'object',
160
+ description: 'Camera rotation for set_camera action. All rotation components required.',
156
161
  properties: {
157
- pitch: { type: 'number' },
158
- yaw: { type: 'number' },
159
- roll: { type: 'number' }
162
+ pitch: { type: 'number', description: 'Pitch in degrees' },
163
+ yaw: { type: 'number', description: 'Yaw in degrees' },
164
+ roll: { type: 'number', description: 'Roll in degrees' }
160
165
  }
161
166
  },
162
167
  // View mode
163
168
  viewMode: {
164
169
  type: 'string',
165
- description: 'View mode (Lit, Unlit, Wireframe, etc.)'
170
+ description: 'View mode for set_view_mode action. Supported: Lit, Unlit, Wireframe, DetailLighting, LightingOnly, LightComplexity, ShaderComplexity. Required for set_view_mode.'
166
171
  }
167
172
  },
168
173
  required: ['action']
@@ -209,31 +214,32 @@ Supported actions: load, save, stream, create_light, build_lighting.`,
209
214
  description: 'Level action'
210
215
  },
211
216
  // Level
212
- levelPath: { type: 'string', description: 'Level path' },
213
- levelName: { type: 'string', description: 'Level name' },
214
- streaming: { type: 'boolean', description: 'Use streaming' },
215
- shouldBeLoaded: { type: 'boolean', description: 'Load or unload' },
216
- shouldBeVisible: { type: 'boolean', description: 'Visibility' },
217
+ levelPath: { type: 'string', description: 'Full content path to level asset (e.g., "/Game/Maps/MyLevel"). Required for load action.' },
218
+ levelName: { type: 'string', description: 'Level name for streaming operations. Required for stream action.' },
219
+ streaming: { type: 'boolean', description: 'Whether to use streaming load (true) or direct load (false). Optional for load action.' },
220
+ shouldBeLoaded: { type: 'boolean', description: 'Whether to load (true) or unload (false) the streaming level. Required for stream action.' },
221
+ shouldBeVisible: { type: 'boolean', description: 'Whether the streaming level should be visible after loading. Optional for stream action.' },
217
222
  // Lighting
218
223
  lightType: {
219
224
  type: 'string',
220
225
  enum: ['Directional', 'Point', 'Spot', 'Rect'],
221
- description: 'Light type'
226
+ description: 'Type of light to create. Directional for sun-like lighting, Point for omni-directional, Spot for cone-shaped, Rect for area lighting. Required for create_light.'
222
227
  },
223
- name: { type: 'string', description: 'Object name' },
228
+ name: { type: 'string', description: 'Name for the spawned light actor. Optional, auto-generated if not provided.' },
224
229
  location: {
225
230
  type: 'object',
231
+ description: 'World space location for light placement in centimeters. Optional for create_light, defaults to origin.',
226
232
  properties: {
227
- x: { type: 'number' },
228
- y: { type: 'number' },
229
- z: { type: 'number' }
233
+ x: { type: 'number', description: 'X coordinate' },
234
+ y: { type: 'number', description: 'Y coordinate' },
235
+ z: { type: 'number', description: 'Z coordinate' }
230
236
  }
231
237
  },
232
- intensity: { type: 'number', description: 'Light intensity' },
238
+ intensity: { type: 'number', description: 'Light intensity value in lumens (for Point/Spot) or lux (for Directional). Typical range: 1000-10000. Optional for create_light.' },
233
239
  quality: {
234
240
  type: 'string',
235
241
  enum: ['Preview', 'Medium', 'High', 'Production'],
236
- description: 'Build quality'
242
+ description: 'Lighting build quality level. Preview is fastest, Production is highest quality. Required for build_lighting action.'
237
243
  }
238
244
  },
239
245
  required: ['action']
@@ -272,17 +278,17 @@ Supported actions: create_animation_bp, play_montage, setup_ragdoll.`,
272
278
  description: 'Action type'
273
279
  },
274
280
  // Common
275
- name: { type: 'string', description: 'Asset name' },
276
- actorName: { type: 'string', description: 'Actor name' },
281
+ name: { type: 'string', description: 'Name for the created animation blueprint asset. Required for create_animation_bp action.' },
282
+ actorName: { type: 'string', description: 'Actor label/name in the level to apply animation to. Required for play_montage and setup_ragdoll actions.' },
277
283
  // Animation
278
- skeletonPath: { type: 'string', description: 'Skeleton path' },
279
- montagePath: { type: 'string', description: 'Montage path' },
280
- animationPath: { type: 'string', description: 'Animation path' },
281
- playRate: { type: 'number', description: 'Play rate' },
284
+ skeletonPath: { type: 'string', description: 'Content path to skeleton asset (e.g., "/Game/Characters/MySkeleton"). Required for create_animation_bp action.' },
285
+ montagePath: { type: 'string', description: 'Content path to animation montage asset to play. Required for play_montage if animationPath not provided.' },
286
+ animationPath: { type: 'string', description: 'Content path to animation sequence asset to play. Alternative to montagePath for play_montage action.' },
287
+ playRate: { type: 'number', description: 'Animation playback speed multiplier. 1.0 is normal speed, 2.0 is double speed, 0.5 is half speed. Optional, defaults to 1.0.' },
282
288
  // Physics
283
- physicsAssetName: { type: 'string', description: 'Physics asset' },
284
- blendWeight: { type: 'number', description: 'Blend weight' },
285
- savePath: { type: 'string', description: 'Save location' }
289
+ physicsAssetName: { type: 'string', description: 'Name or path to physics asset for ragdoll simulation. Required for setup_ragdoll action.' },
290
+ blendWeight: { type: 'number', description: 'Blend weight between animated and ragdoll physics (0.0 to 1.0). 0.0 is fully animated, 1.0 is fully ragdoll. Optional, defaults to 1.0.' },
291
+ savePath: { type: 'string', description: 'Content path where animation blueprint will be saved (e.g., "/Game/Animations"). Required for create_animation_bp action.' }
286
292
  },
287
293
  required: ['action']
288
294
  },
@@ -319,34 +325,35 @@ Supported actions: niagara, particle, debug_shape.`,
319
325
  description: 'Effect type'
320
326
  },
321
327
  // Common
322
- name: { type: 'string', description: 'Effect name' },
328
+ name: { type: 'string', description: 'Name for the spawned effect actor. Optional, auto-generated if not provided.' },
323
329
  location: {
324
330
  type: 'object',
331
+ description: 'World space location where effect will be spawned in centimeters. Optional, defaults to origin.',
325
332
  properties: {
326
- x: { type: 'number' },
327
- y: { type: 'number' },
328
- z: { type: 'number' }
333
+ x: { type: 'number', description: 'X coordinate' },
334
+ y: { type: 'number', description: 'Y coordinate' },
335
+ z: { type: 'number', description: 'Z coordinate' }
329
336
  }
330
337
  },
331
338
  // Particles
332
339
  effectType: {
333
340
  type: 'string',
334
- description: 'Effect type (Fire, Smoke, Water, etc.)'
341
+ description: 'Preset particle effect type (Fire, Smoke, Water, Explosion, etc.). Used for particle action to spawn common effects.'
335
342
  },
336
- systemPath: { type: 'string', description: 'Niagara system path' },
337
- scale: { type: 'number', description: 'Scale factor' },
343
+ systemPath: { type: 'string', description: 'Content path to Niagara system asset (e.g., "/Game/Effects/MyNiagaraSystem"). Required for niagara action.' },
344
+ scale: { type: 'number', description: 'Uniform scale multiplier for Niagara effect. 1.0 is normal size. Optional, defaults to 1.0.' },
338
345
  // Debug
339
346
  shape: {
340
347
  type: 'string',
341
- description: 'Debug shape (Line, Box, Sphere, etc.)'
348
+ description: 'Debug shape type to draw (Line, Box, Sphere, Capsule, Cone, Cylinder, Arrow). Required for debug_shape action.'
342
349
  },
343
- size: { type: 'number', description: 'Size/radius' },
350
+ size: { type: 'number', description: 'Size/radius of debug shape in centimeters. For Line, this is thickness. For shapes, this is radius/extent. Optional, defaults vary by shape.' },
344
351
  color: {
345
352
  type: 'array',
346
353
  items: { type: 'number' },
347
- description: 'RGBA color'
354
+ description: 'RGBA color array with values 0-255 (e.g., [255, 0, 0, 255] for red). Optional, defaults to white.'
348
355
  },
349
- duration: { type: 'number', description: 'Duration' }
356
+ duration: { type: 'number', description: 'How long debug shape persists in seconds. 0 means one frame, -1 means permanent until cleared. Optional, defaults to 0.' }
350
357
  },
351
358
  required: ['action']
352
359
  },
@@ -385,14 +392,14 @@ Supported actions: create, add_component.`,
385
392
  enum: ['create', 'add_component'],
386
393
  description: 'Blueprint action'
387
394
  },
388
- name: { type: 'string', description: 'Blueprint name' },
395
+ name: { type: 'string', description: 'Name for the blueprint asset. Required for create action. For add_component, this is the blueprint asset name or path.' },
389
396
  blueprintType: {
390
397
  type: 'string',
391
- description: 'Type (Actor, Pawn, Character, etc.)'
398
+ description: 'Base class type for blueprint (Actor, Pawn, Character, Object, ActorComponent, SceneComponent, etc.). Required for create action.'
392
399
  },
393
- componentType: { type: 'string', description: 'Component type' },
394
- componentName: { type: 'string', description: 'Component name' },
395
- savePath: { type: 'string', description: 'Save location' }
400
+ componentType: { type: 'string', description: 'Component class to add (StaticMeshComponent, SkeletalMeshComponent, CameraComponent, etc.). Required for add_component action.' },
401
+ componentName: { type: 'string', description: 'Unique name for the component instance within the blueprint. Required for add_component action.' },
402
+ savePath: { type: 'string', description: 'Content path where blueprint will be saved (e.g., "/Game/Blueprints"). Required for create action.' }
396
403
  },
397
404
  required: ['action', 'name']
398
405
  },
@@ -429,22 +436,23 @@ Supported actions: create_landscape, sculpt, add_foliage, paint_foliage, create_
429
436
  description: 'Environment action'
430
437
  },
431
438
  // Common
432
- name: { type: 'string', description: 'Object name' },
439
+ name: { type: 'string', description: 'Name for landscape, foliage type, or grass type actor. Optional for most actions, auto-generated if not provided.' },
433
440
  // Landscape
434
- sizeX: { type: 'number', description: 'Landscape size X' },
435
- sizeY: { type: 'number', description: 'Landscape size Y' },
441
+ sizeX: { type: 'number', description: 'Landscape width in components. Each component is typically 63 quads. Required for create_landscape action.' },
442
+ sizeY: { type: 'number', description: 'Landscape height in components. Each component is typically 63 quads. Required for create_landscape action.' },
436
443
  tool: {
437
444
  type: 'string',
438
- description: 'Sculpt tool (Sculpt, Smooth, Flatten, etc.)'
445
+ description: 'Landscape sculpt tool to use (Sculpt, Smooth, Flatten, Ramp, Erosion, Hydro, Noise). Required for sculpt action.'
439
446
  },
440
447
  // Advanced: procedural terrain
441
448
  location: {
442
449
  type: 'object',
443
- properties: { x: { type: 'number' }, y: { type: 'number' }, z: { type: 'number' } }
450
+ description: 'World space location for terrain placement. Required for create_procedural_terrain.',
451
+ properties: { x: { type: 'number', description: 'X coordinate' }, y: { type: 'number', description: 'Y coordinate' }, z: { type: 'number', description: 'Z coordinate' } }
444
452
  },
445
- subdivisions: { type: 'number' },
446
- heightFunction: { type: 'string' },
447
- materialPath: { type: 'string' },
453
+ subdivisions: { type: 'number', description: 'Number of subdivisions for procedural terrain mesh. Higher values create more detailed terrain. Optional for create_procedural_terrain.' },
454
+ heightFunction: { type: 'string', description: 'Mathematical function or algorithm for terrain height generation (e.g., "perlin", "simplex", custom formula). Optional for create_procedural_terrain.' },
455
+ materialPath: { type: 'string', description: 'Content path to material for terrain/landscape (e.g., "/Game/Materials/TerrainMat"). Optional.' },
448
456
  // Advanced: procedural foliage
449
457
  bounds: {
450
458
  type: 'object',
@@ -482,19 +490,20 @@ Supported actions: create_landscape, sculpt, add_foliage, paint_foliage, create_
482
490
  }
483
491
  },
484
492
  // Foliage (for add_foliage)
485
- meshPath: { type: 'string', description: 'Mesh path' },
486
- density: { type: 'number', description: 'Density' },
493
+ meshPath: { type: 'string', description: 'Content path to static mesh for foliage (e.g., "/Game/Foliage/TreeMesh"). Required for add_foliage action.' },
494
+ density: { type: 'number', description: 'Foliage placement density (instances per unit area). Typical range: 0.1 to 10.0. Required for add_foliage and affects procedural foliage.' },
487
495
  // Painting
488
496
  position: {
489
497
  type: 'object',
498
+ description: 'World space position for foliage paint brush center. Required for paint_foliage action.',
490
499
  properties: {
491
- x: { type: 'number' },
492
- y: { type: 'number' },
493
- z: { type: 'number' }
500
+ x: { type: 'number', description: 'X coordinate' },
501
+ y: { type: 'number', description: 'Y coordinate' },
502
+ z: { type: 'number', description: 'Z coordinate' }
494
503
  }
495
504
  },
496
- brushSize: { type: 'number', description: 'Brush size' },
497
- strength: { type: 'number', description: 'Tool strength' }
505
+ brushSize: { type: 'number', description: 'Radius of foliage paint brush in centimeters. Typical range: 500-5000. Required for paint_foliage action.' },
506
+ strength: { type: 'number', description: 'Paint tool strength/intensity (0.0 to 1.0). Higher values place more instances. Optional for paint_foliage, defaults to 0.5.' }
498
507
  },
499
508
  required: ['action']
500
509
  },
@@ -534,39 +543,40 @@ Supported actions: profile, show_fps, set_quality, play_sound, create_widget, sh
534
543
  // Performance
535
544
  profileType: {
536
545
  type: 'string',
537
- description: 'Profile type (CPU, GPU, Memory)'
546
+ description: 'Type of profiling to enable: CPU (stat cpu), GPU (stat gpu), Memory (stat memory), FPS (stat fps), Unit (stat unit). Required for profile action.'
538
547
  },
539
548
  category: {
540
549
  type: 'string',
541
- description: 'Quality category (Shadows, Textures, etc.)'
550
+ description: 'Scalability quality category to adjust: ViewDistance, AntiAliasing, Shadow/Shadows, PostProcess/PostProcessing, Texture/Textures, Effects, Foliage, Shading. Required for set_quality action.'
542
551
  },
543
- level: { type: 'number', description: 'Quality level (0-4)' },
544
- enabled: { type: 'boolean', description: 'Enable/disable' },
545
- verbose: { type: 'boolean', description: 'Verbose output' },
552
+ level: { type: 'number', description: 'Quality level (0=Low, 1=Medium, 2=High, 3=Epic, 4=Cinematic). Required for set_quality action.' },
553
+ enabled: { type: 'boolean', description: 'Enable (true) or disable (false) profiling/FPS display. Required for profile and show_fps actions.' },
554
+ verbose: { type: 'boolean', description: 'Show verbose profiling output with additional details. Optional for profile action.' },
546
555
  // Audio
547
- soundPath: { type: 'string', description: 'Sound asset path' },
556
+ soundPath: { type: 'string', description: 'Content path to sound asset (SoundCue or SoundWave, e.g., "/Game/Audio/MySound"). Required for play_sound action.' },
548
557
  location: {
549
558
  type: 'object',
559
+ description: 'World space location for 3D sound playback. Required if is3D is true for play_sound action.',
550
560
  properties: {
551
- x: { type: 'number' },
552
- y: { type: 'number' },
553
- z: { type: 'number' }
561
+ x: { type: 'number', description: 'X coordinate' },
562
+ y: { type: 'number', description: 'Y coordinate' },
563
+ z: { type: 'number', description: 'Z coordinate' }
554
564
  }
555
565
  },
556
- volume: { type: 'number', description: 'Volume (0-1)' },
557
- is3D: { type: 'boolean', description: '3D sound' },
566
+ volume: { type: 'number', description: 'Volume multiplier (0.0=silent, 1.0=full volume). Optional for play_sound, defaults to 1.0.' },
567
+ is3D: { type: 'boolean', description: 'Whether sound should be played as 3D positional audio (true) or 2D (false). Optional for play_sound, defaults to false.' },
558
568
  // UI
559
- widgetName: { type: 'string', description: 'Widget name' },
569
+ widgetName: { type: 'string', description: 'Name for widget asset or instance. Required for create_widget and show_widget actions.' },
560
570
  widgetType: {
561
571
  type: 'string',
562
- description: 'Widget type (HUD, Menu, etc.)'
572
+ description: 'Widget blueprint type or category (HUD, Menu, Dialog, Notification, etc.). Optional for create_widget, helps categorize the widget.'
563
573
  },
564
- visible: { type: 'boolean', description: 'Visibility' },
574
+ visible: { type: 'boolean', description: 'Whether widget should be visible (true) or hidden (false). Required for show_widget action.' },
565
575
  // Screenshot
566
- resolution: { type: 'string', description: 'e.g. 1920x1080' },
576
+ resolution: { type: 'string', description: 'Screenshot resolution in WIDTHxHEIGHT format (e.g., "1920x1080", "3840x2160"). Optional for screenshot action, uses viewport size if not specified.' },
567
577
  // Engine lifecycle
568
- projectPath: { type: 'string', description: 'Path to .uproject (for engine_start, optional if UE_PROJECT_PATH env set)' },
569
- editorExe: { type: 'string', description: 'Path to UE Editor executable (optional if UE_EDITOR_EXE env set)' }
578
+ projectPath: { type: 'string', description: 'Absolute path to .uproject file (e.g., "C:/Projects/MyGame/MyGame.uproject"). Required for engine_start unless UE_PROJECT_PATH environment variable is set.' },
579
+ editorExe: { type: 'string', description: 'Absolute path to Unreal Editor executable (e.g., "C:/UnrealEngine/Engine/Binaries/Win64/UnrealEditor.exe"). Required for engine_start unless UE_EDITOR_EXE environment variable is set.' }
570
580
  },
571
581
  required: ['action']
572
582
  },
@@ -598,7 +608,7 @@ Use it when higher-level tools don't cover the console tweak you need. Hazardous
598
608
  inputSchema: {
599
609
  type: 'object',
600
610
  properties: {
601
- command: { type: 'string', description: 'Console command to execute' }
611
+ command: { type: 'string', description: 'Console command to execute in Unreal Engine (e.g., "stat fps", "r.SetRes 1920x1080", "viewmode lit"). Dangerous commands like quit/exit and crash triggers are blocked. Required.' }
602
612
  },
603
613
  required: ['command']
604
614
  },
@@ -635,13 +645,13 @@ Supported actions: create_preset, expose_actor, expose_property, list_fields, se
635
645
  enum: ['create_preset', 'expose_actor', 'expose_property', 'list_fields', 'set_property', 'get_property'],
636
646
  description: 'RC action'
637
647
  },
638
- name: { type: 'string', description: 'Preset or entity name' },
639
- path: { type: 'string', description: 'Preset save path (e.g. /Game/RCPresets)' },
640
- presetPath: { type: 'string', description: 'Preset asset path (e.g. /Game/RCPresets/MyPreset)' },
641
- actorName: { type: 'string', description: 'Actor label/name to expose' },
642
- objectPath: { type: 'string', description: 'Object path for property get/set' },
643
- propertyName: { type: 'string', description: 'Property name for remote property set/get' },
644
- value: { description: 'Value for property set (JSON-serializable)' }
648
+ name: { type: 'string', description: 'Name for Remote Control preset asset. Required for create_preset action.' },
649
+ path: { type: 'string', description: 'Content path where preset will be saved (e.g., "/Game/RCPresets"). Required for create_preset action.' },
650
+ presetPath: { type: 'string', description: 'Full content path to existing Remote Control preset asset (e.g., "/Game/RCPresets/MyPreset"). Required for expose_actor, expose_property, list_fields, set_property, and get_property actions.' },
651
+ actorName: { type: 'string', description: 'Actor label/name in level to expose to Remote Control preset. Required for expose_actor action.' },
652
+ objectPath: { type: 'string', description: 'Full object path for property operations (e.g., "/Game/Maps/Level.Level:PersistentLevel.StaticMeshActor_0"). Required for expose_property, set_property, and get_property actions.' },
653
+ propertyName: { type: 'string', description: 'Name of the property to expose, get, or set (e.g., "RelativeLocation", "Intensity", "bHidden"). Required for expose_property, set_property, and get_property actions.' },
654
+ value: { description: 'New value to set for property. Must be JSON-serializable and compatible with property type (e.g., {"X":100,"Y":200,"Z":300} for location, true/false for bool, number for numeric types). Required for set_property action.' }
645
655
  },
646
656
  required: ['action']
647
657
  },
@@ -682,18 +692,18 @@ Supported actions: create, open, add_camera, add_actor, add_actors, remove_actor
682
692
  ],
683
693
  description: 'Sequence action'
684
694
  },
685
- name: { type: 'string', description: 'Sequence name (for create)' },
686
- path: { type: 'string', description: 'Save path (for create), or asset path (for open/operations)' },
687
- actorName: { type: 'string', description: 'Actor name to add as possessable' },
688
- actorNames: { type: 'array', items: { type: 'string' }, description: 'Multiple actor names for batch operations' },
689
- className: { type: 'string', description: 'Class name for spawnable (e.g. StaticMeshActor, CineCameraActor)' },
690
- spawnable: { type: 'boolean', description: 'If true, camera is spawnable' },
691
- frameRate: { type: 'number', description: 'Frame rate for sequence' },
692
- lengthInFrames: { type: 'number', description: 'Total length in frames' },
693
- playbackStart: { type: 'number', description: 'Playback start frame' },
694
- playbackEnd: { type: 'number', description: 'Playback end frame' },
695
- speed: { type: 'number', description: 'Playback speed multiplier' },
696
- loopMode: { type: 'string', enum: ['once', 'loop', 'pingpong'], description: 'Playback loop mode' }
695
+ name: { type: 'string', description: 'Name for new Level Sequence asset. Required for create action.' },
696
+ path: { type: 'string', description: 'Content path - for create action: save location (e.g., "/Game/Cinematics"); for open/operations: full asset path (e.g., "/Game/Cinematics/MySequence"). Required for create and open actions.' },
697
+ actorName: { type: 'string', description: 'Actor label/name in level to add as possessable binding to sequence. Required for add_actor action.' },
698
+ actorNames: { type: 'array', items: { type: 'string' }, description: 'Array of actor labels/names for batch add or remove operations. Required for add_actors and remove_actors actions.' },
699
+ className: { type: 'string', description: 'Unreal class name for spawnable actor (e.g., "StaticMeshActor", "CineCameraActor", "SkeletalMeshActor"). Required for add_spawnable_from_class action.' },
700
+ spawnable: { type: 'boolean', description: 'If true, camera is spawnable (owned by sequence); if false, camera is possessable (references level actor). Optional for add_camera, defaults to true.' },
701
+ frameRate: { type: 'number', description: 'Sequence frame rate in frames per second (e.g., 24, 30, 60). Required for set_properties when changing frame rate.' },
702
+ lengthInFrames: { type: 'number', description: 'Total sequence length measured in frames. Required for set_properties when changing duration.' },
703
+ playbackStart: { type: 'number', description: 'First frame of playback range (inclusive). Optional for set_properties.' },
704
+ playbackEnd: { type: 'number', description: 'Last frame of playback range (inclusive). Optional for set_properties.' },
705
+ speed: { type: 'number', description: 'Playback speed multiplier. 1.0 is normal speed, 2.0 is double speed, 0.5 is half speed. Required for set_playback_speed action.' },
706
+ loopMode: { type: 'string', enum: ['once', 'loop', 'pingpong'], description: 'How sequence loops: "once" plays once and stops, "loop" repeats from start, "pingpong" plays forward then backward. Optional for set_properties.' }
697
707
  },
698
708
  required: ['action']
699
709
  },
@@ -732,10 +742,10 @@ Supported actions: inspect_object, set_property.`,
732
742
  inputSchema: {
733
743
  type: 'object',
734
744
  properties: {
735
- action: { type: 'string', enum: ['inspect_object', 'set_property'], description: 'Inspection action' },
736
- objectPath: { type: 'string', description: 'Object path' },
737
- propertyName: { type: 'string', description: 'Property to set/get' },
738
- value: { description: 'Value to set (JSON-serializable)' }
745
+ action: { type: 'string', enum: ['inspect_object', 'set_property'], description: 'Introspection action: "inspect_object" retrieves all properties, "set_property" modifies a specific property. Required.' },
746
+ objectPath: { type: 'string', description: 'Full object path in Unreal format (e.g., "/Game/Maps/Level.Level:PersistentLevel.StaticMeshActor_0" or "/Script/Engine.Default__StaticMeshActor" for CDO). Required for both actions.' },
747
+ propertyName: { type: 'string', description: 'Name of the property to modify (e.g., "RelativeLocation", "Mobility", "bHidden"). Required for set_property action.' },
748
+ value: { description: 'New property value. Must be JSON-serializable and compatible with property type (e.g., {"X":100,"Y":0,"Z":0} for vectors, 5.0 for floats, true for bools, "Value" for strings). Required for set_property action.' }
739
749
  },
740
750
  required: ['action']
741
751
  },
@@ -86,14 +86,40 @@ try:
86
86
  editor_subsystem = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem)
87
87
  world = editor_subsystem.get_editor_world() if editor_subsystem and hasattr(editor_subsystem, 'get_editor_world') else None
88
88
  data_layer_manager = None
89
+ world_partition = None
89
90
  if world:
91
+ # Try multiple methods to access World Partition (UE 5.6+)
90
92
  try:
91
- world_partition = world.get_world_partition()
92
- result["worldPartition"] = world_partition is not None
93
- if result["worldPartition"] and hasattr(unreal, "WorldPartitionBlueprintLibrary"):
93
+ # Method 1: Try get_world_partition() if it exists
94
+ if hasattr(world, 'get_world_partition'):
95
+ world_partition = world.get_world_partition()
96
+ except (AttributeError, Exception):
97
+ pass
98
+
99
+ if not world_partition:
100
+ try:
101
+ # Method 2: Try WorldPartitionSubsystem
102
+ wp_subsystem = unreal.get_editor_subsystem(unreal.WorldPartitionSubsystem)
103
+ if wp_subsystem:
104
+ world_partition = wp_subsystem.get_world_partition(world)
105
+ except (AttributeError, Exception):
106
+ pass
107
+
108
+ if not world_partition:
109
+ try:
110
+ # Method 3: Check if world has world_partition property
111
+ if hasattr(world, 'world_partition'):
112
+ world_partition = world.world_partition
113
+ except (AttributeError, Exception):
114
+ pass
115
+
116
+ result["worldPartition"] = world_partition is not None
117
+
118
+ if result["worldPartition"] and hasattr(unreal, "WorldPartitionBlueprintLibrary"):
119
+ try:
94
120
  data_layer_manager = unreal.WorldPartitionBlueprintLibrary.get_data_layer_manager(world)
95
- except Exception as wp_error:
96
- result["warnings"].append(f"Failed to inspect world partition: {wp_error}")
121
+ except Exception as dlm_error:
122
+ result["warnings"].append(f"Data layer manager unavailable: {dlm_error}")
97
123
 
98
124
  actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
99
125
  if not actor_subsystem:
@@ -127,12 +153,33 @@ try:
127
153
  if not landscape_actor:
128
154
  result["error"] = "Failed to spawn landscape actor"
129
155
  else:
156
+ # Set label first
130
157
  try:
131
158
  landscape_actor.set_actor_label("${escapedName}", True)
132
159
  except TypeError:
133
160
  landscape_actor.set_actor_label("${escapedName}")
134
161
  except Exception as label_error:
135
162
  result["warnings"].append(f"Failed to set landscape label: {label_error}")
163
+
164
+ # Fix component registration by forcing re-registration
165
+ # This addresses the "RegisterComponentWithWorld: Trying to register component with IsValid() == false" warning
166
+ try:
167
+ # Get landscape components and re-register them
168
+ landscape_components = landscape_actor.get_components_by_class(unreal.LandscapeComponent)
169
+ if landscape_components:
170
+ for component in landscape_components:
171
+ if hasattr(component, 'register_component'):
172
+ try:
173
+ component.register_component()
174
+ except Exception:
175
+ pass
176
+ else:
177
+ # If no components yet, this is expected for LandscapePlaceholder
178
+ # The landscape needs to be "finalized" via editor tools or console commands
179
+ result["details"].append("Landscape placeholder created - finalize via editor for full functionality")
180
+ except Exception as comp_error:
181
+ # Component registration is best-effort; not critical
182
+ result["details"].append(f"Component registration attempted (editor finalization may be needed)")
136
183
 
137
184
  try:
138
185
  landscape_actor.set_actor_scale3d(unreal.Vector(${scaleX.toFixed(4)}, ${scaleY.toFixed(4)}, 1.0))
@@ -140,19 +187,34 @@ try:
140
187
  except Exception as scale_error:
141
188
  result["warnings"].append(f"Failed to set landscape scale: {scale_error}")
142
189
 
143
- landscape_editor = None
190
+ # Workaround for LandscapeEditorSubsystem Python API limitation
191
+ # Use direct property manipulation instead
192
+ landscape_configured = False
144
193
  try:
194
+ # Try LandscapeEditorSubsystem if available (may not be in Python API)
145
195
  landscape_editor = unreal.get_editor_subsystem(unreal.LandscapeEditorSubsystem)
146
- except Exception as editor_error:
147
- result["warnings"].append(f"LandscapeEditorSubsystem unavailable: {editor_error}")
148
-
149
- if landscape_editor:
196
+ if landscape_editor:
197
+ try:
198
+ landscape_editor.set_component_size(${sectionsPerComponent}, ${quadsPerSection})
199
+ landscape_editor.set_component_count(${componentCount}, ${componentCount})
200
+ result["details"].append(f"Component size ${sectionsPerComponent}x${quadsPerSection}, count ${componentCount}x${componentCount}")
201
+ landscape_configured = True
202
+ except Exception as config_error:
203
+ result["details"].append(f"LandscapeEditorSubsystem method limited: {config_error}")
204
+ except (AttributeError, Exception):
205
+ # Expected - LandscapeEditorSubsystem not available in Python API
206
+ pass
207
+
208
+ # Fallback: Configure via properties if subsystem not available
209
+ if not landscape_configured:
150
210
  try:
151
- landscape_editor.set_component_size(${sectionsPerComponent}, ${quadsPerSection})
152
- landscape_editor.set_component_count(${componentCount}, ${componentCount})
153
- result["details"].append(f"Component size ${sectionsPerComponent}x${quadsPerSection}, count ${componentCount}x${componentCount}")
154
- except Exception as config_error:
155
- result["warnings"].append(f"Landscape configuration limited: {config_error}")
211
+ # Set component properties directly
212
+ if hasattr(landscape_actor, 'set_editor_property'):
213
+ # Note: These properties may not be directly editable post-spawn
214
+ # This is documented UE limitation - landscape config is best done via editor tools
215
+ result["details"].append(f"Landscape spawned (config via editor tools recommended for ${sectionsPerComponent}x${quadsPerSection} components)")
216
+ except Exception:
217
+ pass
156
218
 
157
219
  ${escapedMaterial ? `try:
158
220
  material = unreal.EditorAssetLibrary.load_asset("${escapedMaterial}")