godot-mcp-runtime 0.3.0
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/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/godot_operations.gd +757 -0
- package/dist/scripts/mcp_bridge.gd +463 -0
- package/dist/tools/node-tools.d.ts +15 -0
- package/dist/tools/node-tools.d.ts.map +1 -0
- package/dist/tools/node-tools.js +178 -0
- package/dist/tools/node-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +130 -0
- package/dist/tools/project-tools.d.ts.map +1 -0
- package/dist/tools/project-tools.js +638 -0
- package/dist/tools/project-tools.js.map +1 -0
- package/dist/tools/scene-tools.d.ts +27 -0
- package/dist/tools/scene-tools.d.ts.map +1 -0
- package/dist/tools/scene-tools.js +270 -0
- package/dist/tools/scene-tools.js.map +1 -0
- package/dist/utils/godot-runner.d.ts +71 -0
- package/dist/utils/godot-runner.d.ts.map +1 -0
- package/dist/utils/godot-runner.js +601 -0
- package/dist/utils/godot-runner.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import { join, dirname, normalize } from 'path';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, copyFileSync, unlinkSync, mkdirSync } from 'fs';
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
|
+
import { createSocket } from 'dgram';
|
|
6
|
+
// Derive __filename and __dirname in ESM
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
// Debug mode from environment
|
|
10
|
+
const DEBUG_MODE = process.env.DEBUG === 'true';
|
|
11
|
+
/**
|
|
12
|
+
* Extract JSON from Godot output by finding the first { or [ and matching to the end.
|
|
13
|
+
* This strips debug logs, version banners, and other noise.
|
|
14
|
+
*/
|
|
15
|
+
function extractJson(output) {
|
|
16
|
+
// Find the first occurrence of { or [
|
|
17
|
+
const jsonStartBrace = output.indexOf('{');
|
|
18
|
+
const jsonStartBracket = output.indexOf('[');
|
|
19
|
+
let jsonStart = -1;
|
|
20
|
+
if (jsonStartBrace === -1 && jsonStartBracket === -1) {
|
|
21
|
+
return output; // No JSON found, return as-is
|
|
22
|
+
}
|
|
23
|
+
else if (jsonStartBrace === -1) {
|
|
24
|
+
jsonStart = jsonStartBracket;
|
|
25
|
+
}
|
|
26
|
+
else if (jsonStartBracket === -1) {
|
|
27
|
+
jsonStart = jsonStartBrace;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
jsonStart = Math.min(jsonStartBrace, jsonStartBracket);
|
|
31
|
+
}
|
|
32
|
+
// Extract from JSON start to end
|
|
33
|
+
const jsonPart = output.substring(jsonStart);
|
|
34
|
+
// Try to parse to validate, if it fails return original
|
|
35
|
+
try {
|
|
36
|
+
JSON.parse(jsonPart.trim());
|
|
37
|
+
return jsonPart.trim();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// If the extracted part isn't valid JSON, try to find the last } or ]
|
|
41
|
+
const lastBrace = jsonPart.lastIndexOf('}');
|
|
42
|
+
const lastBracket = jsonPart.lastIndexOf(']');
|
|
43
|
+
const lastEnd = Math.max(lastBrace, lastBracket);
|
|
44
|
+
if (lastEnd > 0) {
|
|
45
|
+
const extracted = jsonPart.substring(0, lastEnd + 1);
|
|
46
|
+
try {
|
|
47
|
+
JSON.parse(extracted);
|
|
48
|
+
return extracted;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return output; // Return original if still can't parse
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return output;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Strip Godot banner and debug lines from output, keeping only meaningful content.
|
|
59
|
+
*/
|
|
60
|
+
function cleanOutput(output) {
|
|
61
|
+
const lines = output.split('\n');
|
|
62
|
+
const cleanedLines = lines.filter(line => {
|
|
63
|
+
const trimmed = line.trim();
|
|
64
|
+
// Skip empty lines
|
|
65
|
+
if (!trimmed)
|
|
66
|
+
return false;
|
|
67
|
+
// Skip Godot version banner
|
|
68
|
+
if (trimmed.startsWith('Godot Engine v'))
|
|
69
|
+
return false;
|
|
70
|
+
// Skip debug lines
|
|
71
|
+
if (trimmed.startsWith('[DEBUG]'))
|
|
72
|
+
return false;
|
|
73
|
+
// Skip info lines that are just status updates
|
|
74
|
+
if (trimmed.startsWith('[INFO] Operation:'))
|
|
75
|
+
return false;
|
|
76
|
+
if (trimmed.startsWith('[INFO] Executing operation:'))
|
|
77
|
+
return false;
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
return cleanedLines.join('\n');
|
|
81
|
+
}
|
|
82
|
+
// Parameter mappings between snake_case and camelCase
|
|
83
|
+
const parameterMappings = {
|
|
84
|
+
'project_path': 'projectPath',
|
|
85
|
+
'scene_path': 'scenePath',
|
|
86
|
+
'root_node_type': 'rootNodeType',
|
|
87
|
+
'parent_node_path': 'parentNodePath',
|
|
88
|
+
'node_type': 'nodeType',
|
|
89
|
+
'node_name': 'nodeName',
|
|
90
|
+
'texture_path': 'texturePath',
|
|
91
|
+
'node_path': 'nodePath',
|
|
92
|
+
'output_path': 'outputPath',
|
|
93
|
+
'mesh_item_names': 'meshItemNames',
|
|
94
|
+
'new_path': 'newPath',
|
|
95
|
+
'file_path': 'filePath',
|
|
96
|
+
'script_path': 'scriptPath',
|
|
97
|
+
};
|
|
98
|
+
// Reverse mapping from camelCase to snake_case
|
|
99
|
+
const reverseParameterMappings = {};
|
|
100
|
+
for (const [snakeCase, camelCase] of Object.entries(parameterMappings)) {
|
|
101
|
+
reverseParameterMappings[camelCase] = snakeCase;
|
|
102
|
+
}
|
|
103
|
+
export function logDebug(message) {
|
|
104
|
+
if (DEBUG_MODE) {
|
|
105
|
+
console.error(`[DEBUG] ${message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export function logError(message) {
|
|
109
|
+
console.error(`[SERVER] ${message}`);
|
|
110
|
+
}
|
|
111
|
+
export function normalizeParameters(params) {
|
|
112
|
+
if (!params || typeof params !== 'object') {
|
|
113
|
+
return params;
|
|
114
|
+
}
|
|
115
|
+
const result = {};
|
|
116
|
+
for (const key in params) {
|
|
117
|
+
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
|
118
|
+
let normalizedKey = key;
|
|
119
|
+
if (key.includes('_') && parameterMappings[key]) {
|
|
120
|
+
normalizedKey = parameterMappings[key];
|
|
121
|
+
}
|
|
122
|
+
const value = params[key];
|
|
123
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
124
|
+
result[normalizedKey] = normalizeParameters(value);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
result[normalizedKey] = value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
export function convertCamelToSnakeCase(params) {
|
|
134
|
+
const result = {};
|
|
135
|
+
for (const key in params) {
|
|
136
|
+
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
|
137
|
+
const snakeKey = reverseParameterMappings[key] || key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
138
|
+
const value = params[key];
|
|
139
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
140
|
+
result[snakeKey] = convertCamelToSnakeCase(value);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
result[snakeKey] = value;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
export function validatePath(path) {
|
|
150
|
+
if (!path || path.includes('..')) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
export function createErrorResponse(message, possibleSolutions = []) {
|
|
156
|
+
logError(`Error response: ${message}`);
|
|
157
|
+
if (possibleSolutions.length > 0) {
|
|
158
|
+
logError(`Possible solutions: ${possibleSolutions.join(', ')}`);
|
|
159
|
+
}
|
|
160
|
+
const response = {
|
|
161
|
+
content: [{ type: 'text', text: message }],
|
|
162
|
+
isError: true,
|
|
163
|
+
};
|
|
164
|
+
if (possibleSolutions.length > 0) {
|
|
165
|
+
response.content.push({
|
|
166
|
+
type: 'text',
|
|
167
|
+
text: 'Possible solutions:\n- ' + possibleSolutions.join('\n- '),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return response;
|
|
171
|
+
}
|
|
172
|
+
export class GodotRunner {
|
|
173
|
+
godotPath = null;
|
|
174
|
+
operationsScriptPath;
|
|
175
|
+
bridgeScriptPath;
|
|
176
|
+
validatedPaths = new Map();
|
|
177
|
+
injectedProjects = new Set();
|
|
178
|
+
strictPathValidation;
|
|
179
|
+
activeProcess = null;
|
|
180
|
+
activeProjectPath = null;
|
|
181
|
+
constructor(config) {
|
|
182
|
+
this.strictPathValidation = config?.strictPathValidation ?? false;
|
|
183
|
+
this.operationsScriptPath = join(__dirname, '..', 'scripts', 'godot_operations.gd');
|
|
184
|
+
this.bridgeScriptPath = join(__dirname, '..', 'scripts', 'mcp_bridge.gd');
|
|
185
|
+
logDebug(`Operations script path: ${this.operationsScriptPath}`);
|
|
186
|
+
if (config?.godotPath) {
|
|
187
|
+
const normalizedPath = normalize(config.godotPath);
|
|
188
|
+
if (this.isValidGodotPathSync(normalizedPath)) {
|
|
189
|
+
this.godotPath = normalizedPath;
|
|
190
|
+
logDebug(`Custom Godot path provided: ${this.godotPath}`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
console.warn(`[SERVER] Invalid custom Godot path provided: ${normalizedPath}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
isValidGodotPathSync(path) {
|
|
198
|
+
try {
|
|
199
|
+
logDebug(`Quick-validating Godot path: ${path}`);
|
|
200
|
+
return path === 'godot' || existsSync(path);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
logDebug(`Invalid Godot path: ${path}`);
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
spawnAsync(cmd, args, timeoutMs = 10000) {
|
|
208
|
+
return new Promise((resolve, reject) => {
|
|
209
|
+
const proc = spawn(cmd, args, { stdio: 'pipe' });
|
|
210
|
+
let stdout = '';
|
|
211
|
+
let stderr = '';
|
|
212
|
+
const timer = setTimeout(() => {
|
|
213
|
+
proc.kill();
|
|
214
|
+
reject(new Error(`Process timed out after ${timeoutMs}ms`));
|
|
215
|
+
}, timeoutMs);
|
|
216
|
+
proc.stdout?.on('data', (data) => { stdout += data.toString(); });
|
|
217
|
+
proc.stderr?.on('data', (data) => { stderr += data.toString(); });
|
|
218
|
+
proc.on('error', (err) => { clearTimeout(timer); reject(err); });
|
|
219
|
+
proc.on('close', (code) => {
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
if (code === 0) {
|
|
222
|
+
resolve({ stdout, stderr });
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const err = new Error(`Process exited with code ${code}`);
|
|
226
|
+
err.stdout = stdout;
|
|
227
|
+
err.stderr = stderr;
|
|
228
|
+
err.code = code;
|
|
229
|
+
reject(err);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
async isValidGodotPath(path) {
|
|
235
|
+
if (this.validatedPaths.has(path)) {
|
|
236
|
+
return this.validatedPaths.get(path);
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
logDebug(`Validating Godot path: ${path}`);
|
|
240
|
+
if (path !== 'godot' && !existsSync(path)) {
|
|
241
|
+
logDebug(`Path does not exist: ${path}`);
|
|
242
|
+
this.validatedPaths.set(path, false);
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
await this.spawnAsync(path, ['--version']);
|
|
246
|
+
logDebug(`Valid Godot path: ${path}`);
|
|
247
|
+
this.validatedPaths.set(path, true);
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
logDebug(`Invalid Godot path: ${path}`);
|
|
252
|
+
this.validatedPaths.set(path, false);
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async detectGodotPath() {
|
|
257
|
+
if (this.godotPath && await this.isValidGodotPath(this.godotPath)) {
|
|
258
|
+
logDebug(`Using existing Godot path: ${this.godotPath}`);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (process.env.GODOT_PATH) {
|
|
262
|
+
const normalizedPath = normalize(process.env.GODOT_PATH);
|
|
263
|
+
logDebug(`Checking GODOT_PATH environment variable: ${normalizedPath}`);
|
|
264
|
+
if (await this.isValidGodotPath(normalizedPath)) {
|
|
265
|
+
this.godotPath = normalizedPath;
|
|
266
|
+
logDebug(`Using Godot path from environment: ${this.godotPath}`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const osPlatform = process.platform;
|
|
271
|
+
logDebug(`Auto-detecting Godot path for platform: ${osPlatform}`);
|
|
272
|
+
const possiblePaths = ['godot'];
|
|
273
|
+
if (osPlatform === 'darwin') {
|
|
274
|
+
possiblePaths.push('/Applications/Godot.app/Contents/MacOS/Godot', '/Applications/Godot_4.app/Contents/MacOS/Godot', `${process.env.HOME}/Applications/Godot.app/Contents/MacOS/Godot`);
|
|
275
|
+
}
|
|
276
|
+
else if (osPlatform === 'win32') {
|
|
277
|
+
possiblePaths.push('C:\\Program Files\\Godot\\Godot.exe', 'C:\\Program Files (x86)\\Godot\\Godot.exe', `${process.env.USERPROFILE}\\Godot\\Godot.exe`);
|
|
278
|
+
}
|
|
279
|
+
else if (osPlatform === 'linux') {
|
|
280
|
+
possiblePaths.push('/usr/bin/godot', '/usr/local/bin/godot', '/snap/bin/godot', `${process.env.HOME}/.local/bin/godot`);
|
|
281
|
+
}
|
|
282
|
+
for (const path of possiblePaths) {
|
|
283
|
+
const normalizedPath = normalize(path);
|
|
284
|
+
if (await this.isValidGodotPath(normalizedPath)) {
|
|
285
|
+
this.godotPath = normalizedPath;
|
|
286
|
+
logDebug(`Found Godot at: ${normalizedPath}`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
logDebug(`Warning: Could not find Godot in common locations for ${osPlatform}`);
|
|
291
|
+
logError(`Could not find Godot in common locations for ${osPlatform}`);
|
|
292
|
+
if (this.strictPathValidation) {
|
|
293
|
+
throw new Error('Could not find a valid Godot executable. Set GODOT_PATH or provide a valid path in config.');
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
if (osPlatform === 'win32') {
|
|
297
|
+
this.godotPath = normalize('C:\\Program Files\\Godot\\Godot.exe');
|
|
298
|
+
}
|
|
299
|
+
else if (osPlatform === 'darwin') {
|
|
300
|
+
this.godotPath = normalize('/Applications/Godot.app/Contents/MacOS/Godot');
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
this.godotPath = normalize('/usr/bin/godot');
|
|
304
|
+
}
|
|
305
|
+
logDebug(`Using default path: ${this.godotPath}, but this may not work.`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
getGodotPath() {
|
|
309
|
+
return this.godotPath;
|
|
310
|
+
}
|
|
311
|
+
async getVersion() {
|
|
312
|
+
if (!this.godotPath) {
|
|
313
|
+
await this.detectGodotPath();
|
|
314
|
+
if (!this.godotPath) {
|
|
315
|
+
throw new Error('Could not find a valid Godot executable path');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const { stdout } = await this.spawnAsync(this.godotPath, ['--version']);
|
|
319
|
+
return stdout.trim();
|
|
320
|
+
}
|
|
321
|
+
isGodot44OrLater(version) {
|
|
322
|
+
const match = version.match(/^(\d+)\.(\d+)/);
|
|
323
|
+
if (match) {
|
|
324
|
+
const major = parseInt(match[1], 10);
|
|
325
|
+
const minor = parseInt(match[2], 10);
|
|
326
|
+
return major > 4 || (major === 4 && minor >= 4);
|
|
327
|
+
}
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
async executeOperation(operation, params, projectPath, timeoutMs = 30000) {
|
|
331
|
+
logDebug(`Executing operation: ${operation} in project: ${projectPath}`);
|
|
332
|
+
logDebug(`Original operation params: ${JSON.stringify(params)}`);
|
|
333
|
+
const snakeCaseParams = convertCamelToSnakeCase(params);
|
|
334
|
+
logDebug(`Converted snake_case params: ${JSON.stringify(snakeCaseParams)}`);
|
|
335
|
+
if (!this.godotPath) {
|
|
336
|
+
await this.detectGodotPath();
|
|
337
|
+
if (!this.godotPath) {
|
|
338
|
+
throw new Error('Could not find a valid Godot executable path');
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const paramsJson = JSON.stringify(snakeCaseParams);
|
|
342
|
+
const args = [
|
|
343
|
+
'--headless',
|
|
344
|
+
'--path', projectPath,
|
|
345
|
+
'--script', this.operationsScriptPath,
|
|
346
|
+
operation,
|
|
347
|
+
paramsJson,
|
|
348
|
+
...(DEBUG_MODE ? ['--debug-godot'] : []),
|
|
349
|
+
];
|
|
350
|
+
logDebug(`Command: ${this.godotPath} ${args.join(' ')}`);
|
|
351
|
+
function cleanStdout(stdout) {
|
|
352
|
+
if (stdout.includes('{') || stdout.includes('[')) {
|
|
353
|
+
return extractJson(stdout);
|
|
354
|
+
}
|
|
355
|
+
return cleanOutput(stdout);
|
|
356
|
+
}
|
|
357
|
+
try {
|
|
358
|
+
const { stdout, stderr } = await this.spawnAsync(this.godotPath, args, timeoutMs);
|
|
359
|
+
return { stdout: cleanStdout(stdout), stderr };
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
if (error instanceof Error && 'stdout' in error && 'stderr' in error) {
|
|
363
|
+
const execError = error;
|
|
364
|
+
return {
|
|
365
|
+
stdout: cleanStdout(execError.stdout),
|
|
366
|
+
stderr: execError.stderr,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
throw error;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
launchEditor(projectPath) {
|
|
373
|
+
if (!this.godotPath) {
|
|
374
|
+
throw new Error('Godot path not set. Call detectGodotPath first.');
|
|
375
|
+
}
|
|
376
|
+
return spawn(this.godotPath, ['-e', '--path', projectPath], { stdio: 'pipe' });
|
|
377
|
+
}
|
|
378
|
+
runProject(projectPath, scene) {
|
|
379
|
+
if (!this.godotPath) {
|
|
380
|
+
throw new Error('Godot path not set. Call detectGodotPath first.');
|
|
381
|
+
}
|
|
382
|
+
if (this.activeProcess) {
|
|
383
|
+
logDebug('Killing existing Godot process before starting a new one');
|
|
384
|
+
this.activeProcess.process.kill();
|
|
385
|
+
// Clean up old project's autoload if switching projects
|
|
386
|
+
if (this.activeProjectPath && this.activeProjectPath !== projectPath) {
|
|
387
|
+
this.cleanupBridgeAutoload(this.activeProjectPath);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
this.injectBridgeAutoload(projectPath);
|
|
392
|
+
}
|
|
393
|
+
catch (err) {
|
|
394
|
+
logDebug(`Non-fatal: Failed to inject bridge autoload: ${err}`);
|
|
395
|
+
}
|
|
396
|
+
this.activeProjectPath = projectPath;
|
|
397
|
+
const cmdArgs = ['-d', '--path', projectPath];
|
|
398
|
+
if (scene && validatePath(scene)) {
|
|
399
|
+
logDebug(`Adding scene parameter: ${scene}`);
|
|
400
|
+
cmdArgs.push(scene);
|
|
401
|
+
}
|
|
402
|
+
logDebug(`Running Godot project: ${projectPath}`);
|
|
403
|
+
const proc = spawn(this.godotPath, cmdArgs, { stdio: 'pipe' });
|
|
404
|
+
const output = [];
|
|
405
|
+
const errors = [];
|
|
406
|
+
const godotProcess = {
|
|
407
|
+
process: proc,
|
|
408
|
+
output,
|
|
409
|
+
errors,
|
|
410
|
+
exitCode: null,
|
|
411
|
+
hasExited: false,
|
|
412
|
+
};
|
|
413
|
+
proc.stdout?.on('data', (data) => {
|
|
414
|
+
const lines = data.toString().split('\n');
|
|
415
|
+
output.push(...lines);
|
|
416
|
+
if (output.length > 500)
|
|
417
|
+
output.splice(0, output.length - 500);
|
|
418
|
+
lines.forEach((line) => {
|
|
419
|
+
if (line.trim())
|
|
420
|
+
logDebug(`[Godot stdout] ${line}`);
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
proc.stderr?.on('data', (data) => {
|
|
424
|
+
const lines = data.toString().split('\n');
|
|
425
|
+
errors.push(...lines);
|
|
426
|
+
if (errors.length > 500)
|
|
427
|
+
errors.splice(0, errors.length - 500);
|
|
428
|
+
lines.forEach((line) => {
|
|
429
|
+
if (line.trim())
|
|
430
|
+
logDebug(`[Godot stderr] ${line}`);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
proc.on('exit', (code) => {
|
|
434
|
+
logDebug(`Godot process exited with code ${code}`);
|
|
435
|
+
godotProcess.exitCode = code;
|
|
436
|
+
godotProcess.hasExited = true;
|
|
437
|
+
// Don't clear activeProcess immediately - keep it so output can be retrieved
|
|
438
|
+
});
|
|
439
|
+
proc.on('error', (err) => {
|
|
440
|
+
console.error('Failed to start Godot process:', err);
|
|
441
|
+
errors.push(`Process error: ${err.message}`);
|
|
442
|
+
godotProcess.hasExited = true;
|
|
443
|
+
});
|
|
444
|
+
this.activeProcess = godotProcess;
|
|
445
|
+
return this.activeProcess;
|
|
446
|
+
}
|
|
447
|
+
stopProject() {
|
|
448
|
+
if (!this.activeProcess) {
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
logDebug('Stopping active Godot process');
|
|
452
|
+
this.activeProcess.process.kill();
|
|
453
|
+
const result = {
|
|
454
|
+
output: this.activeProcess.output,
|
|
455
|
+
errors: this.activeProcess.errors,
|
|
456
|
+
};
|
|
457
|
+
this.activeProcess = null;
|
|
458
|
+
if (this.activeProjectPath) {
|
|
459
|
+
this.cleanupBridgeAutoload(this.activeProjectPath);
|
|
460
|
+
this.activeProjectPath = null;
|
|
461
|
+
}
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
removeAutoloadEntry(projectPath, entryName, scriptFilename) {
|
|
465
|
+
try {
|
|
466
|
+
const projectFile = join(projectPath, 'project.godot');
|
|
467
|
+
if (existsSync(projectFile)) {
|
|
468
|
+
let content = readFileSync(projectFile, 'utf8');
|
|
469
|
+
const autoloadEntry = `${entryName}="*res://${scriptFilename}"`;
|
|
470
|
+
if (content.includes(autoloadEntry)) {
|
|
471
|
+
content = content.replace(new RegExp(`\\n?${autoloadEntry.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`, 'g'), '');
|
|
472
|
+
content = content.replace(/\[autoload\]\s*(?=\n\[|\n*$)/g, '');
|
|
473
|
+
content = content.trimEnd() + '\n';
|
|
474
|
+
writeFileSync(projectFile, content, 'utf8');
|
|
475
|
+
logDebug(`Removed ${entryName} autoload from project.godot`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch (err) {
|
|
480
|
+
logDebug(`Non-fatal: Failed to clean ${entryName} from project.godot: ${err}`);
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
const scriptFile = join(projectPath, scriptFilename);
|
|
484
|
+
if (existsSync(scriptFile)) {
|
|
485
|
+
unlinkSync(scriptFile);
|
|
486
|
+
logDebug(`Removed ${scriptFilename} from project`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
logDebug(`Non-fatal: Failed to remove ${scriptFilename}: ${err}`);
|
|
491
|
+
}
|
|
492
|
+
try {
|
|
493
|
+
const uidFile = join(projectPath, `${scriptFilename}.uid`);
|
|
494
|
+
if (existsSync(uidFile)) {
|
|
495
|
+
unlinkSync(uidFile);
|
|
496
|
+
logDebug(`Removed ${scriptFilename}.uid from project`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
catch (err) {
|
|
500
|
+
logDebug(`Non-fatal: Failed to remove ${scriptFilename}.uid: ${err}`);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
injectBridgeAutoload(projectPath) {
|
|
504
|
+
if (this.injectedProjects.has(projectPath)) {
|
|
505
|
+
logDebug('Bridge already injected for this project, skipping');
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
// Ensure .mcp/ directory exists with .gdignore so Godot skips it
|
|
509
|
+
const mcpDir = join(projectPath, '.mcp');
|
|
510
|
+
if (!existsSync(mcpDir)) {
|
|
511
|
+
mkdirSync(mcpDir, { recursive: true });
|
|
512
|
+
}
|
|
513
|
+
const gdignorePath = join(mcpDir, '.gdignore');
|
|
514
|
+
if (!existsSync(gdignorePath)) {
|
|
515
|
+
writeFileSync(gdignorePath, '', 'utf8');
|
|
516
|
+
logDebug('Created .mcp/.gdignore');
|
|
517
|
+
}
|
|
518
|
+
// Also add .mcp/ to .gitignore if not already present
|
|
519
|
+
const gitignorePath = join(projectPath, '.gitignore');
|
|
520
|
+
const mcpGitignoreEntry = '.mcp/';
|
|
521
|
+
if (existsSync(gitignorePath)) {
|
|
522
|
+
const gitignoreContent = readFileSync(gitignorePath, 'utf8');
|
|
523
|
+
if (!gitignoreContent.includes(mcpGitignoreEntry)) {
|
|
524
|
+
const newline = gitignoreContent.endsWith('\n') ? '' : '\n';
|
|
525
|
+
writeFileSync(gitignorePath, gitignoreContent + newline + mcpGitignoreEntry + '\n', 'utf8');
|
|
526
|
+
logDebug('Added .mcp/ to existing .gitignore');
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
writeFileSync(gitignorePath, mcpGitignoreEntry + '\n', 'utf8');
|
|
531
|
+
logDebug('Created .gitignore with .mcp/ entry');
|
|
532
|
+
}
|
|
533
|
+
// Clean up legacy screenshot server if present
|
|
534
|
+
this.removeAutoloadEntry(projectPath, 'McpScreenshotServer', 'mcp_screenshot_server.gd');
|
|
535
|
+
const destScript = join(projectPath, 'mcp_bridge.gd');
|
|
536
|
+
copyFileSync(this.bridgeScriptPath, destScript);
|
|
537
|
+
logDebug(`Copied bridge autoload to ${destScript}`);
|
|
538
|
+
const projectFile = join(projectPath, 'project.godot');
|
|
539
|
+
let content = readFileSync(projectFile, 'utf8');
|
|
540
|
+
const autoloadEntry = 'McpBridge="*res://mcp_bridge.gd"';
|
|
541
|
+
if (content.includes(autoloadEntry)) {
|
|
542
|
+
logDebug('Bridge autoload already present, skipping injection');
|
|
543
|
+
this.injectedProjects.add(projectPath);
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
const autoloadSectionRegex = /^\[autoload\]\s*$/m;
|
|
547
|
+
if (autoloadSectionRegex.test(content)) {
|
|
548
|
+
content = content.replace(autoloadSectionRegex, `[autoload]\n${autoloadEntry}`);
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
content = content.trimEnd() + `\n\n[autoload]\n${autoloadEntry}\n`;
|
|
552
|
+
}
|
|
553
|
+
writeFileSync(projectFile, content, 'utf8');
|
|
554
|
+
logDebug('Injected bridge autoload into project.godot');
|
|
555
|
+
this.injectedProjects.add(projectPath);
|
|
556
|
+
}
|
|
557
|
+
cleanupBridgeAutoload(projectPath) {
|
|
558
|
+
this.removeAutoloadEntry(projectPath, 'McpBridge', 'mcp_bridge.gd');
|
|
559
|
+
this.injectedProjects.delete(projectPath);
|
|
560
|
+
}
|
|
561
|
+
sendCommand(command, params = {}, timeoutMs = 10000) {
|
|
562
|
+
return new Promise((resolve, reject) => {
|
|
563
|
+
const socket = createSocket('udp4');
|
|
564
|
+
let settled = false;
|
|
565
|
+
const timer = setTimeout(() => {
|
|
566
|
+
if (!settled) {
|
|
567
|
+
settled = true;
|
|
568
|
+
socket.close();
|
|
569
|
+
reject(new Error(`Command '${command}' timed out after ${timeoutMs}ms. Is the game running?`));
|
|
570
|
+
}
|
|
571
|
+
}, timeoutMs);
|
|
572
|
+
socket.on('message', (msg) => {
|
|
573
|
+
if (!settled) {
|
|
574
|
+
settled = true;
|
|
575
|
+
clearTimeout(timer);
|
|
576
|
+
socket.close();
|
|
577
|
+
resolve(msg.toString('utf8'));
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
socket.on('error', (err) => {
|
|
581
|
+
if (!settled) {
|
|
582
|
+
settled = true;
|
|
583
|
+
clearTimeout(timer);
|
|
584
|
+
socket.close();
|
|
585
|
+
reject(new Error(`UDP error for command '${command}': ${err.message}`));
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
const payload = JSON.stringify({ command, ...params });
|
|
589
|
+
const message = Buffer.from(payload);
|
|
590
|
+
socket.send(message, 9900, '127.0.0.1', (err) => {
|
|
591
|
+
if (err && !settled) {
|
|
592
|
+
settled = true;
|
|
593
|
+
clearTimeout(timer);
|
|
594
|
+
socket.close();
|
|
595
|
+
reject(new Error(`Failed to send command '${command}': ${err.message}`));
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
//# sourceMappingURL=godot-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"godot-runner.js","sourceRoot":"","sources":["../../src/utils/godot-runner.ts"],"names":[],"mappings":"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"}
|