godot-cli 0.11.1 → 0.13.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/README.md CHANGED
@@ -25,7 +25,8 @@ Requires Node `^20.19.0 || >=22.12.0`.
25
25
 
26
26
  | Command | What it does |
27
27
  | --- | --- |
28
- | `open [path]` | Resolve the Godot editor binary and launch `--editor --path <project>` with `GODOT_MCP_*` connection env vars. |
28
+ | `open [path]` | Build the project's C# assembly (so the addon loads on first open — see below), resolve the Godot editor binary, and launch `--editor --path <project>` with `GODOT_MCP_*` connection env vars. `--no-build` skips the build. |
29
+ | `build [path]` | Build the project's C# assembly (`dotnet build`) so the `godot_mcp` addon loads on the next editor open. GDScript-only projects (no `.csproj`) are a no-op. This is the same build `open` runs before launching. |
29
30
  | `run-tool <tool> [path]` | POST to `<url>/api/tools/<tool>` with JSON input. |
30
31
  | `run-system-tool <tool> [path]` | POST to `<url>/api/system-tools/<tool>` (tools not exposed to MCP clients). |
31
32
  | `status [path]` | Detect a running Godot editor for the project and probe MCP-server health. |
@@ -34,10 +35,26 @@ Requires Node `^20.19.0 || >=22.12.0`.
34
35
  | `setup-skills <agent> [path]` | Generate Godot-MCP skill files (a `SKILL.md`-per-tool-family) under the agent's skills path. `--list` shows each agent's skills support. |
35
36
  | `configure [path]` | List / enable / disable tools, prompts, and resources in the project-local `.godot-mcp/features.json`. |
36
37
  | `close [path]` | Gracefully stop the Godot editor running for a project (`--force` to hard-kill). |
37
- | `install-plugin [path]` | Enable the `godot_mcp` addon in `project.godot` `[editor_plugins]`. |
38
- | `remove-plugin [path]` | Disable the `godot_mcp` addon in `project.godot` `[editor_plugins]`. |
38
+ | `install-plugin [path]` | Install the `godot_mcp` addon end-to-end: materialize `res://addons/godot_mcp/` (download the matching GitHub release, or `--source <path>` a local copy), add the required NuGet `PackageReference`s to the project `.csproj`, and enable the plugin. Idempotent. |
39
+ | `remove-plugin [path]` | Disable the `godot_mcp` addon in `project.godot` `[editor_plugins]` (does not delete the addon files). |
39
40
  | `update` | Check npm for a newer `godot-cli` and install it. |
40
41
 
42
+ ### Build before open (`open` / `build`)
43
+
44
+ `open` **builds the project's C# assembly before launching the editor**. Godot instantiates an
45
+ enabled addon's `EditorPlugin` as soon as the editor loads — so on a *fresh* first open of a C#
46
+ project that was never built, no assembly exists yet and Godot fails with
47
+ `Unable to load addon script 'res://addons/godot_mcp/Editor/GodotMcpPlugin.cs' … Disabling the addon`.
48
+ Building first guarantees the assembly is present when the addon is instantiated.
49
+
50
+ - The build is the same one `godot-cli build` runs: `dotnet build <project>.csproj --configuration Debug`.
51
+ - **GDScript-only projects** (no `.csproj` at the root) are skipped automatically — there is nothing to compile.
52
+ - The build runs **unconditionally** for C# projects; `dotnet build` is incremental, so an up-to-date
53
+ project is a fast no-op. Pass `--no-build` to `open` to skip it (e.g. you already built, or want to
54
+ open as fast as possible).
55
+ - If the build **fails**, `open` does **not** launch the editor (launching would just reproduce the
56
+ disable-addon failure); the error is surfaced instead.
57
+
41
58
  ### Editor resolution (`open`)
42
59
 
43
60
  `open` locates the Godot editor binary in this order:
@@ -97,6 +114,33 @@ exposes no skill-generate HTTP endpoint, so no server or running editor is requi
97
114
  `GodotMcpConnection.Start` → `GenerateSkillFilesIfNeeded`; the CLI command is the
98
115
  server-less, scriptable path that does not need a live editor.)
99
116
 
