godot-cli 0.16.1 → 0.17.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.
Files changed (43) hide show
  1. package/dist/commands/configure.js +24 -1
  2. package/dist/commands/configure.js.map +1 -1
  3. package/dist/commands/install-plugin.js +99 -7
  4. package/dist/commands/install-plugin.js.map +1 -1
  5. package/dist/commands/login.js +53 -15
  6. package/dist/commands/login.js.map +1 -1
  7. package/dist/lib/configure-agent.d.ts +20 -0
  8. package/dist/lib/configure-agent.js +115 -0
  9. package/dist/lib/configure-agent.js.map +1 -0
  10. package/dist/lib/enroll.d.ts +21 -0
  11. package/dist/lib/enroll.js +100 -0
  12. package/dist/lib/enroll.js.map +1 -0
  13. package/dist/lib/install-server.d.ts +25 -0
  14. package/dist/lib/install-server.js +234 -0
  15. package/dist/lib/install-server.js.map +1 -0
  16. package/dist/lib/types.d.ts +138 -0
  17. package/dist/lib.d.ts +4 -1
  18. package/dist/lib.js +3 -0
  19. package/dist/lib.js.map +1 -1
  20. package/dist/utils/addon-deps.js +2 -2
  21. package/dist/utils/addon-deps.js.map +1 -1
  22. package/dist/utils/cloud-login.d.ts +22 -4
  23. package/dist/utils/cloud-login.js +40 -17
  24. package/dist/utils/cloud-login.js.map +1 -1
  25. package/dist/utils/connection.d.ts +4 -7
  26. package/dist/utils/connection.js +8 -10
  27. package/dist/utils/connection.js.map +1 -1
  28. package/dist/utils/enroll.d.ts +39 -0
  29. package/dist/utils/enroll.js +66 -0
  30. package/dist/utils/enroll.js.map +1 -0
  31. package/dist/utils/machine-credentials.d.ts +74 -0
  32. package/dist/utils/machine-credentials.js +182 -0
  33. package/dist/utils/machine-credentials.js.map +1 -0
  34. package/dist/utils/project-identity.d.ts +76 -0
  35. package/dist/utils/project-identity.js +111 -0
  36. package/dist/utils/project-identity.js.map +1 -0
  37. package/dist/utils/project-marker.d.ts +64 -0
  38. package/dist/utils/project-marker.js +192 -0
  39. package/dist/utils/project-marker.js.map +1 -0
  40. package/dist/utils/server-source.d.ts +84 -0
  41. package/dist/utils/server-source.js +217 -0
  42. package/dist/utils/server-source.js.map +1 -0
  43. package/package.json +1 -1
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The tool-neutral, committable **project marker** `<project>/.ai-game-dev/project.json`
3
+ * (design 06 / D15). It is NON-secret — credentials NEVER go here — and records:
4
+ *
5
+ * - `serverTarget` — the hub URL the enrolled plugin should connect to (hosted
6
+ * `https://ai-game.dev` or a local `http://localhost:<port>`), returned by the
7
+ * enrollment-redeem endpoint.
8
+ * - `pin` — the D14 routing pin (first 8 hex of the ProjectIdentity SHA256), so
9
+ * the plugin, the CLIs, and `configure` all agree which project the session
10
+ * routes to.
11
+ * - `port` — the deterministic local port (SHA256→20000–29999) recorded for a
12
+ * localhost target so a terminal-written config and the plugin never diverge.
13
+ * - `portOverride` — an explicit user port override (D15) that always wins.
14
+ *
15
+ * ProjectIdentity resolution and every config writer consult it, so an override
16
+ * or target can never silently diverge between the plugin and a terminal-written
17
+ * config.
18
+ */
19
+ export declare const PROJECT_MARKER_RELATIVE_PATH: string;
20
+ export interface ProjectMarker {
21
+ /** The enrolled server target URL (hosted or local). */
22
+ serverTarget?: string;
23
+ /** The D14 routing pin (first 8 hex of the ProjectIdentity hash). */
24
+ pin?: string;
25
+ /** The deterministic local port (recorded for localhost targets). */
26
+ port?: number;
27
+ /** An explicit user port override (always wins over the derived port). */
28
+ portOverride?: number;
29
+ /** Forward-compatible: unknown keys are preserved on rewrite. */
30
+ [key: string]: unknown;
31
+ }
32
+ /** Absolute path of the marker file for a project. */
33
+ export declare function getProjectMarkerPath(projectPath: string): string;
34
+ /** Read the marker, or null when absent / empty / malformed. Never throws. */
35
+ export declare function readProjectMarker(projectPath: string): ProjectMarker | null;
36
+ /**
37
+ * Write the marker, MERGING over any existing document so a re-enroll never drops
38
+ * a previously-set `portOverride` or forward-compatible key. Creates the
39
+ * `.ai-game-dev/` directory if needed. The supplied `patch` fields overwrite the
40
+ * existing values; every other existing field is preserved.
41
+ */
42
+ export declare function writeProjectMarker(projectPath: string, patch: ProjectMarker): ProjectMarker;
43
+ /** True when `url`'s host is a loopback address (localhost / 127.0.0.1 / ::1). Never throws. */
44
+ export declare function isLocalhostUrl(url: string): boolean;
45
+ /**
46
+ * Append (or replace) the `/p/<pin>` routing segment on an MCP-server URL —
47
+ * the D14 project pin the plugin routes on. A URL already ending in `/p/<hex>`
48
+ * has its pin REPLACED (idempotent re-enroll); otherwise `/p/<pin>` is appended
49
+ * to the existing path. Query/hash are preserved. Returns the input unchanged on
50
+ * a malformed URL. Pure.
51
+ */
52
+ export declare function applyPinToUrl(url: string, pin: string): string;
53
+ /**
54
+ * Upsert the D14 pin into the URL of the `ai-game-developer` entry of every
55
+ * EXISTING project-local agent config (design 06 — "upserts the D14 pin into any
56
+ * existing project-local agent config entry"), so a hosted/local server the user
57
+ * added manually before enrolling becomes pinned. Best-effort: user-global
58
+ * configs (Claude Desktop, Cline, …) are skipped; a config with no
59
+ * `ai-game-developer` entry or no URL is left untouched; a malformed/unreadable
60
+ * file is skipped without throwing. Returns the absolute paths that were
61
+ * rewritten. JSON configs rewrite the `url`/`serverUrl` value; the Codex TOML
62
+ * config rewrites its `url = "…"` line.
63
+ */
64
+ export declare function upsertPinIntoAgentConfigs(projectPath: string, pin: string): string[];
@@ -0,0 +1,192 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { PIN_LENGTH } from './project-identity.js';
4
+ import { agentRegistry, MCP_SERVER_NAME } from './agents.js';
5
+ /**
6
+ * The tool-neutral, committable **project marker** `<project>/.ai-game-dev/project.json`
7
+ * (design 06 / D15). It is NON-secret — credentials NEVER go here — and records:
8
+ *
9
+ * - `serverTarget` — the hub URL the enrolled plugin should connect to (hosted
10
+ * `https://ai-game.dev` or a local `http://localhost:<port>`), returned by the
11
+ * enrollment-redeem endpoint.
12
+ * - `pin` — the D14 routing pin (first 8 hex of the ProjectIdentity SHA256), so
13
+ * the plugin, the CLIs, and `configure` all agree which project the session
14
+ * routes to.
15
+ * - `port` — the deterministic local port (SHA256→20000–29999) recorded for a
16
+ * localhost target so a terminal-written config and the plugin never diverge.
17
+ * - `portOverride` — an explicit user port override (D15) that always wins.
18
+ *
19
+ * ProjectIdentity resolution and every config writer consult it, so an override
20
+ * or target can never silently diverge between the plugin and a terminal-written
21
+ * config.
22
+ */
23
+ export const PROJECT_MARKER_RELATIVE_PATH = path.join('.ai-game-dev', 'project.json');
24
+ /** Absolute path of the marker file for a project. */
25
+ export function getProjectMarkerPath(projectPath) {
26
+ return path.join(projectPath, PROJECT_MARKER_RELATIVE_PATH);
27
+ }
28
+ /** Read the marker, or null when absent / empty / malformed. Never throws. */
29
+ export function readProjectMarker(projectPath) {
30
+ const markerPath = getProjectMarkerPath(projectPath);
31
+ if (!fs.existsSync(markerPath))
32
+ return null;
33
+ try {
34
+ const raw = fs.readFileSync(markerPath, 'utf-8');
35
+ if (raw.trim().length === 0)
36
+ return null;
37
+ const parsed = JSON.parse(raw);
38
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
39
+ return null;
40
+ return parsed;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ /**
47
+ * Write the marker, MERGING over any existing document so a re-enroll never drops
48
+ * a previously-set `portOverride` or forward-compatible key. Creates the
49
+ * `.ai-game-dev/` directory if needed. The supplied `patch` fields overwrite the
50
+ * existing values; every other existing field is preserved.
51
+ */
52
+ export function writeProjectMarker(projectPath, patch) {
53
+ const markerPath = getProjectMarkerPath(projectPath);
54
+ const dir = path.dirname(markerPath);
55
+ if (!fs.existsSync(dir)) {
56
+ fs.mkdirSync(dir, { recursive: true });
57
+ }
58
+ const existing = readProjectMarker(projectPath) ?? {};
59
+ const merged = { ...existing, ...patch };
60
+ fs.writeFileSync(markerPath, JSON.stringify(merged, null, 2) + '\n');
61
+ return merged;
62
+ }
63
+ /** True when `url`'s host is a loopback address (localhost / 127.0.0.1 / ::1). Never throws. */
64
+ export function isLocalhostUrl(url) {
65
+ try {
66
+ const host = new URL(url).hostname.toLowerCase();
67
+ return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]';
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * Append (or replace) the `/p/<pin>` routing segment on an MCP-server URL —
75
+ * the D14 project pin the plugin routes on. A URL already ending in `/p/<hex>`
76
+ * has its pin REPLACED (idempotent re-enroll); otherwise `/p/<pin>` is appended
77
+ * to the existing path. Query/hash are preserved. Returns the input unchanged on
78
+ * a malformed URL. Pure.
79
+ */
80
+ export function applyPinToUrl(url, pin) {
81
+ let parsed;
82
+ try {
83
+ parsed = new URL(url);
84
+ }
85
+ catch {
86
+ return url;
87
+ }
88
+ const segments = parsed.pathname.split('/').filter((s) => s.length > 0);
89
+ const hexLen = PIN_LENGTH; // 8
90
+ const isPinHex = (s) => new RegExp(`^[0-9a-f]{${hexLen}}$`, 'i').test(s);
91
+ if (segments.length >= 2 && segments[segments.length - 2] === 'p' && isPinHex(segments[segments.length - 1])) {
92
+ segments[segments.length - 1] = pin;
93
+ }
94
+ else {
95
+ segments.push('p', pin);
96
+ }
97
+ parsed.pathname = '/' + segments.join('/');
98
+ return parsed.toString();
99
+ }
100
+ /** True when `configPath` resolves INSIDE `projectPath` (a project-local, not user-global, config). */
101
+ function isProjectLocalConfig(configPath, projectPath) {
102
+ const root = path.resolve(projectPath) + path.sep;
103
+ return path.resolve(configPath).startsWith(root);
104
+ }
105
+ /**
106
+ * Upsert the D14 pin into the URL of the `ai-game-developer` entry of every
107
+ * EXISTING project-local agent config (design 06 — "upserts the D14 pin into any
108
+ * existing project-local agent config entry"), so a hosted/local server the user
109
+ * added manually before enrolling becomes pinned. Best-effort: user-global
110
+ * configs (Claude Desktop, Cline, …) are skipped; a config with no
111
+ * `ai-game-developer` entry or no URL is left untouched; a malformed/unreadable
112
+ * file is skipped without throwing. Returns the absolute paths that were
113
+ * rewritten. JSON configs rewrite the `url`/`serverUrl` value; the Codex TOML
114
+ * config rewrites its `url = "…"` line.
115
+ */
116
+ export function upsertPinIntoAgentConfigs(projectPath, pin) {
117
+ const updated = [];
118
+ for (const agent of agentRegistry) {
119
+ let configPath;
120
+ try {
121
+ configPath = agent.getConfigPath(projectPath);
122
+ }
123
+ catch {
124
+ continue;
125
+ }
126
+ if (!isProjectLocalConfig(configPath, projectPath))
127
+ continue;
128
+ if (!fs.existsSync(configPath))
129
+ continue;
130
+ try {
131
+ if (agent.configFormat === 'toml') {
132
+ if (upsertPinInTomlConfig(configPath, pin))
133
+ updated.push(configPath);
134
+ }
135
+ else {
136
+ if (upsertPinInJsonConfig(configPath, agent.bodyPath, pin))
137
+ updated.push(configPath);
138
+ }
139
+ }
140
+ catch {
141
+ // Best-effort: a single unreadable/malformed config never fails enrollment.
142
+ }
143
+ }
144
+ return updated;
145
+ }
146
+ /** Rewrite the `url`/`serverUrl` of `bodyPath.ai-game-developer` in a JSON config. Returns true when changed. */
147
+ function upsertPinInJsonConfig(configPath, bodyPath, pin) {
148
+ const root = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
149
+ if (!root || typeof root !== 'object' || Array.isArray(root))
150
+ return false;
151
+ const body = root[bodyPath];
152
+ if (!body || typeof body !== 'object' || Array.isArray(body))
153
+ return false;
154
+ const entry = body[MCP_SERVER_NAME];
155
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry))
156
+ return false;
157
+ // The registry uses `url` for most agents and `serverUrl` for Antigravity.
158
+ const urlKey = typeof entry['url'] === 'string' ? 'url' : typeof entry['serverUrl'] === 'string' ? 'serverUrl' : null;
159
+ if (!urlKey)
160
+ return false;
161
+ const current = entry[urlKey];
162
+ const pinned = applyPinToUrl(current, pin);
163
+ if (pinned === current)
164
+ return false;
165
+ entry[urlKey] = pinned;
166
+ fs.writeFileSync(configPath, JSON.stringify(root, null, 2) + '\n');
167
+ return true;
168
+ }
169
+ /** Rewrite the `url = "…"` line under `[mcp_servers.ai-game-developer]` in a Codex TOML config. Returns true when changed. */
170
+ function upsertPinInTomlConfig(configPath, pin) {
171
+ const lines = fs.readFileSync(configPath, 'utf-8').split('\n');
172
+ const header = `[mcp_servers.${MCP_SERVER_NAME}]`;
173
+ const sectionIdx = lines.findIndex((l) => l.trim() === header);
174
+ if (sectionIdx < 0)
175
+ return false;
176
+ for (let i = sectionIdx + 1; i < lines.length; i++) {
177
+ const trimmed = lines[i].trim();
178
+ if (trimmed.startsWith('['))
179
+ break; // next section
180
+ const m = trimmed.match(/^url\s*=\s*"([^"]*)"\s*$/);
181
+ if (m) {
182
+ const pinned = applyPinToUrl(m[1], pin);
183
+ if (pinned === m[1])
184
+ return false;
185
+ lines[i] = `url = "${pinned}"`;
186
+ fs.writeFileSync(configPath, lines.join('\n'));
187
+ return true;
188
+ }
189
+ }
190
+ return false;
191
+ }
192
+ //# sourceMappingURL=project-marker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-marker.js","sourceRoot":"","sources":["../../src/utils/project-marker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The DEFAULT shared-server version `--with-server` downloads. Single-sourced
3
+ * from the addon's `GodotMcpServerView.ServerVersion` constant (parity-tested).
4
+ * `--server-version <v>` overrides it; `--server-source <path>` skips the
5
+ * download entirely (offline / CI). Bumping the addon's server pin requires
6
+ * bumping this in the same PR or the parity test goes red.
7
+ */
8
+ export declare const DEFAULT_SERVER_VERSION = "9.0.0";
9
+ /** GitHub-release host the server zip + manifest are downloaded from. NOTHING else is trusted. */
10
+ export declare const TRUSTED_DOWNLOAD_HOST = "github.com";
11
+ /** The `owner/repo` the shared server releases live under. */
12
+ export declare const SERVER_RELEASE_REPO = "IvanMurzak/GameDev-MCP-Server";
13
+ /** The server-binary base name (matches the addon's `GodotMcpServerView.ExecutableName`). */
14
+ export declare const SERVER_EXECUTABLE_NAME = "gamedev-mcp-server";
15
+ /** The release-asset / RID prefix (matches the addon's `AssetPrefix`). */
16
+ export declare const SERVER_ASSET_PREFIX = "gamedev-mcp-server";
17
+ /** The integrity-manifest asset attached to every GameDev-MCP-Server release. */
18
+ export declare const SHA256SUMS_ASSET_NAME = "SHA256SUMS";
19
+ /** Map a Node `process.platform` token to the .NET RID os segment (`win`/`osx`/`linux`). */
20
+ export declare function osToken(platform?: NodeJS.Platform): string;
21
+ /** Map a Node `process.arch` token to the .NET RID arch segment (`x86`/`x64`/`arm`/`arm64`). */
22
+ export declare function archToken(arch?: string): string;
23
+ /**
24
+ * The RID-style platform name `<os>-<arch>` (e.g. `win-x64`) for the given (or
25
+ * current) host. Matches the addon's `GodotMcpServerView.PlatformName` and the
26
+ * GameDev-MCP-Server release asset RIDs (linux-arm64/linux-x64/osx-arm64/osx-x64/
27
+ * win-arm64/win-x64/win-x86). Pure.
28
+ */
29
+ export declare function detectHostRid(platform?: NodeJS.Platform, arch?: string): string;
30
+ /** The on-disk executable file name for an os: `gamedev-mcp-server.exe` on Windows, else `gamedev-mcp-server`. */
31
+ export declare function serverExecutableFileName(platform?: NodeJS.Platform): string;
32
+ /** The GitHub release-zip asset name for a RID: `gamedev-mcp-server-<rid>.zip`. Pure. */
33
+ export declare function serverAssetName(rid: string): string;
34
+ /** The git release TAG for a server version: the version with a leading `v` (`9.0.0` → `v9.0.0`). Pure. */
35
+ export declare function serverReleaseTag(version: string): string;
36
+ /**
37
+ * The download URL for a server version's per-RID zip:
38
+ * `https://github.com/IvanMurzak/GameDev-MCP-Server/releases/download/v<version>/gamedev-mcp-server-<rid>.zip`.
39
+ * Mirrors `GodotMcpServerView.DownloadUrl`. The host is always `github.com` by
40
+ * construction; `assertTrustedServerUrl` re-checks a URL before any network call. Pure.
41
+ */
42
+ export declare function serverDownloadUrl(version: string, rid: string): string;
43
+ /**
44
+ * The `SHA256SUMS` manifest URL — the sibling of the per-RID zip under the SAME
45
+ * `v<version>` release tag. Mirrors `GodotMcpServerView.Sha256SumsUrl`. Pure.
46
+ */
47
+ export declare function sha256SumsUrl(version: string): string;
48
+ /**
49
+ * Fail-closed host trust check: throw unless `url` is an HTTPS URL whose host is
50
+ * EXACTLY `github.com` (no subdomains, no `github.com.evil.test`, no http). The
51
+ * security boundary the task requires for the server download. Returns the parsed
52
+ * URL on success. Pure (throws on the unhappy path; callers turn it into a
53
+ * structured failure so nothing escapes the public boundary).
54
+ */
55
+ export declare function assertTrustedServerUrl(url: string): URL;
56
+ /**
57
+ * Parse a coreutils `sha256sum` manifest into a `{filename → lowercase-hex-digest}`
58
+ * map. One line per file: a 64-char hex digest, whitespace, then the file name.
59
+ * Tolerances (matching the C# reference): CRLF + bare-LF; blank lines skipped;
60
+ * leading/trailing whitespace trimmed; the binary-mode `*` marker before the
61
+ * filename stripped; a line whose first token is not 64-hex, or which has no
62
+ * filename, is skipped (never a spurious entry — fail-closed at lookup). On a
63
+ * duplicate filename the LAST entry wins. Never throws. Pure.
64
+ */
65
+ export declare function parseSha256Sums(sha256SumsText: string | null | undefined): Map<string, string>;
66
+ /** Look up the expected digest for an asset zip name in a parsed manifest, or null when absent. Pure. */
67
+ export declare function lookupDigest(parsed: Map<string, string>, assetZipName: string): string | null;
68
+ /** Case-insensitive hex-digest equality (both trimmed). A null/empty side is NEVER a match (fail-closed). Pure. */
69
+ export declare function digestMatches(expectedHexDigest: string | null | undefined, actualHexDigest: string | null | undefined): boolean;
70
+ /** The verdict of verifying a downloaded zip against a release `SHA256SUMS` manifest. */
71
+ export type ChecksumVerdict = 'verified' | 'manifest-unparsable' | 'missing-entry' | 'digest-mismatch';
72
+ /**
73
+ * The single fail-closed integrity decision the installer calls BEFORE extract:
74
+ * parse the release `SHA256SUMS`, find the entry for `assetZipName`, and compare
75
+ * it (case-insensitive hex) against the locally-computed SHA256 of the downloaded
76
+ * zip. Returns `'verified'` ONLY when the manifest parsed, contained the asset,
77
+ * and the digest matched; every other outcome is a distinct fail-closed verdict
78
+ * the caller MUST treat as "do NOT extract". Never throws. Pure.
79
+ */
80
+ export declare function verifyZipChecksum(sha256SumsText: string | null | undefined, assetZipName: string, actualZipHexDigest: string | null | undefined): ChecksumVerdict;
81
+ /** A short, actionable reason for a non-`verified` verdict, for the installer's fail-closed error. Pure. */
82
+ export declare function checksumFailureReason(verdict: ChecksumVerdict, assetZipName: string): string;
83
+ /** The lowercase hex SHA256 of a byte buffer (the downloaded zip). Pure. */
84
+ export declare function sha256Hex(bytes: Buffer): string;
@@ -0,0 +1,217 @@
1
+ // Pure helpers for resolving WHERE the shared `gamedev-mcp-server` binary comes
2
+ // from when `install-plugin --with-server` materializes it: RID detection, the
3
+ // trusted GitHub-release download URL, the `SHA256SUMS` integrity manifest, and
4
+ // the fail-closed verify verdict. These MIRROR the addon's own server logic in
5
+ // `addons/godot_mcp/Runtime/Connection/GodotMcpServerView.cs` (github.com only,
6
+ // `releases/download/v<version>/gamedev-mcp-server-<rid>.zip`, verify-before-
7
+ // extract against `SHA256SUMS`). No side effects; unit-testable with no network.
8
+ //
9
+ // The DEFAULT server version is single-sourced from the addon's pinned
10
+ // `ServerVersion` constant (a parity test — `cli/tests/server-source-parity.test.ts`
11
+ // — reads `GodotMcpServerView.cs` and FAILS the build if this drifts), so the CLI
12
+ // and the addon can never download two different server versions.
13
+ import { createHash } from 'crypto';
14
+ /**
15
+ * The DEFAULT shared-server version `--with-server` downloads. Single-sourced
16
+ * from the addon's `GodotMcpServerView.ServerVersion` constant (parity-tested).
17
+ * `--server-version <v>` overrides it; `--server-source <path>` skips the
18
+ * download entirely (offline / CI). Bumping the addon's server pin requires
19
+ * bumping this in the same PR or the parity test goes red.
20
+ */
21
+ export const DEFAULT_SERVER_VERSION = '9.0.0';
22
+ /** GitHub-release host the server zip + manifest are downloaded from. NOTHING else is trusted. */
23
+ export const TRUSTED_DOWNLOAD_HOST = 'github.com';
24
+ /** The `owner/repo` the shared server releases live under. */
25
+ export const SERVER_RELEASE_REPO = 'IvanMurzak/GameDev-MCP-Server';
26
+ /** The server-binary base name (matches the addon's `GodotMcpServerView.ExecutableName`). */
27
+ export const SERVER_EXECUTABLE_NAME = 'gamedev-mcp-server';
28
+ /** The release-asset / RID prefix (matches the addon's `AssetPrefix`). */
29
+ export const SERVER_ASSET_PREFIX = SERVER_EXECUTABLE_NAME;
30
+ /** The integrity-manifest asset attached to every GameDev-MCP-Server release. */
31
+ export const SHA256SUMS_ASSET_NAME = 'SHA256SUMS';
32
+ /** Map a Node `process.platform` token to the .NET RID os segment (`win`/`osx`/`linux`). */
33
+ export function osToken(platform = process.platform) {
34
+ switch (platform) {
35
+ case 'win32':
36
+ return 'win';
37
+ case 'darwin':
38
+ return 'osx';
39
+ case 'linux':
40
+ return 'linux';
41
+ default:
42
+ return 'unknown';
43
+ }
44
+ }
45
+ /** Map a Node `process.arch` token to the .NET RID arch segment (`x86`/`x64`/`arm`/`arm64`). */
46
+ export function archToken(arch = process.arch) {
47
+ switch (arch) {
48
+ case 'x64':
49
+ return 'x64';
50
+ case 'arm64':
51
+ return 'arm64';
52
+ case 'ia32':
53
+ return 'x86';
54
+ case 'arm':
55
+ return 'arm';
56
+ default:
57
+ return 'unknown';
58
+ }
59
+ }
60
+ /**
61
+ * The RID-style platform name `<os>-<arch>` (e.g. `win-x64`) for the given (or
62
+ * current) host. Matches the addon's `GodotMcpServerView.PlatformName` and the
63
+ * GameDev-MCP-Server release asset RIDs (linux-arm64/linux-x64/osx-arm64/osx-x64/
64
+ * win-arm64/win-x64/win-x86). Pure.
65
+ */
66
+ export function detectHostRid(platform = process.platform, arch = process.arch) {
67
+ return `${osToken(platform)}-${archToken(arch)}`;
68
+ }
69
+ /** The on-disk executable file name for an os: `gamedev-mcp-server.exe` on Windows, else `gamedev-mcp-server`. */
70
+ export function serverExecutableFileName(platform = process.platform) {
71
+ return platform === 'win32' ? `${SERVER_EXECUTABLE_NAME}.exe` : SERVER_EXECUTABLE_NAME;
72
+ }
73
+ /** The GitHub release-zip asset name for a RID: `gamedev-mcp-server-<rid>.zip`. Pure. */
74
+ export function serverAssetName(rid) {
75
+ return `${SERVER_ASSET_PREFIX}-${rid}.zip`;
76
+ }
77
+ /** The git release TAG for a server version: the version with a leading `v` (`9.0.0` → `v9.0.0`). Pure. */
78
+ export function serverReleaseTag(version) {
79
+ const v = (version ?? '').trim();
80
+ return v.startsWith('v') ? v : `v${v}`;
81
+ }
82
+ /**
83
+ * The download URL for a server version's per-RID zip:
84
+ * `https://github.com/IvanMurzak/GameDev-MCP-Server/releases/download/v<version>/gamedev-mcp-server-<rid>.zip`.
85
+ * Mirrors `GodotMcpServerView.DownloadUrl`. The host is always `github.com` by
86
+ * construction; `assertTrustedServerUrl` re-checks a URL before any network call. Pure.
87
+ */
88
+ export function serverDownloadUrl(version, rid) {
89
+ return `https://${TRUSTED_DOWNLOAD_HOST}/${SERVER_RELEASE_REPO}/releases/download/${serverReleaseTag(version)}/${serverAssetName(rid)}`;
90
+ }
91
+ /**
92
+ * The `SHA256SUMS` manifest URL — the sibling of the per-RID zip under the SAME
93
+ * `v<version>` release tag. Mirrors `GodotMcpServerView.Sha256SumsUrl`. Pure.
94
+ */
95
+ export function sha256SumsUrl(version) {
96
+ return `https://${TRUSTED_DOWNLOAD_HOST}/${SERVER_RELEASE_REPO}/releases/download/${serverReleaseTag(version)}/${SHA256SUMS_ASSET_NAME}`;
97
+ }
98
+ /**
99
+ * Fail-closed host trust check: throw unless `url` is an HTTPS URL whose host is
100
+ * EXACTLY `github.com` (no subdomains, no `github.com.evil.test`, no http). The
101
+ * security boundary the task requires for the server download. Returns the parsed
102
+ * URL on success. Pure (throws on the unhappy path; callers turn it into a
103
+ * structured failure so nothing escapes the public boundary).
104
+ */
105
+ export function assertTrustedServerUrl(url) {
106
+ let parsed;
107
+ try {
108
+ parsed = new URL(url);
109
+ }
110
+ catch {
111
+ throw new Error(`Refusing to download server: malformed URL "${url}".`);
112
+ }
113
+ if (parsed.protocol !== 'https:') {
114
+ throw new Error(`Refusing to download server: only https is allowed, got "${parsed.protocol}" (${url}).`);
115
+ }
116
+ if (parsed.hostname.toLowerCase() !== TRUSTED_DOWNLOAD_HOST) {
117
+ throw new Error(`Refusing to download server from untrusted host "${parsed.hostname}". Only ${TRUSTED_DOWNLOAD_HOST} is trusted.`);
118
+ }
119
+ return parsed;
120
+ }
121
+ // --- SHA256SUMS integrity manifest (download-verify-before-extract, fail-closed) ---
122
+ // Ported from GodotMcpServerView.{ParseSha256Sums,LookupDigest,DigestMatches,VerifyZipChecksum}
123
+ // so the CLI and the addon apply byte-identical integrity rules.
124
+ /** True when `value` is exactly 64 ASCII hex characters (a SHA256 hex digest). */
125
+ function isHex64(value) {
126
+ if (value.length !== 64)
127
+ return false;
128
+ return /^[0-9a-fA-F]{64}$/.test(value);
129
+ }
130
+ /**
131
+ * Parse a coreutils `sha256sum` manifest into a `{filename → lowercase-hex-digest}`
132
+ * map. One line per file: a 64-char hex digest, whitespace, then the file name.
133
+ * Tolerances (matching the C# reference): CRLF + bare-LF; blank lines skipped;
134
+ * leading/trailing whitespace trimmed; the binary-mode `*` marker before the
135
+ * filename stripped; a line whose first token is not 64-hex, or which has no
136
+ * filename, is skipped (never a spurious entry — fail-closed at lookup). On a
137
+ * duplicate filename the LAST entry wins. Never throws. Pure.
138
+ */
139
+ export function parseSha256Sums(sha256SumsText) {
140
+ const map = new Map();
141
+ if (!sha256SumsText)
142
+ return map;
143
+ for (const rawLine of sha256SumsText.replace(/\r\n/g, '\n').split('\n')) {
144
+ const line = rawLine.trim();
145
+ if (line.length === 0)
146
+ continue;
147
+ // Split into the digest token and the remainder (the filename) on the FIRST
148
+ // run of whitespace, so single-space/tab variants still parse.
149
+ let sepIndex = -1;
150
+ for (let i = 0; i < line.length; i++) {
151
+ if (line[i] === ' ' || line[i] === '\t') {
152
+ sepIndex = i;
153
+ break;
154
+ }
155
+ }
156
+ if (sepIndex <= 0 || sepIndex >= line.length - 1)
157
+ continue;
158
+ const digestToken = line.slice(0, sepIndex);
159
+ if (!isHex64(digestToken))
160
+ continue;
161
+ let fileName = line.slice(sepIndex + 1).replace(/^[ \t]+/, '');
162
+ if (fileName.startsWith('*'))
163
+ fileName = fileName.slice(1);
164
+ fileName = fileName.trim();
165
+ if (fileName.length === 0)
166
+ continue;
167
+ map.set(fileName, digestToken.toLowerCase());
168
+ }
169
+ return map;
170
+ }
171
+ /** Look up the expected digest for an asset zip name in a parsed manifest, or null when absent. Pure. */
172
+ export function lookupDigest(parsed, assetZipName) {
173
+ if (!parsed || !assetZipName)
174
+ return null;
175
+ return parsed.get(assetZipName) ?? null;
176
+ }
177
+ /** Case-insensitive hex-digest equality (both trimmed). A null/empty side is NEVER a match (fail-closed). Pure. */
178
+ export function digestMatches(expectedHexDigest, actualHexDigest) {
179
+ if (!expectedHexDigest || !expectedHexDigest.trim() || !actualHexDigest || !actualHexDigest.trim())
180
+ return false;
181
+ return expectedHexDigest.trim().toLowerCase() === actualHexDigest.trim().toLowerCase();
182
+ }
183
+ /**
184
+ * The single fail-closed integrity decision the installer calls BEFORE extract:
185
+ * parse the release `SHA256SUMS`, find the entry for `assetZipName`, and compare
186
+ * it (case-insensitive hex) against the locally-computed SHA256 of the downloaded
187
+ * zip. Returns `'verified'` ONLY when the manifest parsed, contained the asset,
188
+ * and the digest matched; every other outcome is a distinct fail-closed verdict
189
+ * the caller MUST treat as "do NOT extract". Never throws. Pure.
190
+ */
191
+ export function verifyZipChecksum(sha256SumsText, assetZipName, actualZipHexDigest) {
192
+ const parsed = parseSha256Sums(sha256SumsText);
193
+ if (parsed.size === 0)
194
+ return 'manifest-unparsable';
195
+ const expected = lookupDigest(parsed, assetZipName);
196
+ if (expected === null)
197
+ return 'missing-entry';
198
+ return digestMatches(expected, actualZipHexDigest) ? 'verified' : 'digest-mismatch';
199
+ }
200
+ /** A short, actionable reason for a non-`verified` verdict, for the installer's fail-closed error. Pure. */
201
+ export function checksumFailureReason(verdict, assetZipName) {
202
+ switch (verdict) {
203
+ case 'manifest-unparsable':
204
+ return `the downloaded ${SHA256SUMS_ASSET_NAME} manifest was empty or unparsable`;
205
+ case 'missing-entry':
206
+ return `the ${SHA256SUMS_ASSET_NAME} manifest has no entry for '${assetZipName}'`;
207
+ case 'digest-mismatch':
208
+ return `the downloaded '${assetZipName}' SHA256 did not match the ${SHA256SUMS_ASSET_NAME} manifest entry`;
209
+ default:
210
+ return 'the checksum was verified';
211
+ }
212
+ }
213
+ /** The lowercase hex SHA256 of a byte buffer (the downloaded zip). Pure. */
214
+ export function sha256Hex(bytes) {
215
+ return createHash('sha256').update(bytes).digest('hex');
216
+ }
217
+ //# sourceMappingURL=server-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-source.js","sourceRoot":"","sources":["../../src/utils/server-source.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "godot-cli",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "description": "Cross-platform CLI tool for Godot-MCP (Skills & MCP). Resolves and launches the Godot editor with MCP connection env vars, runs MCP/system tools over HTTP, probes server health, configures AI agents (Claude Code, Cursor, VS Code, …), and enables/disables the godot_mcp addon. Works with Claude Code, Cursor, Copilot, and any MCP client.",
5
5
  "type": "module",
6
6
  "main": "dist/lib.js",