unreal-engine-mcp-server 0.2.1 → 0.3.1

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.
@@ -3,7 +3,18 @@ export const toolDefinitions = [
3
3
  // Asset Tools
4
4
  {
5
5
  name: 'list_assets',
6
- description: 'List all assets in a directory',
6
+ description: `List assets in a folder of the project.
7
+
8
+ When to use:
9
+ - Browse project content (use /Game; /Content is auto-mapped by the server).
10
+ - Get a quick inventory of assets in a subfolder to refine subsequent actions.
11
+
12
+ Notes:
13
+ - For /Game, the server may limit results for performance; prefer subfolders (e.g., /Game/ThirdPerson).
14
+ - Returns a structured list with Name/Path/Class/PackagePath when available.
15
+
16
+ Example:
17
+ - {"directory":"/Game/ThirdPerson","recursive":false}`,
7
18
  inputSchema: {
8
19
  type: 'object',
9
20
  properties: {
@@ -34,7 +45,17 @@ export const toolDefinitions = [
34
45
  },
35
46
  {
36
47
  name: 'import_asset',
37
- description: 'Import an asset from file system',
48
+ description: `Import a file from disk into the project (e.g., FBX, PNG, WAV, EXR).
49
+
50
+ When to use:
51
+ - Bring external content into /Game at a specific destination path.
52
+
53
+ Notes:
54
+ - destinationPath is a package path like /Game/Environment/Trees.
55
+ - Keep file names simple (avoid spaces and special characters).
56
+
57
+ Example:
58
+ - {"sourcePath":"C:/Temp/Tree.fbx","destinationPath":"/Game/Environment/Trees"}`,
38
59
  inputSchema: {
39
60
  type: 'object',
40
61
  properties: {
@@ -56,7 +77,17 @@ export const toolDefinitions = [
56
77
  // Actor Tools
57
78
  {
58
79
  name: 'spawn_actor',
59
- description: 'Spawn a new actor in the level',
80
+ description: `Spawn a new actor in the current level.
81
+
82
+ When to use:
83
+ - Place a class (e.g., StaticMeshActor, CameraActor) or spawn from an asset path (e.g., /Engine/BasicShapes/Cube).
84
+
85
+ Notes:
86
+ - If an asset path is provided, a StaticMeshActor is auto-spawned with the mesh set.
87
+ - location/rotation are optional; defaults are used if omitted.
88
+
89
+ Example:
90
+ - {"classPath":"/Engine/BasicShapes/Cube","location":{"x":0,"y":0,"z":100}}`,
60
91
  inputSchema: {
61
92
  type: 'object',
62
93
  properties: {
@@ -91,7 +122,13 @@ export const toolDefinitions = [
91
122
  },
92
123
  {
93
124
  name: 'delete_actor',
94
- description: 'Delete an actor from the level',
125
+ description: `Delete one or more actors by name/label.
126
+
127
+ When to use:
128
+ - Remove actors matching a label/name (case-insensitive).
129
+
130
+ Example:
131
+ - {"actorName":"Cube_1"}`,
95
132
  inputSchema: {
96
133
  type: 'object',
97
134
  properties: {
@@ -111,7 +148,13 @@ export const toolDefinitions = [
111
148
  // Material Tools
112
149
  {
113
150
  name: 'create_material',
114
- description: 'Create a new material asset',
151
+ description: `Create a simple Material asset at a path.
152
+
153
+ When to use:
154
+ - Quickly scaffold a basic material you can edit later.
155
+
156
+ Example:
157
+ - {"name":"M_Mask","path":"/Game/Materials"}`,
115
158
  inputSchema: {
116
159
  type: 'object',
117
160
  properties: {
@@ -132,7 +175,13 @@ export const toolDefinitions = [
132
175
  },
133
176
  {
134
177
  name: 'apply_material_to_actor',
135
- description: 'Apply a material to an actor in the level',
178
+ description: `Assign a material to an actor's mesh component.
179
+
180
+ When to use:
181
+ - Swap an actor's material by path; slotIndex defaults to 0.
182
+
183
+ Example:
184
+ - {"actorPath":"/Game/LevelActors/Cube_1","materialPath":"/Game/Materials/M_Mask","slotIndex":0}`,
136
185
  inputSchema: {
137
186
  type: 'object',
138
187
  properties: {
@@ -153,7 +202,10 @@ export const toolDefinitions = [
153
202
  // Editor Tools
154
203
  {
155
204
  name: 'play_in_editor',
156
- description: 'Start Play In Editor (PIE) mode',
205
+ description: `Start a Play-In-Editor (PIE) session.
206
+
207
+ When to use:
208
+ - Begin simulating the level in the editor.`,
157
209
  inputSchema: {
158
210
  type: 'object',
159
211
  properties: {}
@@ -169,7 +221,10 @@ export const toolDefinitions = [
169
221
  },
170
222
  {
171
223
  name: 'stop_play_in_editor',
172
- description: 'Stop Play In Editor (PIE) mode',
224
+ description: `Stop the active PIE session.
225
+
226
+ When to use:
227
+ - End simulation and return to the editor.`,
173
228
  inputSchema: {
174
229
  type: 'object',
175
230
  properties: {}
@@ -185,7 +240,16 @@ export const toolDefinitions = [
185
240
  },
186
241
  {
187
242
  name: 'set_camera',
188
- description: 'Set viewport camera position and rotation',
243
+ description: `Reposition the editor viewport camera.
244
+
245
+ When to use:
246
+ - Move/aim the camera in the editor for framing.
247
+
248
+ Notes:
249
+ - Accepts object or array formats; values are normalized.
250
+
251
+ Example:
252
+ - {"location":{"x":0,"y":-600,"z":250},"rotation":{"pitch":0,"yaw":0,"roll":0}}`,
189
253
  inputSchema: {
190
254
  type: 'object',
191
255
  properties: {
@@ -220,7 +284,13 @@ export const toolDefinitions = [
220
284
  // Animation Tools
221
285
  {
222
286
  name: 'create_animation_blueprint',
223
- description: 'Create an animation blueprint',
287
+ description: `Create an Animation Blueprint for a skeleton.
288
+
289
+ When to use:
290
+ - Generate a starter Anim BP for a given skeleton.
291
+
292
+ Example:
293
+ - {"name":"ABP_Hero","skeletonPath":"/Game/Characters/Hero/SK_Hero_Skeleton","savePath":"/Game/Characters/Hero"}`,
224
294
  inputSchema: {
225
295
  type: 'object',
226
296
  properties: {
@@ -241,7 +311,13 @@ export const toolDefinitions = [
241
311
  },
242
312
  {
243
313
  name: 'play_animation_montage',
244
- description: 'Play an animation montage on an actor',
314
+ description: `Play a Montage/Animation on an actor.
315
+
316
+ When to use:
317
+ - Trigger a montage on a possessed or editor actor.
318
+
319
+ Example:
320
+ - {"actorName":"Hero","montagePath":"/Game/Anim/MT_Attack","playRate":1.0}`,
245
321
  inputSchema: {
246
322
  type: 'object',
247
323
  properties: {
@@ -263,7 +339,13 @@ export const toolDefinitions = [
263
339
  // Physics Tools
264
340
  {
265
341
  name: 'setup_ragdoll',
266
- description: 'Setup ragdoll physics for a skeletal mesh',
342
+ description: `Enable simple ragdoll using a physics asset.
343
+
344
+ When to use:
345
+ - Toggle ragdoll behavior on a character skeleton.
346
+
347
+ Example:
348
+ - {"skeletonPath":"/Game/Characters/Hero/SK_Hero_Skeleton","physicsAssetName":"PHYS_Hero","blendWeight":1.0}`,
267
349
  inputSchema: {
268
350
  type: 'object',
269
351
  properties: {
@@ -284,7 +366,10 @@ export const toolDefinitions = [
284
366
  },
285
367
  {
286
368
  name: 'apply_force',
287
- description: 'Apply force to an actor',
369
+ description: `Apply a world-space force vector to an actor with physics enabled.
370
+
371
+ Example:
372
+ - {"actorName":"PhysicsBox","force":{"x":0,"y":0,"z":5000}}`,
288
373
  inputSchema: {
289
374
  type: 'object',
290
375
  properties: {
@@ -313,7 +398,13 @@ export const toolDefinitions = [
313
398
  // Niagara Tools
314
399
  {
315
400
  name: 'create_particle_effect',
316
- description: 'Create a Niagara particle effect',
401
+ description: `Create a simple particle/FX by tag.
402
+
403
+ When to use:
404
+ - Quickly drop a generic Fire/Smoke/Water effect for previews.
405
+
406
+ Example:
407
+ - {"effectType":"Smoke","name":"SMK1","location":{"x":100,"y":0,"z":50}}`,
317
408
  inputSchema: {
318
409
  type: 'object',
319
410
  properties: {
@@ -342,7 +433,10 @@ export const toolDefinitions = [
342
433
  },
343
434
  {
344
435
  name: 'spawn_niagara_system',
345
- description: 'Spawn a Niagara system in the level',
436
+ description: `Spawn a Niagara system at a location.
437
+
438
+ Example:
439
+ - {"systemPath":"/Game/FX/NS_Explosion","location":{"x":0,"y":0,"z":200},"scale":1.0}`,
346
440
  inputSchema: {
347
441
  type: 'object',
348
442
  properties: {
@@ -371,7 +465,10 @@ export const toolDefinitions = [
371
465
  // Blueprint Tools
372
466
  {
373
467
  name: 'create_blueprint',
374
- description: 'Create a new blueprint',
468
+ description: `Create a new Blueprint asset at a path.
469
+
470
+ Example:
471
+ - {"name":"BP_Switch","blueprintType":"Actor","savePath":"/Game/Blueprints"}`,
375
472
  inputSchema: {
376
473
  type: 'object',
377
474
  properties: {
@@ -392,7 +489,10 @@ export const toolDefinitions = [
392
489
  },
393
490
  {
394
491
  name: 'add_blueprint_component',
395
- description: 'Add a component to a blueprint',
492
+ description: `Add a component to an existing Blueprint.
493
+
494
+ Example:
495
+ - {"blueprintName":"BP_Switch","componentType":"PointLightComponent","componentName":"KeyLight"}`,
396
496
  inputSchema: {
397
497
  type: 'object',
398
498
  properties: {
@@ -415,7 +515,10 @@ export const toolDefinitions = [
415
515
  // Level Tools
416
516
  {
417
517
  name: 'load_level',
418
- description: 'Load a level',
518
+ description: `Load a level by path (e.g., /Game/Maps/Lobby).
519
+
520
+ Example:
521
+ - {"levelPath":"/Game/Maps/Lobby","streaming":false}`,
419
522
  inputSchema: {
420
523
  type: 'object',
421
524
  properties: {
@@ -435,7 +538,10 @@ export const toolDefinitions = [
435
538
  },
436
539
  {
437
540
  name: 'save_level',
438
- description: 'Save the current level',
541
+ description: `Save the current level to a path or by name.
542
+
543
+ Example:
544
+ - {"levelName":"Lobby","savePath":"/Game/Maps"}`,
439
545
  inputSchema: {
440
546
  type: 'object',
441
547
  properties: {
@@ -454,7 +560,10 @@ export const toolDefinitions = [
454
560
  },
455
561
  {
456
562
  name: 'stream_level',
457
- description: 'Stream a level in or out',
563
+ description: `Stream in/out a sublevel and set visibility.
564
+
565
+ Example:
566
+ - {"levelName":"Sublevel_A","shouldBeLoaded":true,"shouldBeVisible":true}`,
458
567
  inputSchema: {
459
568
  type: 'object',
460
569
  properties: {
@@ -477,7 +586,11 @@ export const toolDefinitions = [
477
586
  // Lighting Tools
478
587
  {
479
588
  name: 'create_light',
480
- description: 'Create a light in the level',
589
+ description: `Create a light (Directional/Point/Spot/Rect/Sky) with optional transform/intensity.
590
+
591
+ Examples:
592
+ - {"lightType":"Directional","name":"KeyLight","intensity":5.0}
593
+ - {"lightType":"Point","name":"Fill","location":{"x":0,"y":100,"z":200},"intensity":2000}`,
481
594
  inputSchema: {
482
595
  type: 'object',
483
596
  properties: {
@@ -506,7 +619,13 @@ export const toolDefinitions = [
506
619
  },
507
620
  {
508
621
  name: 'build_lighting',
509
- description: 'Build lighting for the current level',
622
+ description: `Start a lighting build.
623
+
624
+ When to use:
625
+ - Bake lights for preview or final output (choose quality).
626
+
627
+ Example:
628
+ - {"quality":"High"}`,
510
629
  inputSchema: {
511
630
  type: 'object',
512
631
  properties: {
@@ -525,7 +644,13 @@ export const toolDefinitions = [
525
644
  // Landscape Tools
526
645
  {
527
646
  name: 'create_landscape',
528
- description: 'Create a new landscape',
647
+ description: `Attempt to create a landscape.
648
+
649
+ Notes:
650
+ - Native Python APIs are limited; you may be guided to use Landscape Mode in the editor.
651
+
652
+ Example:
653
+ - {"name":"Landscape_Basic","sizeX":1024,"sizeY":1024}`,
529
654
  inputSchema: {
530
655
  type: 'object',
531
656
  properties: {
@@ -547,7 +672,10 @@ export const toolDefinitions = [
547
672
  },
548
673
  {
549
674
  name: 'sculpt_landscape',
550
- description: 'Sculpt the landscape',
675
+ description: `Sculpt a landscape using editor tools (best-effort; some operations may require manual Landscape Mode).
676
+
677
+ Example:
678
+ - {"landscapeName":"Landscape_Basic","tool":"Smooth","brushSize":300,"strength":0.5}`,
551
679
  inputSchema: {
552
680
  type: 'object',
553
681
  properties: {
@@ -569,7 +697,10 @@ export const toolDefinitions = [
569
697
  // Foliage Tools
570
698
  {
571
699
  name: 'add_foliage_type',
572
- description: 'Add a foliage type',
700
+ description: `Create or load a FoliageType asset for instanced foliage workflows.
701
+
702
+ Example:
703
+ - {"name":"FT_Grass","meshPath":"/Game/Foliage/SM_Grass","density":300}`,
573
704
  inputSchema: {
574
705
  type: 'object',
575
706
  properties: {
@@ -590,7 +721,13 @@ export const toolDefinitions = [
590
721
  },
591
722
  {
592
723
  name: 'paint_foliage',
593
- description: 'Paint foliage on landscape',
724
+ description: `Paint foliage onto the world.
725
+
726
+ When to use:
727
+ - Scatter instances using an existing FoliageType.
728
+
729
+ Example:
730
+ - {"foliageType":"/Game/Foliage/Types/FT_Grass","position":{"x":0,"y":0,"z":0},"brushSize":300}`,
594
731
  inputSchema: {
595
732
  type: 'object',
596
733
  properties: {
@@ -619,7 +756,10 @@ export const toolDefinitions = [
619
756
  // Debug Visualization Tools
620
757
  {
621
758
  name: 'draw_debug_shape',
622
- description: 'Draw a debug shape',
759
+ description: `Draw a debug shape.
760
+
761
+ Example:
762
+ - {"shape":"Sphere","position":{"x":0,"y":0,"z":0},"size":100,"color":[255,0,0,255],"duration":3}`,
623
763
  inputSchema: {
624
764
  type: 'object',
625
765
  properties: {
@@ -652,7 +792,10 @@ export const toolDefinitions = [
652
792
  },
653
793
  {
654
794
  name: 'set_view_mode',
655
- description: 'Set the viewport view mode',
795
+ description: `Set the viewport view mode.
796
+
797
+ Example:
798
+ - {"mode":"Wireframe"}`,
656
799
  inputSchema: {
657
800
  type: 'object',
658
801
  properties: {
@@ -672,7 +815,10 @@ export const toolDefinitions = [
672
815
  // Performance Tools
673
816
  {
674
817
  name: 'start_profiling',
675
- description: 'Start performance profiling',
818
+ description: `Start performance profiling.
819
+
820
+ Example:
821
+ - {"type":"GPU","duration":10}`,
676
822
  inputSchema: {
677
823
  type: 'object',
678
824
  properties: {
@@ -692,7 +838,10 @@ export const toolDefinitions = [
692
838
  },
693
839
  {
694
840
  name: 'show_fps',
695
- description: 'Show FPS counter',
841
+ description: `Show/hide the FPS counter.
842
+
843
+ Example:
844
+ - {"enabled":true,"verbose":false}`,
696
845
  inputSchema: {
697
846
  type: 'object',
698
847
  properties: {
@@ -712,7 +861,10 @@ export const toolDefinitions = [
712
861
  },
713
862
  {
714
863
  name: 'set_scalability',
715
- description: 'Set scalability settings',
864
+ description: `Set scalability/quality levels.
865
+
866
+ Example:
867
+ - {"category":"Shadows","level":2}`,
716
868
  inputSchema: {
717
869
  type: 'object',
718
870
  properties: {
@@ -733,7 +885,10 @@ export const toolDefinitions = [
733
885
  // Audio Tools
734
886
  {
735
887
  name: 'play_sound',
736
- description: 'Play a sound',
888
+ description: `Play a sound.
889
+
890
+ Example:
891
+ - {"soundPath":"/Game/Audio/SFX/Click","volume":0.5,"is3D":true}`,
737
892
  inputSchema: {
738
893
  type: 'object',
739
894
  properties: {
@@ -762,7 +917,10 @@ export const toolDefinitions = [
762
917
  },
763
918
  {
764
919
  name: 'create_ambient_sound',
765
- description: 'Create an ambient sound',
920
+ description: `Create an ambient sound actor.
921
+
922
+ Example:
923
+ - {"name":"Amb_Wind","soundPath":"/Game/Audio/Amb/AMB_Wind","location":{"x":0,"y":0,"z":0},"radius":1000}`,
766
924
  inputSchema: {
767
925
  type: 'object',
768
926
  properties: {
@@ -792,7 +950,10 @@ export const toolDefinitions = [
792
950
  // UI Tools
793
951
  {
794
952
  name: 'create_widget',
795
- description: 'Create a UI widget',
953
+ description: `Create a UI widget.
954
+
955
+ Example:
956
+ - {"name":"HUDMain","type":"HUD","savePath":"/Game/UI"}`,
796
957
  inputSchema: {
797
958
  type: 'object',
798
959
  properties: {
@@ -813,7 +974,10 @@ export const toolDefinitions = [
813
974
  },
814
975
  {
815
976
  name: 'show_widget',
816
- description: 'Show or hide a widget',
977
+ description: `Show or hide a widget.
978
+
979
+ Example:
980
+ - {"widgetName":"HUDMain","visible":true}`,
817
981
  inputSchema: {
818
982
  type: 'object',
819
983
  properties: {
@@ -833,7 +997,10 @@ export const toolDefinitions = [
833
997
  },
834
998
  {
835
999
  name: 'create_hud',
836
- description: 'Create a HUD',
1000
+ description: `Create a HUD description/layout.
1001
+
1002
+ Example:
1003
+ - {"name":"GameHUD","elements":[{"type":"Text","position":[10,10]}]}`,
837
1004
  inputSchema: {
838
1005
  type: 'object',
839
1006
  properties: {
@@ -866,7 +1033,14 @@ export const toolDefinitions = [
866
1033
  // Console command (universal tool)
867
1034
  {
868
1035
  name: 'console_command',
869
- description: 'Execute any console command in Unreal Engine',
1036
+ description: `Execute a console command.
1037
+
1038
+ When to use:
1039
+ - Quick toggles like "stat fps", "viewmode wireframe", or r.* cvars.
1040
+
1041
+ Examples:
1042
+ - {"command":"stat fps"}
1043
+ - {"command":"r.ScreenPercentage 75"}`,
870
1044
  inputSchema: {
871
1045
  type: 'object',
872
1046
  properties: {
@@ -32,15 +32,23 @@ export async function handleToolCall(name, args, tools) {
32
32
  message = 'Failed to list assets: directory path cannot be empty';
33
33
  break;
34
34
  }
35
+ // Normalize virtual content path: map /Content -> /Game (case-insensitive)
36
+ const rawDir = String(args.directory).trim();
37
+ let normDir = rawDir.replace(/^\/?content(\/|$)/i, '/Game$1');
38
+ // Ensure leading slash
39
+ if (!normDir.startsWith('/'))
40
+ normDir = '/' + normDir;
41
+ // Collapse duplicate slashes
42
+ normDir = normDir.replace(/\\+/g, '/').replace(/\/+/g, '/');
35
43
  // Try multiple approaches to list assets
36
44
  try {
37
- console.log('[list_assets] Starting asset listing for directory:', args.directory);
38
- // First try: Use Python for most reliable listing
45
+ console.log('[list_assets] Starting asset listing for directory:', normDir);
46
+ // First try: Use Python for most reliable listing (recursive if /Game)
39
47
  const pythonCode = `
40
48
  import unreal
41
49
  import json
42
50
 
43
- directory = '${args.directory || '/Game'}'
51
+ directory = '${normDir || '/Game'}'
44
52
  # Use recursive for /Game to find assets in subdirectories, but limit depth
45
53
  recursive = True if directory == '/Game' else False
46
54
 
@@ -141,8 +149,9 @@ except Exception as e:
141
149
  const searchResult = await tools.bridge.httpCall('/remote/search/assets', 'PUT', {
142
150
  Query: '', // Empty query to match all (wildcard doesn't work)
143
151
  Filter: {
144
- PackagePaths: [args.directory || '/Game'],
145
- RecursivePaths: false, // Always non-recursive
152
+ PackagePaths: [normDir || '/Game'],
153
+ // Recursively search so we actually find assets in subfolders
154
+ RecursivePaths: true,
146
155
  ClassNames: [], // Empty to get all types
147
156
  RecursiveClasses: true
148
157
  },
@@ -165,7 +174,7 @@ except Exception as e:
165
174
  functionName: 'ExecuteConsoleCommand',
166
175
  parameters: {
167
176
  WorldContextObject: null,
168
- Command: `AssetRegistry.DumpAssets ${args.directory || '/Game'}`,
177
+ Command: `AssetRegistry.DumpAssets ${normDir || '/Game'}`,
169
178
  SpecificPlayer: null
170
179
  },
171
180
  generateTransaction: false
@@ -186,6 +195,24 @@ except Exception as e:
186
195
  }
187
196
  // Include full asset list with details in the message
188
197
  console.log('[list_assets] Formatting message - result has assets?', !!(result && result.assets), 'count:', result?.assets?.length);
198
+ if (result && result.assets && result.assets.length > 0) {
199
+ // If Python/HTTP gives only paths, generate Name from path
200
+ result.assets = result.assets.map((asset) => {
201
+ if (!asset.Name && asset.Path) {
202
+ const base = String(asset.Path).split('/').pop() || '';
203
+ const name = base.includes('.') ? base.split('.').pop() : base;
204
+ return { ...asset, Name: name };
205
+ }
206
+ return asset;
207
+ });
208
+ // Group assets by type for better organization
209
+ result.assets = result.assets.map((a) => {
210
+ if (a && !a.Path && a.AssetPath) {
211
+ return { ...a, Path: a.AssetPath, PackagePath: a.AssetPath.split('/').slice(0, -1).join('/') };
212
+ }
213
+ return a;
214
+ });
215
+ }
189
216
  if (result && result.assets && result.assets.length > 0) {
190
217
  // Group assets by type for better organization
191
218
  const assetsByType = {};
@@ -197,7 +224,7 @@ except Exception as e:
197
224
  assetsByType[type].push(asset);
198
225
  });
199
226
  // Format output with proper structure
200
- let assetDetails = `📁 Asset Directory: ${args.directory || '/Game'}\n`;
227
+ let assetDetails = `📁 Asset Directory: ${normDir || '/Game'}\n`;
201
228
  assetDetails += `📊 Total Assets: ${result.assets.length}\n\n`;
202
229
  // Sort types alphabetically
203
230
  const sortedTypes = Object.keys(assetsByType).sort();
@@ -223,7 +250,7 @@ except Exception as e:
223
250
  // Also keep the structured data in the result for programmatic access
224
251
  }
225
252
  else {
226
- message = `No assets found in ${args.directory || '/Game'}`;
253
+ message = `No assets found in ${normDir || '/Game'}`;
227
254
  }
228
255
  break;
229
256
  case 'import_asset':
@@ -529,7 +556,13 @@ print(f"RESULT:{json.dumps(result)}")
529
556
  // Landscape Tools
530
557
  case 'create_landscape':
531
558
  result = await tools.landscapeTools.createLandscape(args);
532
- message = result.message || `Landscape ${args.name} created`;
559
+ // Never claim success unless the tool says so; prefer error/message from UE/Python
560
+ if (result && typeof result === 'object') {
561
+ message = result.message || result.error || (result.success ? `Landscape ${args.name} created` : `Failed to create landscape ${args.name}`);
562
+ }
563
+ else {
564
+ message = `Failed to create landscape ${args.name}`;
565
+ }
533
566
  break;
534
567
  case 'sculpt_landscape':
535
568
  result = await tools.landscapeTools.sculptLandscape(args);
@@ -14,6 +14,7 @@ export declare class UnrealBridge {
14
14
  private reconnectAttempts;
15
15
  private readonly MAX_RECONNECT_ATTEMPTS;
16
16
  private readonly BASE_RECONNECT_DELAY;
17
+ private autoReconnectEnabled;
17
18
  private commandQueue;
18
19
  private isProcessing;
19
20
  private readonly MIN_COMMAND_DELAY;
@@ -32,6 +33,7 @@ export declare class UnrealBridge {
32
33
  * @param retryDelayMs Delay between retry attempts in milliseconds
33
34
  * @returns Promise that resolves when connected or rejects after all attempts fail
34
35
  */
36
+ private connectPromise?;
35
37
  tryConnect(maxAttempts?: number, timeoutMs?: number, retryDelayMs?: number): Promise<boolean>;
36
38
  connect(timeoutMs?: number): Promise<void>;
37
39
  httpCall<T = any>(path: string, method?: 'GET' | 'POST' | 'PUT', body?: any): Promise<T>;
@@ -39,6 +41,7 @@ export declare class UnrealBridge {
39
41
  getExposed(): Promise<any>;
40
42
  executeConsoleCommand(command: string): Promise<any>;
41
43
  executePython(command: string): Promise<any>;
44
+ setAutoReconnectEnabled(enabled: boolean): void;
42
45
  private scheduleReconnect;
43
46
  disconnect(): Promise<void>;
44
47
  /**
@@ -49,7 +52,7 @@ export declare class UnrealBridge {
49
52
  /**
50
53
  * Execute Python script and parse the result
51
54
  */
52
- private executePythonWithResult;
55
+ executePythonWithResult(script: string): Promise<any>;
53
56
  /**
54
57
  * Get the Unreal Engine version via Python and parse major/minor/patch.
55
58
  */