breakpoint-mcp 1.74.0 โ 1.74.1
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/dist/bridge.js +11 -1
- package/dist/cli/args.js +32 -2
- package/dist/cli/doctor.js +8 -3
- package/dist/cli/init.js +22 -3
- package/dist/cli/tools.js +12 -15
- package/dist/cli/usage.js +102 -0
- package/dist/index.js +35 -38
- package/package.json +1 -1
package/dist/bridge.js
CHANGED
|
@@ -39,7 +39,17 @@ export class BridgeClient {
|
|
|
39
39
|
eventListeners = new Set();
|
|
40
40
|
wantConnected = false;
|
|
41
41
|
reconnectTimer = null;
|
|
42
|
-
constructor(host, port, defaultTimeoutMs, label = "editor bridge",
|
|
42
|
+
constructor(host, port, defaultTimeoutMs, label = "editor bridge",
|
|
43
|
+
// ๐ด THE SECOND SENTENCE IS THE ONE THAT EARNS ITS PLACE. The first asks a
|
|
44
|
+
// question whose answer, for the user most likely to be reading this line,
|
|
45
|
+
// is YES: the editor IS open and the plugin IS listed in project.godot.
|
|
46
|
+
// Godot reads `[editor_plugins]` at project load and never re-reads it, so
|
|
47
|
+
// an editor that was already running when `init` wrote the section keeps
|
|
48
|
+
// the plugin disabled โ the bridge never starts, every editor-plane tool is
|
|
49
|
+
// dark, and the remedy agrees with everything the user can see. `init` now
|
|
50
|
+
// warns at the point it writes; this is the same fact told to the person
|
|
51
|
+
// who did not read that line, or who read it a week ago.
|
|
52
|
+
hint = 'Is the editor open with the "Breakpoint MCP" plugin enabled? If it was ALREADY open when you ran `breakpoint-mcp init`, close and reopen the project โ Godot reads the enabled-plugin list only at project load.',
|
|
43
53
|
/**
|
|
44
54
|
* Loopback-auth secret provider, read lazily on each connect. When it
|
|
45
55
|
* returns a non-empty string the client sends it as the FIRST line on the
|
package/dist/cli/args.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function parseArgs(argv, booleanFlags = []) {
|
|
1
|
+
export function parseArgs(argv, booleanFlags = [], knownFlags) {
|
|
2
2
|
const bool = new Set(booleanFlags);
|
|
3
3
|
const positionals = [];
|
|
4
4
|
const flags = {};
|
|
@@ -35,6 +35,36 @@ export function parseArgs(argv, booleanFlags = []) {
|
|
|
35
35
|
}
|
|
36
36
|
positionals.push(a);
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
// Computed AFTER the loop rather than inside it, so `--flag=value`,
|
|
39
|
+
// `--flag value` and the bare boolean forms are all judged by the same rule โ
|
|
40
|
+
// the key that landed in `flags`, however it got there.
|
|
41
|
+
const known = knownFlags === undefined ? null : new Set([...knownFlags, ...booleanFlags]);
|
|
42
|
+
const unknown = known === null ? [] : Object.keys(flags).filter((k) => !known.has(k));
|
|
43
|
+
return { positionals, flags, unknown };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The two questions every subcommand must answer before it does any work: was
|
|
47
|
+
* `--help` asked for, and was it handed something it does not accept. Returns
|
|
48
|
+
* the exit code to return, or `null` to carry on.
|
|
49
|
+
*
|
|
50
|
+
* Shared rather than written per subcommand, because written per subcommand it
|
|
51
|
+
* was answered by exactly ONE of the three. `tools` handled `--help` and kept
|
|
52
|
+
* its own copy of the text; `doctor` ignored it and ran the checks; `init`
|
|
53
|
+
* ignored it and fell through to the project check, reporting a missing
|
|
54
|
+
* `project.godot` โ an error about the user's directory in answer to a
|
|
55
|
+
* question about flags.
|
|
56
|
+
*/
|
|
57
|
+
export function preflight(parsed, subcommand, usage) {
|
|
58
|
+
if (parsed.flags.help === true || parsed.flags.h === true) {
|
|
59
|
+
process.stdout.write(usage.join("\n") + "\n");
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
if (parsed.unknown.length > 0) {
|
|
63
|
+
const named = parsed.unknown.map((u) => (u.length === 1 ? `-${u}` : `--${u}`)).join(", ");
|
|
64
|
+
process.stderr.write(`${subcommand}: unknown ${parsed.unknown.length === 1 ? "option" : "options"} ${named}.\n` +
|
|
65
|
+
` Run \`breakpoint-mcp ${subcommand} --help\` for the options this subcommand accepts.\n`);
|
|
66
|
+
return 2;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
39
69
|
}
|
|
40
70
|
//# sourceMappingURL=args.js.map
|
package/dist/cli/doctor.js
CHANGED
|
@@ -23,7 +23,8 @@ import path from "node:path";
|
|
|
23
23
|
import { spawnSync } from "node:child_process";
|
|
24
24
|
import { loadConfig } from "../config.js";
|
|
25
25
|
import { CAPABILITY_GROUPS, droppedTools, selectPrivilegedGroups } from "../capabilities.js";
|
|
26
|
-
import { parseArgs } from "./args.js";
|
|
26
|
+
import { parseArgs, preflight } from "./args.js";
|
|
27
|
+
import { DOCTOR_FLAGS, DOCTOR_USAGE } from "./usage.js";
|
|
27
28
|
import { BridgeClient } from "../bridge.js";
|
|
28
29
|
import { resolveBridgeSecret } from "../secret.js";
|
|
29
30
|
const ADDON_REL = "addons/breakpoint_mcp";
|
|
@@ -257,7 +258,7 @@ export async function runDoctorChecks(config, opts) {
|
|
|
257
258
|
name: "editor-bridge",
|
|
258
259
|
host: config.bridgeHost,
|
|
259
260
|
port: config.bridgePort,
|
|
260
|
-
hint: 'Open the editor with the "Breakpoint MCP" plugin enabled.',
|
|
261
|
+
hint: 'Open the editor with the "Breakpoint MCP" plugin enabled โ and if it was already open when you ran `breakpoint-mcp init`, close and reopen the project (Godot reads the enabled-plugin list only at project load).',
|
|
261
262
|
secretEnv: ["BREAKPOINT_BRIDGE_SECRET"],
|
|
262
263
|
},
|
|
263
264
|
{
|
|
@@ -344,7 +345,11 @@ function printReport(report) {
|
|
|
344
345
|
}
|
|
345
346
|
/** Entry point for `breakpoint-mcp doctor`. Returns the process exit code. */
|
|
346
347
|
export async function runDoctor(argv) {
|
|
347
|
-
const
|
|
348
|
+
const parsed = parseArgs(argv, ["json", "require-live", "include-csharp", "help", "h"], DOCTOR_FLAGS);
|
|
349
|
+
const pre = preflight(parsed, "doctor", DOCTOR_USAGE);
|
|
350
|
+
if (pre !== null)
|
|
351
|
+
return pre;
|
|
352
|
+
const { flags } = parsed;
|
|
348
353
|
if (typeof flags.project === "string")
|
|
349
354
|
process.env.GODOT_PROJECT = flags.project;
|
|
350
355
|
const timeoutRaw = typeof flags.timeout === "string" ? Number.parseInt(flags.timeout, 10) : NaN;
|
package/dist/cli/init.js
CHANGED
|
@@ -12,7 +12,8 @@ import fs from "node:fs";
|
|
|
12
12
|
import os from "node:os";
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
15
|
-
import { parseArgs } from "./args.js";
|
|
15
|
+
import { parseArgs, preflight } from "./args.js";
|
|
16
|
+
import { INIT_FLAGS, INIT_USAGE } from "./usage.js";
|
|
16
17
|
import { CLIENT_IDS, clientInfo, mergeClientConfig, serverEntry, snippet } from "./clients.js";
|
|
17
18
|
import { DEFAULT_REPO, fetchAddonFromGitHub } from "./github.js";
|
|
18
19
|
import { CAPABILITY_GROUPS, PRIVILEGED_TOOL_COUNT, parsePrivilegedGroups, selectPrivilegedGroups, } from "../capabilities.js";
|
|
@@ -147,7 +148,11 @@ function claudeCodeCommand(projectPath, privilegedGroups) {
|
|
|
147
148
|
}
|
|
148
149
|
/** Entry point for `breakpoint-mcp init`. Returns the process exit code. */
|
|
149
150
|
export async function runInit(argv, deps = {}) {
|
|
150
|
-
const
|
|
151
|
+
const parsed = parseArgs(argv, ["force", "dry-run", "help", "h"], INIT_FLAGS);
|
|
152
|
+
const pre = preflight(parsed, "init", INIT_USAGE);
|
|
153
|
+
if (pre !== null)
|
|
154
|
+
return pre;
|
|
155
|
+
const { flags } = parsed;
|
|
151
156
|
const projectPath = typeof flags.project === "string"
|
|
152
157
|
? path.resolve(flags.project)
|
|
153
158
|
: process.env.GODOT_PROJECT ?? process.cwd();
|
|
@@ -292,7 +297,21 @@ export async function runInit(argv, deps = {}) {
|
|
|
292
297
|
if (privilegedWarn)
|
|
293
298
|
say(` note: ${privilegedWarn}`);
|
|
294
299
|
say("");
|
|
295
|
-
|
|
300
|
+
// ๐ด THE REOPEN TRAP. Godot reads project.godot's [editor_plugins] at project load and
|
|
301
|
+
// does not reload it, so an editor that was already running when we wrote the section
|
|
302
|
+
// keeps the plugin DISABLED โ the bridge never starts and every editor-plane tool is
|
|
303
|
+
// dark, with nothing on screen saying why. The line is conditioned on `en.changed`
|
|
304
|
+
// because a project whose plugin was already enabled has nothing to reopen for, and a
|
|
305
|
+
// warning printed on every run is a warning nobody reads.
|
|
306
|
+
if (!dryRun && en.changed) {
|
|
307
|
+
say("Next: open the project in Godot โ and if it is ALREADY OPEN, close and reopen it.");
|
|
308
|
+
say(" Godot reads project.godot's [editor_plugins] at project load and does not reload");
|
|
309
|
+
say(" it, so an editor that was already running keeps the plugin disabled.");
|
|
310
|
+
say("Then run `breakpoint-mcp doctor --require-live` to verify.");
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
say("Next: open the project in Godot, then run `breakpoint-mcp doctor --require-live` to verify.");
|
|
314
|
+
}
|
|
296
315
|
process.stdout.write(out.join("\n") + "\n");
|
|
297
316
|
return 0;
|
|
298
317
|
}
|
package/dist/cli/tools.js
CHANGED
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
* `--surface` picks which one populates `tools[]`; both counts are always in the
|
|
23
23
|
* header so a consumer cannot report one as the other by accident.
|
|
24
24
|
*/
|
|
25
|
-
import { parseArgs } from "./args.js";
|
|
25
|
+
import { parseArgs, preflight } from "./args.js";
|
|
26
|
+
import { TOOLS_FLAGS, TOOLS_USAGE } from "./usage.js";
|
|
26
27
|
import { buildToolsets } from "../toolsets.js";
|
|
27
28
|
import { applyOutputSchemas } from "../schemas.js";
|
|
28
29
|
import { applyAnnotations, annotationsFor } from "../annotations.js";
|
|
@@ -148,20 +149,16 @@ function renderText(report) {
|
|
|
148
149
|
return lines.join("\n");
|
|
149
150
|
}
|
|
150
151
|
export async function runTools(argv) {
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
"",
|
|
162
|
-
].join("\n"));
|
|
163
|
-
return 0;
|
|
164
|
-
}
|
|
152
|
+
const parsed = parseArgs(argv, ["json", "help", "h"], TOOLS_FLAGS);
|
|
153
|
+
const pre = preflight(parsed, "tools", [
|
|
154
|
+
...TOOLS_USAGE,
|
|
155
|
+
"",
|
|
156
|
+
"Reads no Godot install and starts no server โ the registry is built statically.",
|
|
157
|
+
"",
|
|
158
|
+
]);
|
|
159
|
+
if (pre !== null)
|
|
160
|
+
return pre;
|
|
161
|
+
const { flags } = parsed;
|
|
165
162
|
const raw = typeof flags.surface === "string" ? flags.surface : "secure-default";
|
|
166
163
|
if (raw !== "full" && raw !== "secure-default") {
|
|
167
164
|
process.stderr.write(`unknown --surface "${raw}" (expected: full | secure-default)\n`);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLI's help text, in ONE place, split by subcommand.
|
|
3
|
+
*
|
|
4
|
+
* It lived in `index.ts`'s `printUsage` as a single flat array, which was fine
|
|
5
|
+
* while `--help` was the only thing that printed it. It stopped being fine the
|
|
6
|
+
* moment `breakpoint-mcp init --help` had to print the init section and nothing
|
|
7
|
+
* else: the alternative to this module is the same twelve lines written twice,
|
|
8
|
+
* and a help text that disagrees with itself is worse than one that is merely
|
|
9
|
+
* long. `index.ts` composes the whole document from these parts, so a flag
|
|
10
|
+
* documented for a subcommand is documented in the top-level help by
|
|
11
|
+
* construction.
|
|
12
|
+
*
|
|
13
|
+
* ๐ด THE ROSTERS BELOW ARE NOT DOCUMENTATION โ THEY ARE THE PARSER'S INPUT.
|
|
14
|
+
* `parseArgs` takes them as `knownFlags` and reports anything else as unknown,
|
|
15
|
+
* so a flag added to a subcommand and not added here is refused at the command
|
|
16
|
+
* line rather than silently ignored. That is the whole point of keeping the
|
|
17
|
+
* prose and the roster in the same file: the pressure to update both is the
|
|
18
|
+
* same edit.
|
|
19
|
+
*/
|
|
20
|
+
export const HEADLINE = "breakpoint-mcp โ MCP server exposing Godot to AI coding assistants.";
|
|
21
|
+
export const SYNOPSIS = [
|
|
22
|
+
"Usage:",
|
|
23
|
+
" breakpoint-mcp Start the MCP server on stdio (default; how MCP clients launch it).",
|
|
24
|
+
" breakpoint-mcp init Install + enable the editor addon in a project and wire the MCP client.",
|
|
25
|
+
" breakpoint-mcp doctor Check the Godot binary, the editor addon, and the four bridges.",
|
|
26
|
+
" breakpoint-mcp tools Export the tool surface + risk annotations (for catalogs / reviews).",
|
|
27
|
+
" breakpoint-mcp --help Show this help.",
|
|
28
|
+
" breakpoint-mcp --version Print the installed version and exit.",
|
|
29
|
+
"",
|
|
30
|
+
"Every subcommand also accepts --help.",
|
|
31
|
+
];
|
|
32
|
+
export const INIT_USAGE = [
|
|
33
|
+
"Usage: breakpoint-mcp init [options]",
|
|
34
|
+
"",
|
|
35
|
+
"Install + enable the editor addon in a Godot project and wire the MCP client.",
|
|
36
|
+
"",
|
|
37
|
+
"init options:",
|
|
38
|
+
" --project <dir> Target Godot project (default: $GODOT_PROJECT or the current directory).",
|
|
39
|
+
" --client <id> Write the MCP config for a client: claude-code | claude-desktop | cursor | windsurf | vscode.",
|
|
40
|
+
" --force Overwrite an addon that is already installed.",
|
|
41
|
+
" --dry-run Print what would change without writing anything.",
|
|
42
|
+
" --from-github [ref] Fetch the editor addon from GitHub at [ref] (default: this package's version tag) instead of the bundled copy.",
|
|
43
|
+
" --repo <owner/repo> With --from-github, the source repo (default: jlivingston-Cipher/godot-breakpoint-mcp).",
|
|
44
|
+
" --trust <level> secure | full. `full` enables every higher-trust group (default: secure).",
|
|
45
|
+
" --privileged-groups <a,b> Enable named higher-trust groups instead of all of them.",
|
|
46
|
+
];
|
|
47
|
+
export const DOCTOR_USAGE = [
|
|
48
|
+
"Usage: breakpoint-mcp doctor [options]",
|
|
49
|
+
"",
|
|
50
|
+
"Check the Godot binary, the editor addon, and the four bridges.",
|
|
51
|
+
"",
|
|
52
|
+
"doctor options:",
|
|
53
|
+
" --project <dir> Project to check (default: $GODOT_PROJECT or the current directory).",
|
|
54
|
+
" --require-live Also require the editor/runtime/LSP/DAP bridges to be reachable.",
|
|
55
|
+
" --include-csharp Also probe OmniSharp / netcoredbg on PATH (the C# planes).",
|
|
56
|
+
" --timeout <ms> Per-bridge connect timeout (default 1500).",
|
|
57
|
+
" --json Emit the report as JSON.",
|
|
58
|
+
];
|
|
59
|
+
export const TOOLS_USAGE = [
|
|
60
|
+
"Usage: breakpoint-mcp tools [options]",
|
|
61
|
+
"",
|
|
62
|
+
"Export the tool surface + risk annotations (for catalogs / reviews).",
|
|
63
|
+
"",
|
|
64
|
+
"tools options:",
|
|
65
|
+
" --surface <which> full | secure-default (default: secure-default, what an untouched install advertises).",
|
|
66
|
+
" --json Emit the surface as JSON โ stable and timestamp-free, so releases can be diffed.",
|
|
67
|
+
];
|
|
68
|
+
/** Every flag `init` accepts. Booleans are declared at the call site. */
|
|
69
|
+
export const INIT_FLAGS = [
|
|
70
|
+
"project",
|
|
71
|
+
"client",
|
|
72
|
+
"from-github",
|
|
73
|
+
"repo",
|
|
74
|
+
"trust",
|
|
75
|
+
"privileged-groups",
|
|
76
|
+
];
|
|
77
|
+
/** Every flag `doctor` accepts. */
|
|
78
|
+
export const DOCTOR_FLAGS = ["project", "timeout"];
|
|
79
|
+
/** Every flag `tools` accepts. */
|
|
80
|
+
export const TOOLS_FLAGS = ["surface"];
|
|
81
|
+
/** The whole document, composed โ what `breakpoint-mcp --help` prints. */
|
|
82
|
+
export function fullUsage() {
|
|
83
|
+
// Each subcommand block contributes only its own `<name> options:` tail; the
|
|
84
|
+
// per-subcommand synopsis above it would read as four competing headlines in
|
|
85
|
+
// a single document.
|
|
86
|
+
const tail = (block) => block.slice(block.findIndex((l) => l.endsWith("options:")));
|
|
87
|
+
return [
|
|
88
|
+
HEADLINE,
|
|
89
|
+
"",
|
|
90
|
+
...SYNOPSIS,
|
|
91
|
+
"",
|
|
92
|
+
...tail(INIT_USAGE),
|
|
93
|
+
"",
|
|
94
|
+
...tail(DOCTOR_USAGE),
|
|
95
|
+
"",
|
|
96
|
+
...tail(TOOLS_USAGE),
|
|
97
|
+
"",
|
|
98
|
+
"All runtime configuration is via environment variables; see the README.",
|
|
99
|
+
"",
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=usage.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { CsLspClient } from "./cslsp.js";
|
|
|
9
9
|
import { CsDapClient } from "./csdap.js";
|
|
10
10
|
import { StdioChannel } from "./stdio.js";
|
|
11
11
|
import { DapClient } from "./dap.js";
|
|
12
|
+
import { fullUsage } from "./cli/usage.js";
|
|
12
13
|
import { buildToolsets } from "./toolsets.js";
|
|
13
14
|
import { registerRecipes } from "./recipes.js";
|
|
14
15
|
import { applyWireDefaults } from "./wire-defaults.js";
|
|
@@ -42,7 +43,7 @@ async function main() {
|
|
|
42
43
|
// so long jobs (export/import/headless script) support poll/await/cancel.
|
|
43
44
|
// D3: also advertise resources.subscribe so clients can subscribe to
|
|
44
45
|
// godot://โฆ resources and receive notifications/resources/updated.
|
|
45
|
-
const server = new McpServer({ name: "breakpoint-mcp", version: "1.74.
|
|
46
|
+
const server = new McpServer({ name: "breakpoint-mcp", version: "1.74.1" }, { capabilities: { ...TASK_CAPABILITIES, ...RESOURCE_CAPABILITIES }, taskStore });
|
|
46
47
|
// 208 ยง7.1 โ delete from the wire what the protocol already says: the SDK's
|
|
47
48
|
// draft-07 `$schema` inside every input/output schema (MCP's default dialect is
|
|
48
49
|
// 2020-12, and declaring another is an explicit switch a peer may reject), and
|
|
@@ -160,44 +161,26 @@ async function main() {
|
|
|
160
161
|
process.on("SIGTERM", shutdown);
|
|
161
162
|
}
|
|
162
163
|
function printUsage() {
|
|
163
|
-
process.stdout.write(
|
|
164
|
-
"breakpoint-mcp โ MCP server exposing Godot to AI coding assistants.",
|
|
165
|
-
"",
|
|
166
|
-
"Usage:",
|
|
167
|
-
" breakpoint-mcp Start the MCP server on stdio (default; how MCP clients launch it).",
|
|
168
|
-
" breakpoint-mcp init Install + enable the editor addon in a project and wire the MCP client.",
|
|
169
|
-
" breakpoint-mcp doctor Check the Godot binary, the editor addon, and the four bridges.",
|
|
170
|
-
" breakpoint-mcp tools Export the tool surface + risk annotations (for catalogs / reviews).",
|
|
171
|
-
" breakpoint-mcp --help Show this help.",
|
|
172
|
-
"",
|
|
173
|
-
"init options:",
|
|
174
|
-
" --project <dir> Target Godot project (default: $GODOT_PROJECT or the current directory).",
|
|
175
|
-
" --client <id> Write the MCP config for a client: claude-code | claude-desktop | cursor | windsurf | vscode.",
|
|
176
|
-
" --force Overwrite an addon that is already installed.",
|
|
177
|
-
" --dry-run Print what would change without writing anything.",
|
|
178
|
-
" --from-github [ref] Fetch the editor addon from GitHub at [ref] (default: this package's version tag) instead of the bundled copy.",
|
|
179
|
-
" --repo <owner/repo> With --from-github, the source repo (default: jlivingston-Cipher/godot-breakpoint-mcp).",
|
|
180
|
-
" --trust <level> secure | full. `full` enables every higher-trust group (default: secure).",
|
|
181
|
-
" --privileged-groups <a,b> Enable named higher-trust groups instead of all of them.",
|
|
182
|
-
"",
|
|
183
|
-
"doctor options:",
|
|
184
|
-
" --project <dir> Project to check (default: $GODOT_PROJECT or the current directory).",
|
|
185
|
-
" --require-live Also require the editor/runtime/LSP/DAP bridges to be reachable.",
|
|
186
|
-
" --include-csharp Also probe OmniSharp / netcoredbg on PATH (the C# planes).",
|
|
187
|
-
" --timeout <ms> Per-bridge connect timeout (default 1500).",
|
|
188
|
-
" --json Emit the report as JSON.",
|
|
189
|
-
"",
|
|
190
|
-
"tools options:",
|
|
191
|
-
" --surface <which> full | secure-default (default: secure-default, what an untouched install advertises).",
|
|
192
|
-
" --json Emit the surface as JSON โ stable and timestamp-free, so releases can be diffed.",
|
|
193
|
-
"",
|
|
194
|
-
"All runtime configuration is via environment variables; see the README.",
|
|
195
|
-
"",
|
|
196
|
-
].join("\n"));
|
|
164
|
+
process.stdout.write(fullUsage().join("\n"));
|
|
197
165
|
}
|
|
198
|
-
// Subcommand dispatch.
|
|
199
|
-
//
|
|
200
|
-
//
|
|
166
|
+
// Subcommand dispatch. NO arguments at all is how every MCP client launches
|
|
167
|
+
// this โ every invocation in the README, the user guide and `init`'s own
|
|
168
|
+
// emitted config passes the binary an empty argv โ so that case, and only that
|
|
169
|
+
// case, starts the stdio server. The launch contract is unchanged.
|
|
170
|
+
//
|
|
171
|
+
// ๐ด WHAT CHANGED IS THE FALL-THROUGH, WHICH USED TO SWALLOW EVERYTHING ELSE.
|
|
172
|
+
// `breakpoint-mcp --version` started a server. So did `-v`, `version`, and any
|
|
173
|
+
// mistyped flag: the process printed one ready line and then sat on a stdin
|
|
174
|
+
// nobody was going to speak MCP into, which in a terminal is a hang. The two
|
|
175
|
+
// halves of that are separate defects and both are user-facing:
|
|
176
|
+
//
|
|
177
|
+
// * There was NO WAY TO ASK THIS BINARY ITS VERSION. `--version` is the most
|
|
178
|
+
// universal convention a CLI has, and the first thing anyone filing a bug
|
|
179
|
+
// report is asked for. A project with 0 issues against ~3,700 downloads
|
|
180
|
+
// cannot afford a version query that hangs the terminal instead.
|
|
181
|
+
// * An unrecognized token is a TYPO, and the only useful thing to do with one
|
|
182
|
+
// is name it. Falling through spends the user's next twenty minutes on the
|
|
183
|
+
// wrong question.
|
|
201
184
|
void (async () => {
|
|
202
185
|
const sub = process.argv[2];
|
|
203
186
|
if (sub === "doctor") {
|
|
@@ -216,6 +199,20 @@ void (async () => {
|
|
|
216
199
|
printUsage();
|
|
217
200
|
process.exit(0);
|
|
218
201
|
}
|
|
202
|
+
if (sub === "version" || sub === "--version" || sub === "-v" || sub === "-V") {
|
|
203
|
+
// Bare, so `breakpoint-mcp --version` is usable in a shell substitution.
|
|
204
|
+
// Read from package.json rather than written here: see version.ts on the
|
|
205
|
+
// twenty releases that announced 0.2.0 to every LSP server they met.
|
|
206
|
+
const { packageVersion } = await import("./version.js");
|
|
207
|
+
process.stdout.write(`${packageVersion()}\n`);
|
|
208
|
+
process.exit(0);
|
|
209
|
+
}
|
|
210
|
+
if (sub !== undefined) {
|
|
211
|
+
process.stderr.write(`breakpoint-mcp: unknown argument '${sub}'.\n` +
|
|
212
|
+
" Run `breakpoint-mcp --help` for the subcommands and their options.\n" +
|
|
213
|
+
" To start the MCP server, run it with no arguments โ that is how MCP clients launch it.\n");
|
|
214
|
+
process.exit(2);
|
|
215
|
+
}
|
|
219
216
|
await main();
|
|
220
217
|
})().catch((err) => {
|
|
221
218
|
log("fatal:", err instanceof Error ? err.stack ?? err.message : String(err));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "breakpoint-mcp",
|
|
3
|
-
"version": "1.74.
|
|
3
|
+
"version": "1.74.1",
|
|
4
4
|
"description": "MCP server exposing Godot to AI coding assistants over the Model Context Protocol โ developed and tested with Claude โ across four planes (CLI, live editor, LSP+DAP, runtime) with elicitation-gated destructive tools, long jobs on the formal MCP task model, captured console output, and MCP resources.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|