117
+ ## `install-plugin`
118
+
119
+ `godot-cli install-plugin [path]` is a **real installer** — it makes a from-scratch terminal install
120
+ produce a working project, in one idempotent command:
121
+
122
+ ```bash
123
+ godot-cli install-plugin ./MyGodotProject # download the matching release + install
124
+ godot-cli install-plugin --version 0.11.1 ./MyGodotProject # pin a specific addon release
125
+ godot-cli install-plugin --source ./Godot-MCP/addons/godot_mcp ./MyGodotProject # offline / dev copy
126
+ ```
127
+
128
+ It performs three steps:
129
+
130
+ 1. **Materialize `res://addons/godot_mcp/`.** By default it downloads `godot-mcp-addon-<version>.zip`
131
+ over HTTPS from **github.com only** (the `IvanMurzak/Godot-MCP` release `v<version>`; the version
132
+ defaults to the CLI's own version). Non-`github.com` hosts and plain `http` are rejected. With
133
+ `--source <path>` it copies the addon from a local directory instead (no network) — `<path>` may be a
134
+ directory that *is* `addons/godot_mcp` or one that *contains* it.
135
+ 2. **Add the NuGet packages** the addon needs (`com.IvanMurzak.ReflectorNet`, `com.IvanMurzak.McpPlugin`)
136
+ to the project's `.csproj`, idempotently — adding when missing, reconciling a stale version, and
137
+ leaving a correct pin untouched. The versions are single-sourced from the addon's own
138
+ `Godot-MCP.csproj` pins, so the scaffold can never drift.
139
+ 3. **Enable the plugin** in `project.godot` `[editor_plugins]`.
140
+
141
+ It is library-safe (returns a `{ kind: 'success' | 'failure' }` union; never throws past the public
142
+ boundary) and idempotent — re-running on an already-installed project reports no change.
143
+
100
144
  ## Library API
101
145
 
102
146
  The package also exports a side-effect-free library (the `.` entry):
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const buildCommand: Command;
@@ -0,0 +1,66 @@
1
+ import { Command } from 'commander';
2
+ import * as path from 'path';
3
+ import * as ui from '../utils/ui.js';
4
+ import { verbose } from '../utils/ui.js';
5
+ import { buildProject } from '../lib/build.js';
6
+ export const buildCommand = new Command('build')
7
+ .description('Build the Godot project\'s C# assembly (dotnet build) so the godot_mcp addon loads on the next editor open. GDScript-only projects (no .csproj) are a no-op. This is the same build `open` runs before launching the editor.')
8
+ .argument('[path]', 'Path to the Godot project (defaults to current directory)')
9
+ .option('--path <path>', 'Path to the Godot project (defaults to current directory)')
10
+ .option('--configuration <cfg>', 'MSBuild configuration to compile (default: Debug)')
11
+ .option('--dotnet-path <path>', 'Explicit dotnet executable path (default: dotnet on PATH)')
12
+ .action(async (positionalPath, options) => {
13
+ const resolvedPath = positionalPath ?? options.path ?? process.cwd();
14
+ const projectPath = path.resolve(resolvedPath);
15
+ ui.heading('Building Godot C# project');
16
+ verbose(`Project path: ${projectPath}`);
17
+ const spinner = ui.startSpinner('Building C# assembly...');
18
+ const result = await buildProject({
19
+ projectPath,
20
+ configuration: options.configuration,
21
+ dotnetPath: options.dotnetPath,
22
+ onProgress: (event) => {
23
+ switch (event.phase) {
24
+ case 'build-running':
25
+ spinner.text = `Building ${path.basename(event.csprojPath)} ...`;
26
+ verbose(`Build command: ${event.command}`);
27
+ break;
28
+ case 'build-skipped':
29
+ verbose('No .csproj at project root — skipping build (GDScript-only).');
30
+ break;
31
+ default:
32
+ break;
33
+ }
34
+ },
35
+ });
36
+ if (result.kind === 'failure') {
37
+ spinner.error('Build failed');
38
+ ui.error(result.errorMessage);
39
+ for (const warning of result.warnings) {
40
+ console.log('');
41
+ ui.warn(warning);
42
+ }
43
+ process.exit(1);
44
+ }
45
+ if (result.skipped) {
46
+ spinner.success('No C# to build (GDScript-only project)');
47
+ ui.info('This project has no .csproj at its root — nothing to compile.');
48
+ }
49
+ else {
50
+ spinner.success('C# assembly built');
51
+ ui.label('Project', result.projectPath);
52
+ if (result.csprojPath)
53
+ ui.label('Built', result.csprojPath);
54
+ if (result.configuration)
55
+ ui.label('Configuration', result.configuration);
56
+ // Surface the captured `dotnet build` output in verbose mode — otherwise
57
+ // a slow non-incremental first build shows only a static spinner.
58
+ if (result.output)
59
+ verbose(result.output.trim());
60
+ }
61
+ for (const warning of result.warnings) {
62
+ console.log('');
63
+ ui.warn(warning);
64
+ }
65
+ });
66
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -1,30 +1,68 @@
1
1
  import { Command } from 'commander';
2
+ import { createRequire } from 'module';
2
3
  import * as path from 'path';
3
4
  import * as ui from '../utils/ui.js';
4
5
  import { verbose } from '../utils/ui.js';
5
6
  import { installPlugin } from '../lib/install-plugin.js';
7
+ /** The CLI's own version — the default addon release version to download. */
8
+ function cliVersion() {
9
+ try {
10
+ const require = createRequire(import.meta.url);
11
+ const pkg = require('../../package.json');
12
+ return pkg.version;
13
+ }
14
+ catch {
15
+ return '';
16
+ }
17
+ }
6
18
  export const installPluginCommand = new Command('install-plugin')
7
- .description('Enable the godot_mcp addon in a project (adds res://addons/godot_mcp/plugin.cfg to project.godot [editor_plugins])')
19
+ .description('Install the godot_mcp addon into a Godot C# project: materialize res://addons/godot_mcp/ (download the matching GitHub release, or --source a local copy), add the required NuGet PackageReferences to the project .csproj, and enable the plugin in project.godot.')
8
20
  .argument('[path]', 'Path to the Godot project')
9
21
  .option('--path <path>', 'Path to the Godot project')
22
+ .option('--source <path>', 'Install the addon from a local directory (offline / dev / CI) instead of downloading it')
23
+ .option('--version <x.y.z>', 'Addon release version to download (defaults to this CLI version). Ignored with --source.')
10
24
  .action(async (positionalPath, options) => {
11
25
  const resolvedPath = positionalPath ?? options.path ?? process.cwd();
12
26
  const projectPath = path.resolve(resolvedPath);
13
- ui.heading('Enabling godot_mcp addon');
27
+ ui.heading('Installing godot_mcp addon');
14
28
  verbose(`Project path: ${projectPath}`);
15
- const spinner = ui.startSpinner('Updating project.godot...');
16
- const result = await installPlugin({ godotProjectPath: projectPath });
29
+ if (options.source)
30
+ verbose(`--source: ${options.source}`);
31
+ const spinner = ui.startSpinner('Installing addon...');
32
+ const result = await installPlugin({
33
+ godotProjectPath: projectPath,
34
+ source: options.source,
35
+ version: options.version ?? cliVersion(),
36
+ });
17
37
  if (result.kind === 'failure') {
18
- spinner.error('Failed to enable plugin');
38
+ spinner.error('Failed to install plugin');
19
39
  ui.error(result.error.message);
40
+ for (const warning of result.warnings) {
41
+ console.log('');
42
+ ui.warn(warning);
43
+ }
20
44
  process.exit(1);
21
45
  }
22
46
  if (result.changed) {
23
- spinner.success('godot_mcp addon enabled');
47
+ spinner.success('godot_mcp addon installed and enabled');
24
48
  }
25
49
  else {
26
50
  spinner.success('godot_mcp addon was already enabled');
27
51
  }
52
+ // Addon files outcome.
53
+ if (result.materialize.source === 'download') {
54
+ ui.label('Addon files', `downloaded → ${result.materialize.addonDir}`);
55
+ }
56
+ else if (result.materialize.source === 'local') {
57
+ ui.label('Addon files', `copied from ${result.materialize.sourceDir} → ${result.materialize.addonDir}`);
58
+ }
59
+ // csproj outcome.
60
+ if (result.csproj.csprojPath) {
61
+ const summary = result.csproj.packages
62
+ .map((p) => `${p.id}@${p.version} (${p.action})`)
63
+ .join(', ');
64
+ ui.label('NuGet packages', summary || '(none)');
65
+ }
28
66
  ui.label('project.godot', result.projectGodotPath);
29
67
  ui.label('Enabled plugins', result.enabledPlugins.join(', ') || '(none)');
30
68
  for (const warning of result.warnings) {
@@ -1 +1 @@
1
- {"version":3,"file":"install-plugin.js","sourceRoot":"","sources":["../../src/commands/install-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,OAAO,CAAC,gBAAgB,CAAC;KAC9D,WAAW,CAAC,oHAAoH,CAAC;KACjI,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;KAC/C,MAAM,CAAC,eAAe,EAAE,2BAA2B,CAAC;KACpD,MAAM,CAAC,KAAK,EAAE,cAAkC,EAAE,OAAgC,EAAE,EAAE;IACrF,MAAM,YAAY,GAAG,cAAc,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACrE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAE/C,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACvC,OAAO,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC;IAExC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,2BAA2B,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,CAAC;IAEtE,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACnD,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC;IAE1E,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"install-plugin.js","sourceRoot":"","sources":["../../src/commands/install-plugin.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@ export const openCommand = new Command('open')
18
18
  .argument('[path]', 'Path to the Godot project (defaults to current directory)')
19
19
  .option('--path <path>', 'Path to the Godot project (defaults to current directory)')
20
20
  .option('--editor-path <path>', 'Explicit path to the Godot editor executable (skips discovery)')
21
+ .option('--no-build', 'Skip building the C# assembly before launching (GDScript-only projects skip automatically)')
22
+ .option('--build-configuration <cfg>', 'MSBuild configuration for the pre-open build (default: Debug)')
21
23
  .option('--no-connect', 'Open without MCP connection environment variables')
22
24
  .option('--url <url>', 'MCP server host to connect to (sets GODOT_MCP_HOST)')
23
25
  .option('--cloud-url <url>', 'Cloud base URL override (sets GODOT_MCP_CLOUD_URL)')
@@ -56,10 +58,12 @@ export const openCommand = new Command('open')
56
58
  ui.error('--mode must be "Cloud" or "Custom"');
57
59
  process.exit(1);
58
60
  }
59
- const spinner = ui.startSpinner('Locating Godot editor...');
61
+ const spinner = ui.startSpinner(options.build === false ? 'Locating Godot editor...' : 'Building C# assembly...');
60
62
  const result = await openProject({
61
63
  projectPath,
62
64
  editorPath: options.editorPath,
65
+ build: options.build !== false,
66
+ buildConfiguration: options.buildConfiguration,
63
67
  noConnect: options.connect === false,
64
68
  url: options.url,
65
69
  cloudUrl: options.cloudUrl,
@@ -69,6 +73,25 @@ export const openCommand = new Command('open')
69
73
  logLevel: options.logLevel,
70
74
  onProgress: (event) => {
71
75
  switch (event.phase) {
76
+ case 'build-running': {
77
+ spinner.text = `Building ${path.basename(event.csprojPath)} ...`;
78
+ verbose(`Build command: ${event.command}`);
79
+ break;
80
+ }
81
+ case 'build-skipped': {
82
+ // GDScript-only project: no C# to compile. Correct the spinner so
83
+ // it doesn't leave "Building C# assembly..." implying a build ran.
84
+ verbose('No .csproj at project root — skipping build (GDScript-only).');
85
+ spinner.text = 'Locating Godot editor...';
86
+ break;
87
+ }
88
+ case 'build-succeeded': {
89
+ spinner.success('C# assembly built');
90
+ verbose(`Built: ${event.csprojPath} (${event.configuration})`);
91
+ spinner.text = 'Locating Godot editor...';
92
+ spinner.start();
93
+ break;
94
+ }
72
95
  case 'editor-resolved': {
73
96
  spinner.success('Godot editor located');
74
97
  verbose(`Editor path: ${event.editorPath}`);
@@ -1 +1 @@
1
- {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  import { createRequire } from 'module';
3
+ import { buildCommand } from './commands/build.js';
3
4
  import { openCommand } from './commands/open.js';
4
5
  import { runToolCommand } from './commands/run-tool.js';
5
6
  import { runSystemToolCommand } from './commands/run-system-tool.js';
@@ -25,6 +26,7 @@ program
25
26
  .option('-v, --verbose', 'Enable verbose diagnostic output');
26
27
  // Register all subcommands
27
28
  const subcommands = [
29
+ buildCommand,
28
30
  closeCommand,
29
31
  configureCommand,
30
32
  createProjectCommand,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { BuildProjectOptions, BuildProjectResult } from './types.js';
2
+ /**
3
+ * Locate the single consumer `.csproj` directly at the Godot project root — the
4
+ * `.csproj` Godot compiles every project `.cs` (addon included) into. A
5
+ * `--dotnet` scaffold writes `<AssemblyName>.csproj` there. Returns `null` when
6
+ * the project has no root csproj (a GDScript-only project — nothing to build).
7
+ *
8
+ * When more than one csproj sits at the root, the first alphabetically is
9
+ * returned and the ambiguity is pushed onto `warnings` (all root csprojs compile
10
+ * into the same Godot assembly, so building one builds the dependency graph the
11
+ * editor will load). Pure / read-only `fs`. Exported for unit tests.
12
+ */
13
+ export declare function findProjectCsproj(projectPath: string, warnings: string[]): string | null;
14
+ /**
15
+ * Build the C# assembly for a Godot project BEFORE the editor opens, so the
16
+ * editor finds a compiled assembly when it instantiates enabled `EditorPlugin`s
17
+ * (otherwise a fresh first open fails with "Unable to load addon script … —
18
+ * Disabling the addon", godotengine/godot#112701-class behavior).
19
+ *
20
+ * Library-safe: never calls `process.exit`, never throws past the public
21
+ * boundary, never writes to stdout/stderr (observability is via `onProgress`).
22
+ *
23
+ * Behavior:
24
+ * - Validates the path is an existing Godot project (`project.godot`).
25
+ * - GDScript-only projects (no root `.csproj`) are a SUCCESS with
26
+ * `skipped: true` / `skipReason: 'no-csproj'` — there is nothing to compile.
27
+ * - C# projects (a root `.csproj`) are built ALWAYS via `dotnet build <csproj>`.
28
+ * `dotnet build` is itself incremental, so an up-to-date project is a fast
29
+ * no-op; building unconditionally avoids the staleness-detection bugs that a
30
+ * "build-if-missing/stale" heuristic would introduce (the exact failure mode
31
+ * this fix exists to prevent — a stale/absent assembly the editor can't load).
32
+ * - A non-zero `dotnet build` exit (or a spawn error such as a missing
33
+ * `dotnet`) is a structured `{ kind: 'failure' }` carrying the captured
34
+ * output, so the caller can surface why the editor would disable the addon.
35
+ */
36
+ export declare function buildProject(options: BuildProjectOptions): Promise<BuildProjectResult>;
@@ -0,0 +1,174 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { spawn } from 'child_process';
4
+ import { resolveProjectPath, isGodotProjectDir } from './open.js';
5
+ import { emitProgress } from './progress.js';
6
+ /**
7
+ * Locate the single consumer `.csproj` directly at the Godot project root — the
8
+ * `.csproj` Godot compiles every project `.cs` (addon included) into. A
9
+ * `--dotnet` scaffold writes `<AssemblyName>.csproj` there. Returns `null` when
10
+ * the project has no root csproj (a GDScript-only project — nothing to build).
11
+ *
12
+ * When more than one csproj sits at the root, the first alphabetically is
13
+ * returned and the ambiguity is pushed onto `warnings` (all root csprojs compile
14
+ * into the same Godot assembly, so building one builds the dependency graph the
15
+ * editor will load). Pure / read-only `fs`. Exported for unit tests.
16
+ */
17
+ export function findProjectCsproj(projectPath, warnings) {
18
+ let names;
19
+ try {
20
+ names = fs.readdirSync(projectPath).filter((n) => n.toLowerCase().endsWith('.csproj'));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ if (names.length === 0)
26
+ return null;
27
+ names.sort();
28
+ if (names.length > 1) {
29
+ warnings.push(`Multiple .csproj files found at the project root (${names.join(', ')}); built ${names[0]}.`);
30
+ }
31
+ return path.join(projectPath, names[0]);
32
+ }
33
+ /** Default MSBuild configuration the build step compiles. */
34
+ const DEFAULT_CONFIGURATION = 'Debug';
35
+ /**
36
+ * Build the C# assembly for a Godot project BEFORE the editor opens, so the
37
+ * editor finds a compiled assembly when it instantiates enabled `EditorPlugin`s
38
+ * (otherwise a fresh first open fails with "Unable to load addon script … —
39
+ * Disabling the addon", godotengine/godot#112701-class behavior).
40
+ *
41
+ * Library-safe: never calls `process.exit`, never throws past the public
42
+ * boundary, never writes to stdout/stderr (observability is via `onProgress`).
43
+ *
44
+ * Behavior:
45
+ * - Validates the path is an existing Godot project (`project.godot`).
46
+ * - GDScript-only projects (no root `.csproj`) are a SUCCESS with
47
+ * `skipped: true` / `skipReason: 'no-csproj'` — there is nothing to compile.
48
+ * - C# projects (a root `.csproj`) are built ALWAYS via `dotnet build <csproj>`.
49
+ * `dotnet build` is itself incremental, so an up-to-date project is a fast
50
+ * no-op; building unconditionally avoids the staleness-detection bugs that a
51
+ * "build-if-missing/stale" heuristic would introduce (the exact failure mode
52
+ * this fix exists to prevent — a stale/absent assembly the editor can't load).
53
+ * - A non-zero `dotnet build` exit (or a spawn error such as a missing
54
+ * `dotnet`) is a structured `{ kind: 'failure' }` carrying the captured
55
+ * output, so the caller can surface why the editor would disable the addon.
56
+ */
57
+ export async function buildProject(options) {
58
+ const warnings = [];
59
+ let resolvedProjectPath;
60
+ try {
61
+ const { projectPath } = resolveProjectPath(options.projectPath, process.cwd());
62
+ resolvedProjectPath = projectPath;
63
+ if (!fs.existsSync(projectPath)) {
64
+ throw new Error(`Project path does not exist: ${projectPath}`);
65
+ }
66
+ if (!isGodotProjectDir(projectPath)) {
67
+ throw new Error(`Not a Godot project (missing project.godot): ${projectPath}`);
68
+ }
69
+ emitProgress(options.onProgress, {
70
+ phase: 'start',
71
+ message: `Building C# for Godot project at ${projectPath}`,
72
+ });
73
+ const csprojPath = findProjectCsproj(projectPath, warnings);
74
+ if (csprojPath === null) {
75
+ // GDScript-only project — nothing to compile. The editor opens fine
76
+ // without an assembly when no C# is present.
77
+ emitProgress(options.onProgress, {
78
+ phase: 'build-skipped',
79
+ message: 'No .csproj at the project root — GDScript-only project, skipping build.',
80
+ reason: 'no-csproj',
81
+ });
82
+ emitProgress(options.onProgress, { phase: 'done', message: 'Build skipped (no C#).' });
83
+ return {
84
+ kind: 'success',
85
+ success: true,
86
+ projectPath,
87
+ skipped: true,
88
+ skipReason: 'no-csproj',
89
+ warnings,
90
+ };
91
+ }
92
+ const configuration = options.configuration ?? DEFAULT_CONFIGURATION;
93
+ const dotnetBin = options.dotnetPath ?? 'dotnet';
94
+ const args = ['build', csprojPath, '--configuration', configuration];
95
+ emitProgress(options.onProgress, {
96
+ phase: 'build-running',
97
+ message: `Building ${path.basename(csprojPath)} (${configuration})`,
98
+ csprojPath,
99
+ command: [dotnetBin, ...args].join(' '),
100
+ });
101
+ const run = await runDotnetBuild(dotnetBin, args, projectPath, options.spawnImpl);
102
+ if (run.code !== 0) {
103
+ const detail = run.output.trim();
104
+ throw new Error(`dotnet build failed (exit ${run.code ?? 'null'}) for ${csprojPath}.` +
105
+ (detail.length > 0 ? `\n${detail}` : ''));
106
+ }
107
+ emitProgress(options.onProgress, {
108
+ phase: 'done',
109
+ message: `Built ${path.basename(csprojPath)} (${configuration}).`,
110
+ });
111
+ return {
112
+ kind: 'success',
113
+ success: true,
114
+ projectPath,
115
+ csprojPath,
116
+ configuration,
117
+ skipped: false,
118
+ output: run.output,
119
+ warnings,
120
+ };
121
+ }
122
+ catch (err) {
123
+ const errorObj = err instanceof Error ? err : new Error(String(err));
124
+ return {
125
+ kind: 'failure',
126
+ success: false,
127
+ projectPath: resolvedProjectPath,
128
+ warnings,
129
+ errorMessage: errorObj.message,
130
+ error: errorObj,
131
+ };
132
+ }
133
+ }
134
+ /**
135
+ * Spawn `dotnet build`, capturing stdout+stderr, and resolve once it exits.
136
+ * Unlike the editor launch (which detaches), the build is awaited to completion
137
+ * so the assembly exists before the caller proceeds. Library-safe: a spawn
138
+ * `error` (e.g. `dotnet` not on PATH) resolves as a non-zero run rather than
139
+ * throwing past the boundary. `spawnImpl` is injectable for unit tests.
140
+ */
141
+ function runDotnetBuild(bin, args, cwd, spawnImpl = spawn) {
142
+ return new Promise((resolve) => {
143
+ let settled = false;
144
+ const finish = (run) => {
145
+ if (settled)
146
+ return;
147
+ settled = true;
148
+ resolve(run);
149
+ };
150
+ let child;
151
+ try {
152
+ child = spawnImpl(bin, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
153
+ }
154
+ catch (err) {
155
+ const msg = err instanceof Error ? err.message : String(err);
156
+ finish({ code: 127, output: `Failed to spawn "${bin}": ${msg}` });
157
+ return;
158
+ }
159
+ let output = '';
160
+ child.stdout?.on('data', (chunk) => {
161
+ output += chunk.toString();
162
+ });
163
+ child.stderr?.on('data', (chunk) => {
164
+ output += chunk.toString();
165
+ });
166
+ child.on('error', (err) => {
167
+ finish({ code: 127, output: `${output}\nFailed to run "${bin}": ${err.message}` });
168
+ });
169
+ child.on('close', (code) => {
170
+ finish({ code, output });
171
+ });
172
+ });
173
+ }
174
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/lib/build.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,23 @@
1
1
  import { projectGodotPath as resolveProjectGodotPath } from '../utils/project-godot.js';
2
2
  import type { InstallPluginOptions, InstallPluginResult, RemovePluginOptions, RemovePluginResult } from './types.js';
3
3
  /**
4
- * Enable the `godot_mcp` addon in a project's `project.godot` `[editor_plugins]`
5
- * `enabled` array. Library-safe: no stdout noise, no process.exit, no throws
6
- * past the public boundary.
4
+ * Install the `godot_mcp` addon into a Godot C# project as a REAL installer:
7
5
  *
8
- * v1 is intentionally minimal it only flips the project.godot plugin-enable
9
- * state. It does NOT copy addon files or patch the consumer `.csproj` with the
10
- * NuGet PackageReferences the addon needs (that is the consumer's responsibility
11
- * per the addon's install docs); a warning surfaces that requirement.
6
+ * 1. Materialize `res://addons/godot_mcp/`by default downloading
7
+ * `godot-mcp-addon-<version>.zip` over HTTPS from github.com only (the
8
+ * `IvanMurzak/Godot-MCP` release `v<version>`), or, with `--source <path>`,
9
+ * copying the addon from a local directory (offline / dev / CI).
10
+ * 2. Add the two NuGet `PackageReference`s the addon needs to the consumer
11
+ * `.csproj`, idempotently and single-sourced from the addon's own pins.
12
+ * 3. Flip the `[editor_plugins] enabled` flag in `project.godot`.
12
13
  *
13
- * Idempotent: enabling an already-enabled plugin returns `changed: false`.
14
+ * Library-safe: no stdout noise, no `process.exit`, no throws past the public
15
+ * boundary; returns a `{ kind: 'success' | 'failure' }` union. Idempotent: a
16
+ * re-run that finds the addon present, the pins present, and the plugin already
17
+ * enabled reports `changed: false` and makes no writes. On a download/copy
18
+ * failure the project is left as found: both paths materialize into a temp
19
+ * sibling and only swap it into the addon dir after a fully successful
20
+ * fetch+extract / copy, so a partial materialization is rolled back.
14
21
  */
15
22
  export declare function installPlugin(opts: InstallPluginOptions): Promise<InstallPluginResult>;
16
23
  /**