unreal-engine-mcp-server 0.2.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.
- package/.dockerignore +57 -0
- package/.env.production +25 -0
- package/.eslintrc.json +54 -0
- package/.github/workflows/publish-mcp.yml +75 -0
- package/Dockerfile +54 -0
- package/LICENSE +21 -0
- package/Public/icon.png +0 -0
- package/README.md +209 -0
- package/claude_desktop_config_example.json +13 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +7 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +484 -0
- package/dist/prompts/index.d.ts +14 -0
- package/dist/prompts/index.js +38 -0
- package/dist/python-utils.d.ts +29 -0
- package/dist/python-utils.js +54 -0
- package/dist/resources/actors.d.ts +13 -0
- package/dist/resources/actors.js +83 -0
- package/dist/resources/assets.d.ts +23 -0
- package/dist/resources/assets.js +245 -0
- package/dist/resources/levels.d.ts +17 -0
- package/dist/resources/levels.js +94 -0
- package/dist/tools/actors.d.ts +51 -0
- package/dist/tools/actors.js +459 -0
- package/dist/tools/animation.d.ts +196 -0
- package/dist/tools/animation.js +579 -0
- package/dist/tools/assets.d.ts +21 -0
- package/dist/tools/assets.js +304 -0
- package/dist/tools/audio.d.ts +170 -0
- package/dist/tools/audio.js +416 -0
- package/dist/tools/blueprint.d.ts +144 -0
- package/dist/tools/blueprint.js +652 -0
- package/dist/tools/build_environment_advanced.d.ts +66 -0
- package/dist/tools/build_environment_advanced.js +484 -0
- package/dist/tools/consolidated-tool-definitions.d.ts +2598 -0
- package/dist/tools/consolidated-tool-definitions.js +607 -0
- package/dist/tools/consolidated-tool-handlers.d.ts +2 -0
- package/dist/tools/consolidated-tool-handlers.js +1050 -0
- package/dist/tools/debug.d.ts +185 -0
- package/dist/tools/debug.js +265 -0
- package/dist/tools/editor.d.ts +88 -0
- package/dist/tools/editor.js +365 -0
- package/dist/tools/engine.d.ts +30 -0
- package/dist/tools/engine.js +36 -0
- package/dist/tools/foliage.d.ts +155 -0
- package/dist/tools/foliage.js +525 -0
- package/dist/tools/introspection.d.ts +98 -0
- package/dist/tools/introspection.js +683 -0
- package/dist/tools/landscape.d.ts +158 -0
- package/dist/tools/landscape.js +375 -0
- package/dist/tools/level.d.ts +110 -0
- package/dist/tools/level.js +362 -0
- package/dist/tools/lighting.d.ts +159 -0
- package/dist/tools/lighting.js +1179 -0
- package/dist/tools/materials.d.ts +34 -0
- package/dist/tools/materials.js +146 -0
- package/dist/tools/niagara.d.ts +145 -0
- package/dist/tools/niagara.js +289 -0
- package/dist/tools/performance.d.ts +163 -0
- package/dist/tools/performance.js +412 -0
- package/dist/tools/physics.d.ts +189 -0
- package/dist/tools/physics.js +784 -0
- package/dist/tools/rc.d.ts +110 -0
- package/dist/tools/rc.js +363 -0
- package/dist/tools/sequence.d.ts +112 -0
- package/dist/tools/sequence.js +675 -0
- package/dist/tools/tool-definitions.d.ts +4919 -0
- package/dist/tools/tool-definitions.js +891 -0
- package/dist/tools/tool-handlers.d.ts +47 -0
- package/dist/tools/tool-handlers.js +830 -0
- package/dist/tools/ui.d.ts +171 -0
- package/dist/tools/ui.js +337 -0
- package/dist/tools/visual.d.ts +29 -0
- package/dist/tools/visual.js +67 -0
- package/dist/types/env.d.ts +10 -0
- package/dist/types/env.js +18 -0
- package/dist/types/index.d.ts +323 -0
- package/dist/types/index.js +28 -0
- package/dist/types/tool-types.d.ts +274 -0
- package/dist/types/tool-types.js +13 -0
- package/dist/unreal-bridge.d.ts +126 -0
- package/dist/unreal-bridge.js +992 -0
- package/dist/utils/cache-manager.d.ts +64 -0
- package/dist/utils/cache-manager.js +176 -0
- package/dist/utils/error-handler.d.ts +66 -0
- package/dist/utils/error-handler.js +243 -0
- package/dist/utils/errors.d.ts +133 -0
- package/dist/utils/errors.js +256 -0
- package/dist/utils/http.d.ts +26 -0
- package/dist/utils/http.js +135 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/normalize.d.ts +17 -0
- package/dist/utils/normalize.js +49 -0
- package/dist/utils/response-validator.d.ts +34 -0
- package/dist/utils/response-validator.js +121 -0
- package/dist/utils/safe-json.d.ts +4 -0
- package/dist/utils/safe-json.js +97 -0
- package/dist/utils/stdio-redirect.d.ts +2 -0
- package/dist/utils/stdio-redirect.js +20 -0
- package/dist/utils/validation.d.ts +50 -0
- package/dist/utils/validation.js +173 -0
- package/mcp-config-example.json +14 -0
- package/package.json +63 -0
- package/server.json +60 -0
- package/src/cli.ts +7 -0
- package/src/index.ts +543 -0
- package/src/prompts/index.ts +51 -0
- package/src/python/editor_compat.py +181 -0
- package/src/python-utils.ts +57 -0
- package/src/resources/actors.ts +92 -0
- package/src/resources/assets.ts +251 -0
- package/src/resources/levels.ts +83 -0
- package/src/tools/actors.ts +480 -0
- package/src/tools/animation.ts +713 -0
- package/src/tools/assets.ts +305 -0
- package/src/tools/audio.ts +548 -0
- package/src/tools/blueprint.ts +736 -0
- package/src/tools/build_environment_advanced.ts +526 -0
- package/src/tools/consolidated-tool-definitions.ts +619 -0
- package/src/tools/consolidated-tool-handlers.ts +1093 -0
- package/src/tools/debug.ts +368 -0
- package/src/tools/editor.ts +360 -0
- package/src/tools/engine.ts +32 -0
- package/src/tools/foliage.ts +652 -0
- package/src/tools/introspection.ts +778 -0
- package/src/tools/landscape.ts +523 -0
- package/src/tools/level.ts +410 -0
- package/src/tools/lighting.ts +1316 -0
- package/src/tools/materials.ts +148 -0
- package/src/tools/niagara.ts +312 -0
- package/src/tools/performance.ts +549 -0
- package/src/tools/physics.ts +924 -0
- package/src/tools/rc.ts +437 -0
- package/src/tools/sequence.ts +791 -0
- package/src/tools/tool-definitions.ts +907 -0
- package/src/tools/tool-handlers.ts +941 -0
- package/src/tools/ui.ts +499 -0
- package/src/tools/visual.ts +60 -0
- package/src/types/env.ts +27 -0
- package/src/types/index.ts +414 -0
- package/src/types/tool-types.ts +343 -0
- package/src/unreal-bridge.ts +1118 -0
- package/src/utils/cache-manager.ts +213 -0
- package/src/utils/error-handler.ts +320 -0
- package/src/utils/errors.ts +312 -0
- package/src/utils/http.ts +184 -0
- package/src/utils/logger.ts +30 -0
- package/src/utils/normalize.ts +54 -0
- package/src/utils/response-validator.ts +145 -0
- package/src/utils/safe-json.ts +112 -0
- package/src/utils/stdio-redirect.ts +18 -0
- package/src/utils/validation.ts +212 -0
- package/tsconfig.json +33 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Utility to safely serialize objects with circular references
|
|
2
|
+
export function safeStringify(obj, space) {
|
|
3
|
+
const seen = new WeakSet();
|
|
4
|
+
return JSON.stringify(obj, (key, value) => {
|
|
5
|
+
// Handle undefined, functions, symbols
|
|
6
|
+
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
// Handle circular references
|
|
10
|
+
if (typeof value === 'object' && value !== null) {
|
|
11
|
+
if (seen.has(value)) {
|
|
12
|
+
return '[Circular Reference]';
|
|
13
|
+
}
|
|
14
|
+
seen.add(value);
|
|
15
|
+
}
|
|
16
|
+
// Handle BigInt
|
|
17
|
+
if (typeof value === 'bigint') {
|
|
18
|
+
return value.toString();
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}, space);
|
|
22
|
+
}
|
|
23
|
+
export function sanitizeResponse(response) {
|
|
24
|
+
if (!response || typeof response !== 'object') {
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
// Create a clean copy without circular references
|
|
28
|
+
try {
|
|
29
|
+
const jsonStr = safeStringify(response);
|
|
30
|
+
return JSON.parse(jsonStr);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Failed to sanitize response:', error);
|
|
34
|
+
// Fallback: return a simple error response
|
|
35
|
+
return {
|
|
36
|
+
content: [{
|
|
37
|
+
type: 'text',
|
|
38
|
+
text: 'Response contained unserializable data'
|
|
39
|
+
}],
|
|
40
|
+
error: 'Serialization error'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Remove circular references and non-serializable properties from an object
|
|
45
|
+
export function cleanObject(obj, maxDepth = 10) {
|
|
46
|
+
const seen = new WeakSet();
|
|
47
|
+
function clean(value, depth, path = 'root') {
|
|
48
|
+
// Prevent infinite recursion
|
|
49
|
+
if (depth > maxDepth) {
|
|
50
|
+
return '[Max depth reached]';
|
|
51
|
+
}
|
|
52
|
+
// Handle primitives
|
|
53
|
+
if (value === null || value === undefined) {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value !== 'object') {
|
|
57
|
+
if (typeof value === 'function' || typeof value === 'symbol') {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value === 'bigint') {
|
|
61
|
+
return value.toString();
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
// Check for circular reference
|
|
66
|
+
if (seen.has(value)) {
|
|
67
|
+
return '[Circular Reference]';
|
|
68
|
+
}
|
|
69
|
+
seen.add(value);
|
|
70
|
+
// Handle arrays
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
const result = value.map((item, index) => clean(item, depth + 1, `${path}[${index}]`));
|
|
73
|
+
seen.delete(value); // Remove from seen after processing
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
// Handle objects
|
|
77
|
+
const cleaned = {};
|
|
78
|
+
// Use Object.keys to avoid prototype properties
|
|
79
|
+
const keys = Object.keys(value);
|
|
80
|
+
for (const key of keys) {
|
|
81
|
+
try {
|
|
82
|
+
const cleanedValue = clean(value[key], depth + 1, `${path}.${key}`);
|
|
83
|
+
if (cleanedValue !== undefined) {
|
|
84
|
+
cleaned[key] = cleanedValue;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
// Skip properties that throw errors when accessed
|
|
89
|
+
console.error(`Error cleaning property ${path}.${key}:`, e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
seen.delete(value); // Remove from seen after processing
|
|
93
|
+
return cleaned;
|
|
94
|
+
}
|
|
95
|
+
return clean(obj, 0);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=safe-json.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function routeStdoutLogsToStderr() {
|
|
2
|
+
// Enable by default. Allow opt-out with LOG_TO_STDERR=false or JSON_STDOUT_MODE=false
|
|
3
|
+
const flagRaw = String(process.env.LOG_TO_STDERR ?? process.env.JSON_STDOUT_MODE ?? 'true').toLowerCase();
|
|
4
|
+
const enabled = !(flagRaw === 'false' || flagRaw === '0' || flagRaw === 'off' || flagRaw === 'no');
|
|
5
|
+
if (!enabled)
|
|
6
|
+
return;
|
|
7
|
+
try {
|
|
8
|
+
const toErr = console.error.bind(console);
|
|
9
|
+
// Route common stdout channels to stderr to keep stdout JSON-only for MCP
|
|
10
|
+
console.log = toErr;
|
|
11
|
+
console.info = toErr;
|
|
12
|
+
console.debug = toErr;
|
|
13
|
+
// Be explicit with trace as well
|
|
14
|
+
console.trace = toErr;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// If overriding fails for any reason, just continue silently.
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=stdio-redirect.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation and sanitization utilities for Unreal Engine assets
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Sanitize an asset name for Unreal Engine
|
|
6
|
+
* @param name The name to sanitize
|
|
7
|
+
* @returns Sanitized name
|
|
8
|
+
*/
|
|
9
|
+
export declare function sanitizeAssetName(name: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Sanitize a path for Unreal Engine
|
|
12
|
+
* @param path The path to sanitize
|
|
13
|
+
* @returns Sanitized path
|
|
14
|
+
*/
|
|
15
|
+
export declare function sanitizePath(path: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Validate path length
|
|
18
|
+
* @param path The full path to validate
|
|
19
|
+
* @returns Object with validation result
|
|
20
|
+
*/
|
|
21
|
+
export declare function validatePathLength(path: string): {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
error?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Validate and sanitize asset parameters
|
|
27
|
+
* @param params Object containing name and optionally savePath
|
|
28
|
+
* @returns Sanitized parameters with validation result
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateAssetParams(params: {
|
|
31
|
+
name: string;
|
|
32
|
+
savePath?: string;
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
}): {
|
|
35
|
+
valid: boolean;
|
|
36
|
+
sanitized: typeof params;
|
|
37
|
+
error?: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Extract valid skeletal mesh path from various inputs
|
|
41
|
+
* @param input The input path which might be a skeleton or mesh
|
|
42
|
+
* @returns Corrected skeletal mesh path or null
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveSkeletalMeshPath(input: string): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Concurrency delay to prevent race conditions
|
|
47
|
+
* @param ms Milliseconds to delay
|
|
48
|
+
*/
|
|
49
|
+
export declare function concurrencyDelay(ms?: number): Promise<void>;
|
|
50
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation and sanitization utilities for Unreal Engine assets
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Maximum path length allowed in Unreal Engine
|
|
6
|
+
*/
|
|
7
|
+
const MAX_PATH_LENGTH = 260;
|
|
8
|
+
/**
|
|
9
|
+
* Invalid characters for Unreal Engine asset names
|
|
10
|
+
* Note: Dashes are allowed in Unreal asset names
|
|
11
|
+
*/
|
|
12
|
+
// eslint-disable-next-line no-useless-escape
|
|
13
|
+
const INVALID_CHARS = /[@#%$&*()+=\[\]{}<>?|\\;:'"`,~!\s]/g;
|
|
14
|
+
/**
|
|
15
|
+
* Reserved keywords that shouldn't be used as names
|
|
16
|
+
*/
|
|
17
|
+
const RESERVED_KEYWORDS = [
|
|
18
|
+
'None', 'null', 'undefined', 'true', 'false',
|
|
19
|
+
'class', 'struct', 'enum', 'interface',
|
|
20
|
+
'default', 'transient', 'native'
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Sanitize an asset name for Unreal Engine
|
|
24
|
+
* @param name The name to sanitize
|
|
25
|
+
* @returns Sanitized name
|
|
26
|
+
*/
|
|
27
|
+
export function sanitizeAssetName(name) {
|
|
28
|
+
if (!name || typeof name !== 'string') {
|
|
29
|
+
return 'Asset';
|
|
30
|
+
}
|
|
31
|
+
// Remove leading/trailing whitespace
|
|
32
|
+
let sanitized = name.trim();
|
|
33
|
+
// Replace invalid characters with underscores
|
|
34
|
+
sanitized = sanitized.replace(INVALID_CHARS, '_');
|
|
35
|
+
// Remove consecutive underscores
|
|
36
|
+
sanitized = sanitized.replace(/_+/g, '_');
|
|
37
|
+
// Remove leading/trailing underscores
|
|
38
|
+
sanitized = sanitized.replace(/^_+|_+$/g, '');
|
|
39
|
+
// If name is empty after sanitization, use default
|
|
40
|
+
if (!sanitized) {
|
|
41
|
+
return 'Asset';
|
|
42
|
+
}
|
|
43
|
+
// If name is a reserved keyword, append underscore
|
|
44
|
+
if (RESERVED_KEYWORDS.includes(sanitized)) {
|
|
45
|
+
sanitized = `${sanitized}_Asset`;
|
|
46
|
+
}
|
|
47
|
+
// Ensure name starts with a letter
|
|
48
|
+
if (!/^[A-Za-z]/.test(sanitized)) {
|
|
49
|
+
sanitized = `Asset_${sanitized}`;
|
|
50
|
+
}
|
|
51
|
+
// Truncate overly long names to reduce risk of hitting path length limits
|
|
52
|
+
if (sanitized.length > 64) {
|
|
53
|
+
sanitized = sanitized.slice(0, 64);
|
|
54
|
+
}
|
|
55
|
+
return sanitized;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sanitize a path for Unreal Engine
|
|
59
|
+
* @param path The path to sanitize
|
|
60
|
+
* @returns Sanitized path
|
|
61
|
+
*/
|
|
62
|
+
export function sanitizePath(path) {
|
|
63
|
+
if (!path || typeof path !== 'string') {
|
|
64
|
+
return '/Game';
|
|
65
|
+
}
|
|
66
|
+
// Ensure path starts with /
|
|
67
|
+
if (!path.startsWith('/')) {
|
|
68
|
+
path = `/${path}`;
|
|
69
|
+
}
|
|
70
|
+
// Split path into segments and sanitize each
|
|
71
|
+
const segments = path.split('/').filter(s => s.length > 0);
|
|
72
|
+
const sanitizedSegments = segments.map(segment => {
|
|
73
|
+
// Don't sanitize Game, Engine, or other root folders
|
|
74
|
+
if (['Game', 'Engine', 'Script', 'Temp'].includes(segment)) {
|
|
75
|
+
return segment;
|
|
76
|
+
}
|
|
77
|
+
return sanitizeAssetName(segment);
|
|
78
|
+
});
|
|
79
|
+
// Reconstruct path
|
|
80
|
+
const sanitizedPath = '/' + sanitizedSegments.join('/');
|
|
81
|
+
return sanitizedPath;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate path length
|
|
85
|
+
* @param path The full path to validate
|
|
86
|
+
* @returns Object with validation result
|
|
87
|
+
*/
|
|
88
|
+
export function validatePathLength(path) {
|
|
89
|
+
if (path.length > MAX_PATH_LENGTH) {
|
|
90
|
+
return {
|
|
91
|
+
valid: false,
|
|
92
|
+
error: `Path too long (${path.length} characters). Maximum allowed is ${MAX_PATH_LENGTH} characters.`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return { valid: true };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validate and sanitize asset parameters
|
|
99
|
+
* @param params Object containing name and optionally savePath
|
|
100
|
+
* @returns Sanitized parameters with validation result
|
|
101
|
+
*/
|
|
102
|
+
export function validateAssetParams(params) {
|
|
103
|
+
// Sanitize name
|
|
104
|
+
const sanitizedName = sanitizeAssetName(params.name);
|
|
105
|
+
// Sanitize path if provided
|
|
106
|
+
const sanitizedPath = params.savePath
|
|
107
|
+
? sanitizePath(params.savePath)
|
|
108
|
+
: params.savePath;
|
|
109
|
+
// Construct full path for validation
|
|
110
|
+
const fullPath = sanitizedPath
|
|
111
|
+
? `${sanitizedPath}/${sanitizedName}`
|
|
112
|
+
: `/Game/${sanitizedName}`;
|
|
113
|
+
// Validate path length
|
|
114
|
+
const pathValidation = validatePathLength(fullPath);
|
|
115
|
+
if (!pathValidation.valid) {
|
|
116
|
+
return {
|
|
117
|
+
valid: false,
|
|
118
|
+
sanitized: params,
|
|
119
|
+
error: pathValidation.error
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
valid: true,
|
|
124
|
+
sanitized: {
|
|
125
|
+
...params,
|
|
126
|
+
name: sanitizedName,
|
|
127
|
+
...(sanitizedPath && { savePath: sanitizedPath })
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Extract valid skeletal mesh path from various inputs
|
|
133
|
+
* @param input The input path which might be a skeleton or mesh
|
|
134
|
+
* @returns Corrected skeletal mesh path or null
|
|
135
|
+
*/
|
|
136
|
+
export function resolveSkeletalMeshPath(input) {
|
|
137
|
+
if (!input || typeof input !== 'string') {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
// Common skeleton to mesh mappings
|
|
141
|
+
const skeletonToMeshMap = {
|
|
142
|
+
'/Game/Mannequin/Character/Mesh/UE4_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Manny',
|
|
143
|
+
'/Game/Characters/Mannequins/Meshes/SK_Mannequin': '/Game/Characters/Mannequins/Meshes/SKM_Manny',
|
|
144
|
+
'/Game/Mannequin/Character/Mesh/SK_Mannequin': '/Game/Characters/Mannequins/Meshes/SKM_Manny',
|
|
145
|
+
'/Game/Characters/Mannequin_UE4/Meshes/UE4_Mannequin_Skeleton': '/Game/Characters/Mannequins/Meshes/SKM_Quinn',
|
|
146
|
+
};
|
|
147
|
+
// Check if this is a known skeleton path
|
|
148
|
+
if (skeletonToMeshMap[input]) {
|
|
149
|
+
return skeletonToMeshMap[input];
|
|
150
|
+
}
|
|
151
|
+
// If it contains _Skeleton, try to convert to mesh name
|
|
152
|
+
if (input.includes('_Skeleton')) {
|
|
153
|
+
// Try common replacements
|
|
154
|
+
let meshPath = input.replace('_Skeleton', '');
|
|
155
|
+
meshPath = meshPath.replace('/SK_', '/SKM_');
|
|
156
|
+
meshPath = meshPath.replace('UE4_Mannequin', 'SKM_Manny');
|
|
157
|
+
return meshPath;
|
|
158
|
+
}
|
|
159
|
+
// If it starts with SK_ (skeleton prefix), try SKM_ (skeletal mesh prefix)
|
|
160
|
+
if (input.includes('/SK_')) {
|
|
161
|
+
return input.replace('/SK_', '/SKM_');
|
|
162
|
+
}
|
|
163
|
+
// Return as-is if no conversion needed
|
|
164
|
+
return input;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Concurrency delay to prevent race conditions
|
|
168
|
+
* @param ms Milliseconds to delay
|
|
169
|
+
*/
|
|
170
|
+
export async function concurrencyDelay(ms = 100) {
|
|
171
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"unreal-engine": {
|
|
4
|
+
"command": "node",
|
|
5
|
+
"args": ["PATH_TO/unreal-engine-mcp-server/dist/cli.js"],
|
|
6
|
+
"env": {
|
|
7
|
+
"UE_HOST": "127.0.0.1",
|
|
8
|
+
"UE_RC_WS_PORT": "30010",
|
|
9
|
+
"UE_RC_HTTP_PORT": "30020",
|
|
10
|
+
"UE_PROJECT_PATH": "C:/Users/YourName/Documents/Unreal Projects/YourProject"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "unreal-engine-mcp-server",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Production-ready MCP server for Unreal Engine integration with consolidated and individual tool modes",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"unreal-mcp-server": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.json",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"test:live": "node test-introspection-live.js",
|
|
15
|
+
"dev": "ts-node-esm src/index.ts",
|
|
16
|
+
"lint": "eslint . --ext .ts",
|
|
17
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
18
|
+
"clean": "rimraf dist",
|
|
19
|
+
"prepare": "npm run build",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"test:coverage": "vitest run --coverage",
|
|
23
|
+
"test:tool4": "vitest run src/tests/consolidated-tool-4.test.ts"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"mcp",
|
|
30
|
+
"modelcontextprotocol",
|
|
31
|
+
"unreal",
|
|
32
|
+
"unreal-engine",
|
|
33
|
+
"ue5",
|
|
34
|
+
"remote-control",
|
|
35
|
+
"automation",
|
|
36
|
+
"game-development"
|
|
37
|
+
],
|
|
38
|
+
"author": "Unreal Engine MCP Team",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"mcpName": "io.github.ChiR24/unreal-engine-mcp",
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@modelcontextprotocol/sdk": "^1.4.0",
|
|
43
|
+
"ajv": "^8.12.0",
|
|
44
|
+
"axios": "^1.7.2",
|
|
45
|
+
"dotenv": "^16.4.5",
|
|
46
|
+
"ws": "^8.18.0",
|
|
47
|
+
"yargs": "^17.7.2",
|
|
48
|
+
"zod": "^3.22.4"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^20.12.7",
|
|
52
|
+
"@types/ws": "^8.5.10",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
|
54
|
+
"@typescript-eslint/parser": "^8.43.0",
|
|
55
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
56
|
+
"cross-env": "^10.0.0",
|
|
57
|
+
"eslint": "^8.57.0",
|
|
58
|
+
"rimraf": "^6.0.1",
|
|
59
|
+
"ts-node": "^10.9.2",
|
|
60
|
+
"typescript": "^5.4.5",
|
|
61
|
+
"vitest": "^1.6.0"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
|
|
3
|
+
"name": "io.github.ChiR24/unreal-engine-mcp",
|
|
4
|
+
"description": "Production-ready MCP server for Unreal Engine with comprehensive game development tools",
|
|
5
|
+
"version": "0.2.1",
|
|
6
|
+
"packages": [
|
|
7
|
+
{
|
|
8
|
+
"registry_type": "npm",
|
|
9
|
+
"registry_base_url": "https://registry.npmjs.org",
|
|
10
|
+
"identifier": "unreal-engine-mcp-server",
|
|
11
|
+
"version": "0.2.1",
|
|
12
|
+
"transport": {
|
|
13
|
+
"type": "stdio"
|
|
14
|
+
},
|
|
15
|
+
"environment_variables": [
|
|
16
|
+
{
|
|
17
|
+
"name": "UE_HOST",
|
|
18
|
+
"description": "Unreal Engine host address",
|
|
19
|
+
"is_required": false,
|
|
20
|
+
"value": "127.0.0.1"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "UE_RC_HTTP_PORT",
|
|
24
|
+
"description": "Remote Control HTTP port",
|
|
25
|
+
"is_required": false,
|
|
26
|
+
"value": "30010"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "UE_RC_WS_PORT",
|
|
30
|
+
"description": "Remote Control WebSocket port",
|
|
31
|
+
"is_required": false,
|
|
32
|
+
"value": "30020"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"keywords": [
|
|
39
|
+
"mcp",
|
|
40
|
+
"modelcontextprotocol",
|
|
41
|
+
"unreal-engine",
|
|
42
|
+
"ue5",
|
|
43
|
+
"game-development",
|
|
44
|
+
"remote-control",
|
|
45
|
+
"automation",
|
|
46
|
+
"3d",
|
|
47
|
+
"gamedev",
|
|
48
|
+
"cinematics"
|
|
49
|
+
],
|
|
50
|
+
"author": "ChiR24",
|
|
51
|
+
"homepage": "https://github.com/ChiR24/Unreal_mcp",
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "https://github.com/ChiR24/Unreal_mcp.git",
|
|
55
|
+
"source": "github"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=18"
|
|
59
|
+
}
|
|
60
|
+
}
|