Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class GodotServer {
private operationsScriptPath: string;
private validatedPaths: Map<string, boolean> = new Map();
private strictPathValidation: boolean = false;
// Track the editor process spawned by launch_editor so quit_godot can close it
private editorProcess: any = null;

/**
* Parameter name mappings between snake_case and camelCase
Expand Down Expand Up @@ -398,6 +400,13 @@ class GodotServer {
this.activeProcess.process.kill();
this.activeProcess = null;
}
if (this.editorProcess) {
this.logDebug('Killing tracked editor process');
try {
this.editorProcess.kill();
} catch (_) {}
this.editorProcess = null;
}
await this.server.close();
}

Expand Down Expand Up @@ -923,6 +932,15 @@ class GodotServer {
required: ['projectPath'],
},
},
{
name: 'quit_godot',
description: 'Close the Godot editor that was launched by this MCP server via launch_editor. Only closes editors spawned by this server.',
inputSchema: {
type: 'object',
properties: {},
required: [],
},
},
],
}));

Expand Down Expand Up @@ -958,6 +976,8 @@ class GodotServer {
return await this.handleGetUid(request.params.arguments);
case 'update_project_uids':
return await this.handleUpdateProjectUids(request.params.arguments);
case 'quit_godot':
return await this.handleQuitGodot();
default:
throw new McpError(
ErrorCode.MethodNotFound,
Expand Down Expand Up @@ -1021,6 +1041,16 @@ class GodotServer {
stdio: 'pipe',
});

// Track the spawned editor so quit_godot can close it later
this.editorProcess = process;

process.on('exit', () => {
if (this.editorProcess === process) {
this.logDebug('Godot editor exited naturally');
this.editorProcess = null;
}
});

process.on('error', (err: Error) => {
console.error('Failed to start Godot editor:', err);
});
Expand Down Expand Up @@ -2168,6 +2198,40 @@ class GodotServer {
}
}

/**
* Handle the quit_godot tool
*/
private async handleQuitGodot() {
if (!this.editorProcess) {
return this.createErrorResponse(
'No Godot editor process is currently tracked',
['The editor may have been closed already, or launch_editor was not used to start it']
);
}

try {
this.logDebug('Quitting Godot editor');
this.editorProcess.kill();
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return this.createErrorResponse(
`Failed to quit Godot editor: ${errorMessage}`,
['The process may have already exited']
);
} finally {
this.editorProcess = null;
}

return {
content: [
{
type: 'text',
text: 'Godot editor closed successfully.',
},
],
};
}

/**
* Run the MCP server
*/
Expand Down