unreal-engine-mcp-server 0.3.1 → 0.4.3
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.
- package/.env.production +1 -1
- package/.github/copilot-instructions.md +45 -0
- package/.github/workflows/publish-mcp.yml +1 -1
- package/README.md +22 -7
- package/dist/index.js +137 -46
- package/dist/prompts/index.d.ts +10 -3
- package/dist/prompts/index.js +186 -7
- package/dist/resources/actors.d.ts +19 -1
- package/dist/resources/actors.js +55 -64
- package/dist/resources/assets.d.ts +3 -2
- package/dist/resources/assets.js +117 -109
- package/dist/resources/levels.d.ts +21 -3
- package/dist/resources/levels.js +31 -56
- package/dist/tools/actors.d.ts +3 -14
- package/dist/tools/actors.js +246 -302
- package/dist/tools/animation.d.ts +57 -102
- package/dist/tools/animation.js +429 -450
- package/dist/tools/assets.d.ts +13 -2
- package/dist/tools/assets.js +58 -46
- package/dist/tools/audio.d.ts +22 -13
- package/dist/tools/audio.js +467 -121
- package/dist/tools/blueprint.d.ts +32 -13
- package/dist/tools/blueprint.js +699 -448
- package/dist/tools/build_environment_advanced.d.ts +0 -1
- package/dist/tools/build_environment_advanced.js +236 -87
- package/dist/tools/consolidated-tool-definitions.d.ts +232 -15
- package/dist/tools/consolidated-tool-definitions.js +124 -255
- package/dist/tools/consolidated-tool-handlers.js +749 -766
- package/dist/tools/debug.d.ts +72 -10
- package/dist/tools/debug.js +170 -36
- package/dist/tools/editor.d.ts +9 -2
- package/dist/tools/editor.js +30 -44
- package/dist/tools/foliage.d.ts +34 -15
- package/dist/tools/foliage.js +97 -107
- package/dist/tools/introspection.js +19 -21
- package/dist/tools/landscape.d.ts +1 -2
- package/dist/tools/landscape.js +311 -168
- package/dist/tools/level.d.ts +3 -28
- package/dist/tools/level.js +642 -192
- package/dist/tools/lighting.d.ts +14 -3
- package/dist/tools/lighting.js +236 -123
- package/dist/tools/materials.d.ts +25 -7
- package/dist/tools/materials.js +102 -79
- package/dist/tools/niagara.d.ts +10 -12
- package/dist/tools/niagara.js +74 -94
- package/dist/tools/performance.d.ts +12 -4
- package/dist/tools/performance.js +38 -79
- package/dist/tools/physics.d.ts +34 -10
- package/dist/tools/physics.js +364 -292
- package/dist/tools/rc.js +98 -24
- package/dist/tools/sequence.d.ts +1 -0
- package/dist/tools/sequence.js +146 -24
- package/dist/tools/ui.d.ts +31 -4
- package/dist/tools/ui.js +83 -66
- package/dist/tools/visual.d.ts +11 -0
- package/dist/tools/visual.js +245 -30
- package/dist/types/tool-types.d.ts +0 -6
- package/dist/types/tool-types.js +1 -8
- package/dist/unreal-bridge.d.ts +32 -2
- package/dist/unreal-bridge.js +621 -127
- package/dist/utils/elicitation.d.ts +57 -0
- package/dist/utils/elicitation.js +104 -0
- package/dist/utils/error-handler.d.ts +0 -33
- package/dist/utils/error-handler.js +4 -111
- package/dist/utils/http.d.ts +2 -22
- package/dist/utils/http.js +12 -75
- package/dist/utils/normalize.d.ts +4 -4
- package/dist/utils/normalize.js +15 -7
- package/dist/utils/python-output.d.ts +18 -0
- package/dist/utils/python-output.js +290 -0
- package/dist/utils/python.d.ts +2 -0
- package/dist/utils/python.js +4 -0
- package/dist/utils/response-validator.d.ts +6 -1
- package/dist/utils/response-validator.js +66 -13
- package/dist/utils/result-helpers.d.ts +27 -0
- package/dist/utils/result-helpers.js +147 -0
- package/dist/utils/safe-json.d.ts +0 -2
- package/dist/utils/safe-json.js +0 -43
- package/dist/utils/validation.d.ts +16 -0
- package/dist/utils/validation.js +70 -7
- package/mcp-config-example.json +2 -2
- package/package.json +11 -10
- package/server.json +37 -14
- package/src/index.ts +146 -50
- package/src/prompts/index.ts +211 -13
- package/src/resources/actors.ts +59 -44
- package/src/resources/assets.ts +123 -102
- package/src/resources/levels.ts +37 -47
- package/src/tools/actors.ts +269 -313
- package/src/tools/animation.ts +556 -539
- package/src/tools/assets.ts +59 -45
- package/src/tools/audio.ts +507 -113
- package/src/tools/blueprint.ts +778 -462
- package/src/tools/build_environment_advanced.ts +312 -106
- package/src/tools/consolidated-tool-definitions.ts +136 -267
- package/src/tools/consolidated-tool-handlers.ts +871 -795
- package/src/tools/debug.ts +179 -38
- package/src/tools/editor.ts +35 -37
- package/src/tools/foliage.ts +110 -104
- package/src/tools/introspection.ts +24 -22
- package/src/tools/landscape.ts +334 -181
- package/src/tools/level.ts +683 -182
- package/src/tools/lighting.ts +244 -123
- package/src/tools/materials.ts +114 -83
- package/src/tools/niagara.ts +87 -81
- package/src/tools/performance.ts +49 -88
- package/src/tools/physics.ts +393 -299
- package/src/tools/rc.ts +103 -25
- package/src/tools/sequence.ts +157 -30
- package/src/tools/ui.ts +101 -70
- package/src/tools/visual.ts +250 -29
- package/src/types/tool-types.ts +0 -9
- package/src/unreal-bridge.ts +658 -140
- package/src/utils/elicitation.ts +129 -0
- package/src/utils/error-handler.ts +4 -159
- package/src/utils/http.ts +16 -115
- package/src/utils/normalize.ts +20 -10
- package/src/utils/python-output.ts +351 -0
- package/src/utils/python.ts +3 -0
- package/src/utils/response-validator.ts +68 -17
- package/src/utils/result-helpers.ts +193 -0
- package/src/utils/safe-json.ts +0 -50
- package/src/utils/validation.ts +94 -7
- package/tests/run-unreal-tool-tests.mjs +720 -0
- package/tsconfig.json +2 -2
- package/dist/python-utils.d.ts +0 -29
- package/dist/python-utils.js +0 -54
- package/dist/tools/tool-definitions.d.ts +0 -4919
- package/dist/tools/tool-definitions.js +0 -1065
- package/dist/tools/tool-handlers.d.ts +0 -47
- package/dist/tools/tool-handlers.js +0 -863
- package/dist/types/index.d.ts +0 -323
- package/dist/types/index.js +0 -28
- package/dist/utils/cache-manager.d.ts +0 -64
- package/dist/utils/cache-manager.js +0 -176
- package/dist/utils/errors.d.ts +0 -133
- package/dist/utils/errors.js +0 -256
- package/src/python/editor_compat.py +0 -181
- package/src/python-utils.ts +0 -57
- package/src/tools/tool-definitions.ts +0 -1081
- package/src/tools/tool-handlers.ts +0 -973
- package/src/types/index.ts +0 -414
- package/src/utils/cache-manager.ts +0 -213
- package/src/utils/errors.ts +0 -312
package/dist/tools/assets.d.ts
CHANGED
|
@@ -5,13 +5,24 @@ export declare class AssetTools {
|
|
|
5
5
|
importAsset(sourcePath: string, destinationPath: string): Promise<{
|
|
6
6
|
success: boolean;
|
|
7
7
|
message: string;
|
|
8
|
-
|
|
8
|
+
imported: number;
|
|
9
|
+
paths: string[];
|
|
9
10
|
error?: undefined;
|
|
11
|
+
details?: undefined;
|
|
10
12
|
} | {
|
|
13
|
+
success: boolean;
|
|
14
|
+
message: string;
|
|
15
|
+
error: string;
|
|
16
|
+
details: string | undefined;
|
|
17
|
+
imported?: undefined;
|
|
18
|
+
paths?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
success: boolean;
|
|
11
21
|
error: string;
|
|
12
|
-
success?: undefined;
|
|
13
22
|
message?: undefined;
|
|
23
|
+
imported?: undefined;
|
|
14
24
|
paths?: undefined;
|
|
25
|
+
details?: undefined;
|
|
15
26
|
}>;
|
|
16
27
|
duplicateAsset(sourcePath: string, destinationPath: string): Promise<any>;
|
|
17
28
|
deleteAsset(assetPath: string): Promise<any>;
|
package/dist/tools/assets.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { bestEffortInterpretedText, coerceNumber, coerceStringArray, interpretStandardResult } from '../utils/result-helpers.js';
|
|
3
4
|
export class AssetTools {
|
|
4
5
|
bridge;
|
|
5
6
|
constructor(bridge) {
|
|
6
7
|
this.bridge = bridge;
|
|
7
8
|
}
|
|
8
9
|
async importAsset(sourcePath, destinationPath) {
|
|
10
|
+
let createdTestFile = false;
|
|
9
11
|
try {
|
|
10
|
-
// Sanitize destination path (remove trailing slash)
|
|
11
|
-
|
|
12
|
+
// Sanitize destination path (remove trailing slash) and normalize UE path
|
|
13
|
+
let cleanDest = destinationPath.replace(/\/$/, '');
|
|
14
|
+
// Map /Content -> /Game for UE asset destinations
|
|
15
|
+
if (/^\/?content(\/|$)/i.test(cleanDest)) {
|
|
16
|
+
cleanDest = '/Game' + cleanDest.replace(/^\/?content/i, '');
|
|
17
|
+
}
|
|
12
18
|
// Create test FBX file if it's a test file
|
|
13
19
|
if (sourcePath.includes('test_model.fbx')) {
|
|
14
20
|
// Create the file outside of Python, before import
|
|
15
21
|
try {
|
|
16
|
-
this.createTestFBX(sourcePath);
|
|
22
|
+
await this.createTestFBX(sourcePath);
|
|
23
|
+
createdTestFile = true;
|
|
17
24
|
}
|
|
18
25
|
catch (_err) {
|
|
19
26
|
// If we can't create the file, we'll handle it in Python
|
|
@@ -23,6 +30,7 @@ export class AssetTools {
|
|
|
23
30
|
const pythonCode = `
|
|
24
31
|
import unreal
|
|
25
32
|
import os
|
|
33
|
+
import json
|
|
26
34
|
|
|
27
35
|
# Create test FBX if needed
|
|
28
36
|
source_path = r'${sourcePath}'
|
|
@@ -143,54 +151,57 @@ task.options = options
|
|
|
143
151
|
|
|
144
152
|
# Use AssetTools to import
|
|
145
153
|
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
|
|
154
|
+
result = {'success': False, 'error': 'No assets imported', 'source': task.filename}
|
|
155
|
+
|
|
146
156
|
try:
|
|
147
157
|
asset_tools.import_asset_tasks([task])
|
|
148
158
|
if task.imported_object_paths:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
159
|
+
result = {
|
|
160
|
+
'success': True,
|
|
161
|
+
'imported': len(task.imported_object_paths),
|
|
162
|
+
'paths': list(task.imported_object_paths)
|
|
163
|
+
}
|
|
152
164
|
except Exception as e:
|
|
153
|
-
|
|
165
|
+
result = {'success': False, 'error': str(e), 'source': task.filename}
|
|
166
|
+
|
|
167
|
+
print('RESULT:' + json.dumps(result))
|
|
154
168
|
`.trim();
|
|
155
169
|
const pyResp = await this.bridge.executePython(pythonCode);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
else {
|
|
170
|
-
outputStr = String(pyResp || '');
|
|
170
|
+
const interpreted = interpretStandardResult(pyResp, {
|
|
171
|
+
successMessage: `Imported assets to ${cleanDest}`,
|
|
172
|
+
failureMessage: 'Import failed'
|
|
173
|
+
});
|
|
174
|
+
if (interpreted.success) {
|
|
175
|
+
const count = coerceNumber(interpreted.payload.imported) ?? 0;
|
|
176
|
+
const paths = coerceStringArray(interpreted.payload.paths) ?? [];
|
|
177
|
+
return {
|
|
178
|
+
success: true,
|
|
179
|
+
message: `Imported ${count} assets to ${cleanDest}`,
|
|
180
|
+
imported: count,
|
|
181
|
+
paths
|
|
182
|
+
};
|
|
171
183
|
}
|
|
172
|
-
const
|
|
173
|
-
|
|
184
|
+
const errorMessage = `Import failed: ${interpreted.error ?? 'Unknown error'} (source: ${interpreted.payload.source ?? sourcePath})`;
|
|
185
|
+
return {
|
|
186
|
+
success: false,
|
|
187
|
+
message: errorMessage,
|
|
188
|
+
error: errorMessage,
|
|
189
|
+
details: bestEffortInterpretedText(interpreted)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
return { success: false, error: `Failed to import asset: ${err}` };
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
if (createdTestFile) {
|
|
174
197
|
try {
|
|
175
|
-
|
|
176
|
-
if (parsed.success) {
|
|
177
|
-
const count = parsed.imported?.count ?? 0;
|
|
178
|
-
const paths = parsed.imported?.paths ?? [];
|
|
179
|
-
return { success: true, message: `Imported ${count} assets to ${cleanDest}`, paths };
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
return { error: `Import failed: ${parsed.error || 'Unknown error'} (source: ${parsed.source || sourcePath})` };
|
|
183
|
-
}
|
|
198
|
+
await fs.rm(sourcePath, { force: true });
|
|
184
199
|
}
|
|
185
|
-
catch {
|
|
186
|
-
//
|
|
200
|
+
catch (cleanupError) {
|
|
201
|
+
// Swallow cleanup error but log for debug visibility
|
|
202
|
+
console.warn(`Failed to clean up temporary FBX ${sourcePath}:`, cleanupError);
|
|
187
203
|
}
|
|
188
204
|
}
|
|
189
|
-
// If unable to parse, return generic attempt result
|
|
190
|
-
return { error: `Import did not report success for source ${sourcePath}` };
|
|
191
|
-
}
|
|
192
|
-
catch (err) {
|
|
193
|
-
return { error: `Failed to import asset: ${err}` };
|
|
194
205
|
}
|
|
195
206
|
}
|
|
196
207
|
async duplicateAsset(sourcePath, destinationPath) {
|
|
@@ -239,7 +250,7 @@ except Exception as e:
|
|
|
239
250
|
return { error: `Failed to save asset: ${err}` };
|
|
240
251
|
}
|
|
241
252
|
}
|
|
242
|
-
createTestFBX(filePath) {
|
|
253
|
+
async createTestFBX(filePath) {
|
|
243
254
|
// Create a minimal valid FBX ASCII file for testing
|
|
244
255
|
const fbxContent = `; FBX 7.5.0 project file
|
|
245
256
|
FBXHeaderExtension: {
|
|
@@ -294,11 +305,12 @@ Connections: {
|
|
|
294
305
|
`;
|
|
295
306
|
// Ensure directory exists
|
|
296
307
|
const dir = path.dirname(filePath);
|
|
297
|
-
|
|
298
|
-
fs.
|
|
308
|
+
try {
|
|
309
|
+
await fs.mkdir(dir, { recursive: true });
|
|
299
310
|
}
|
|
311
|
+
catch { }
|
|
300
312
|
// Write the FBX file
|
|
301
|
-
fs.
|
|
313
|
+
await fs.writeFile(filePath, fbxContent, 'utf8');
|
|
302
314
|
}
|
|
303
315
|
}
|
|
304
316
|
//# sourceMappingURL=assets.js.map
|
package/dist/tools/audio.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { UnrealBridge } from '../unreal-bridge.js';
|
|
|
2
2
|
export declare class AudioTools {
|
|
3
3
|
private bridge;
|
|
4
4
|
constructor(bridge: UnrealBridge);
|
|
5
|
-
private
|
|
5
|
+
private interpretResult;
|
|
6
6
|
createSoundCue(params: {
|
|
7
7
|
name: string;
|
|
8
8
|
wavePath?: string;
|
|
@@ -14,13 +14,16 @@ export declare class AudioTools {
|
|
|
14
14
|
attenuationSettings?: string;
|
|
15
15
|
};
|
|
16
16
|
}): Promise<{
|
|
17
|
-
success:
|
|
17
|
+
success: true;
|
|
18
18
|
message: string;
|
|
19
|
-
|
|
19
|
+
details?: string;
|
|
20
|
+
} | {
|
|
21
|
+
success: false;
|
|
22
|
+
error: string;
|
|
23
|
+
details?: string;
|
|
20
24
|
} | {
|
|
21
25
|
success: boolean;
|
|
22
|
-
error:
|
|
23
|
-
message?: undefined;
|
|
26
|
+
error: string;
|
|
24
27
|
}>;
|
|
25
28
|
playSoundAtLocation(params: {
|
|
26
29
|
soundPath: string;
|
|
@@ -29,13 +32,16 @@ export declare class AudioTools {
|
|
|
29
32
|
pitch?: number;
|
|
30
33
|
startTime?: number;
|
|
31
34
|
}): Promise<{
|
|
32
|
-
success:
|
|
35
|
+
success: true;
|
|
33
36
|
message: string;
|
|
34
|
-
|
|
37
|
+
details?: string;
|
|
38
|
+
} | {
|
|
39
|
+
success: false;
|
|
40
|
+
error: string;
|
|
41
|
+
details?: string;
|
|
35
42
|
} | {
|
|
36
43
|
success: boolean;
|
|
37
|
-
error:
|
|
38
|
-
message?: undefined;
|
|
44
|
+
error: string;
|
|
39
45
|
}>;
|
|
40
46
|
playSound2D(params: {
|
|
41
47
|
soundPath: string;
|
|
@@ -43,13 +49,16 @@ export declare class AudioTools {
|
|
|
43
49
|
pitch?: number;
|
|
44
50
|
startTime?: number;
|
|
45
51
|
}): Promise<{
|
|
46
|
-
success:
|
|
52
|
+
success: true;
|
|
47
53
|
message: string;
|
|
48
|
-
|
|
54
|
+
details?: string;
|
|
55
|
+
} | {
|
|
56
|
+
success: false;
|
|
57
|
+
error: string;
|
|
58
|
+
details?: string;
|
|
49
59
|
} | {
|
|
50
60
|
success: boolean;
|
|
51
|
-
error:
|
|
52
|
-
message?: undefined;
|
|
61
|
+
error: string;
|
|
53
62
|
}>;
|
|
54
63
|
createAudioComponent(params: {
|
|
55
64
|
actorName: string;
|