From a867eec8ac19c62b10016c10c4ae2fac76bf76f3 Mon Sep 17 00:00:00 2001 From: Dluck Date: Thu, 27 Nov 2025 20:51:49 +0800 Subject: [PATCH] Passing custom Godot CLI arguments --- README.md | 16 ++++++++++++++++ src/index.ts | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/README.md b/README.md index fcc253968..0f70d5dea 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,22 @@ Once configured, your AI assistant will automatically run the MCP server when ne "Update UID references in my Godot project after upgrading to 4.4" ``` +### Passing custom Godot CLI arguments + +`run_project` now accepts an optional `extraArgs` array. These strings are appended directly to the Godot command line so you can trigger headless runs, select custom main scenes, or pass feature flags without leaving your IDE. Example request payload: + +```jsonc +{ + "name": "run_project", + "arguments": { + "projectPath": "/absolute/path/to/project", + "extraArgs": ["--headless", "--test=sample_spawn_test"] + } +} +``` + +> ℹ️ For safety, the server automatically injects `--path` for you and filters out duplicate `--path`/`-p` flags. Use `extraArgs` strictly for additional Godot options (e.g., `--headless`, `--quit`, `--test=...`). + ## Implementation Details ### Architecture diff --git a/src/index.ts b/src/index.ts index 325de0fd6..cb4da4dd9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -694,6 +694,13 @@ class GodotServer { type: 'string', description: 'Optional: Specific scene to run', }, + extraArgs: { + type: 'array', + description: 'Optional additional CLI arguments passed directly to the Godot executable', + items: { + type: 'string', + }, + }, }, required: ['projectPath'], }, @@ -1094,6 +1101,12 @@ class GodotServer { cmdArgs.push(args.scene); } + const extraArgs = this.parseExtraArgs(args.extraArgs); + if (extraArgs.length > 0) { + this.logDebug(`Adding custom CLI args: ${extraArgs.join(' ')}`); + cmdArgs.push(...extraArgs); + } + this.logDebug(`Running Godot project: ${args.projectPath}`); const process = spawn(this.godotPath!, cmdArgs, { stdio: 'pipe' }); const output: string[] = []; @@ -1152,6 +1165,42 @@ class GodotServer { } } + /** + * Parse optional extra CLI arguments for Godot + */ + private parseExtraArgs(extraArgs: any): string[] { + if (!extraArgs) { + return []; + } + + const sanitizedArgs: string[] = []; + const disallowedArgs = new Set(['--path', '-p']); + + const pushArg = (value: string) => { + if (typeof value !== 'string') { + return; + } + const trimmed = value.trim(); + if (!trimmed || trimmed.includes('\n') || trimmed.includes('\r')) { + return; + } + if (disallowedArgs.has(trimmed)) { + return; + } + const unquoted = trimmed.replace(/^"(.*)"$/, '$1'); + sanitizedArgs.push(unquoted); + }; + + if (Array.isArray(extraArgs)) { + extraArgs.forEach((arg) => pushArg(arg)); + } else if (typeof extraArgs === 'string') { + const tokens = extraArgs.match(/(?:[^\s"]+|"[^"]*")+/g) ?? []; + tokens.forEach((token) => pushArg(token)); + } + + return sanitizedArgs; + } + /** * Handle the get_debug_output tool */