@girardmedia/bootspring 2.5.7 → 2.5.9

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.
@@ -26,18 +26,19 @@ var C = {
26
26
  red: "\x1B[31m"
27
27
  };
28
28
  var HELP_GROUPS = {
29
- "Core": ["auth", "init", "project", "switch", "health", "mcp", "dashboard", "context"],
30
- "Build & Deploy": ["build", "deploy", "loop", "quality", "security", "doctor", "update"],
31
- "Planning": ["plan", "prd", "seed", "manager"],
32
- "Pipeline & Workflows": ["pipeline", "workflow", "harness"],
33
- "Agents & Skills": ["agent", "skill", "todo", "billing", "plugin"],
34
- "Analysis": ["analyze", "audit", "monitor", "metrics", "validate", "visualize"],
29
+ "Core": ["auth", "init", "project", "switch", "health", "doctor", "mcp", "dashboard", "context", "setup", "go"],
30
+ "Build & Deploy": ["build", "deploy", "loop", "quality", "security", "update", "undo", "scaffold", "guardian"],
31
+ "Planning": ["plan", "prd", "seed", "manager", "spec"],
32
+ "Pipeline & Workflows": ["pipeline", "workflow", "harness", "flow", "autonomous", "pair"],
33
+ "Agents & Skills": ["agent", "skill", "todo", "billing", "plugin", "studio", "prompt"],
34
+ "Analysis & Quality": ["analyze", "audit", "monitor", "metrics", "validate", "visualize", "graph", "diff", "review-code", "arch", "predict", "profile", "runtime", "testgen"],
35
+ "AI & Models": ["model", "local", "learn", "memory", "suggest", "orchestrator"],
36
+ "Intelligence": ["observe", "autopilot", "watch", "timemachine", "team", "network", "report"],
35
37
  "Pro Tools": ["geo", "marketing", "sales", "jobs"],
36
38
  "Docs & Content": ["generate", "content", "docs"],
37
- "Intelligence": ["learn", "memory", "suggest", "orchestrator", "watch", "observe", "autopilot"],
38
39
  "Business": ["business", "fundraise", "legal", "org"],
39
- "Infrastructure": ["workspace", "cloud-sync", "github", "onboard", "checkpoint", "setup"],
40
- "Tools": ["log", "mvp", "task", "telemetry"]
40
+ "Infrastructure": ["workspace", "cloud-sync", "github", "onboard", "checkpoint", "sync", "issue"],
41
+ "Tools": ["log", "mvp", "task", "telemetry", "visual"]
41
42
  };
42
43
  function showHelp() {
43
44
  console.log(`${C.cyan}${C.bold}\u26A1 Bootspring${C.reset} ${C.dim}v${VERSION}${C.reset}`);
@@ -67,14 +68,15 @@ function showHelp() {
67
68
  console.log(`${C.cyan}${C.bold}MORE${C.reset}`);
68
69
  console.log(` ${C.green}bootspring doctor${C.reset} ${C.dim}Diagnose project issues${C.reset}`);
69
70
  console.log(` ${C.green}bootspring observe${C.reset} ${C.dim}Session intelligence and analytics${C.reset}`);
70
- console.log(` ${C.green}bootspring commands${C.reset} ${C.dim}Show all ${Object.values(HELP_GROUPS).flat().length}+ commands${C.reset}`);
71
+ console.log(` ${C.green}bootspring commands${C.reset} ${C.dim}Show all ${Object.values(HELP_GROUPS).flat().length} commands${C.reset}`);
71
72
  console.log(`
72
73
  ${C.dim}Run "bootspring <command> --help" for details${C.reset}`);
73
74
  console.log(`${C.dim}Docs: https://bootspring.com/docs${C.reset}
74
75
  `);
75
76
  }
76
77
  function showFullCommands() {
77
- console.log(`${C.cyan}${C.bold}\u26A1 Bootspring${C.reset} ${C.dim}v${VERSION} \u2014 All Commands${C.reset}
78
+ const total = Object.values(HELP_GROUPS).flat().length;
79
+ console.log(`${C.cyan}${C.bold}\u26A1 Bootspring${C.reset} ${C.dim}v${VERSION} \u2014 ${total} commands${C.reset}
78
80
  `);
79
81
  for (const [group, cmds] of Object.entries(HELP_GROUPS)) {
80
82
  console.log(`${C.bold}${group}:${C.reset} ${cmds.map((command) => `${C.green}${command}${C.reset}`).join(", ")}`);
package/dist/core.js CHANGED
@@ -21625,7 +21625,7 @@ var require_package = __commonJS({
21625
21625
  "../../../package.json"(exports2, module2) {
21626
21626
  module2.exports = {
21627
21627
  name: "bootspring-workspace",
21628
- version: "2.5.7",
21628
+ version: "2.5.9",
21629
21629
  private: true,
21630
21630
  description: "Workspace tooling for the Bootspring monorepo",
21631
21631
  keywords: [
@@ -52219,7 +52219,7 @@ var require_package = __commonJS({
52219
52219
  "../../../package.json"(exports2, module2) {
52220
52220
  module2.exports = {
52221
52221
  name: "bootspring-workspace",
52222
- version: "2.5.7",
52222
+ version: "2.5.9",
52223
52223
  private: true,
52224
52224
  description: "Workspace tooling for the Bootspring monorepo",
52225
52225
  keywords: [
@@ -52481,10 +52481,59 @@ function createAuthError(message) {
52481
52481
  isError: true
52482
52482
  };
52483
52483
  }
52484
+ function diagnoseApiSurface() {
52485
+ const required = ["callMcpTool", "listMcpTools", "listMcpResources", "getMcpResource"];
52486
+ const missing = required.filter((fn) => typeof api2?.[fn] !== "function");
52487
+ if (missing.length === 0) return null;
52488
+ return [
52489
+ `Bootspring MCP server v${VERSION} is missing required API methods: ${missing.join(", ")}.`,
52490
+ `This usually means the installed @girardmedia/bootspring package is out of date.`,
52491
+ `Fix:`,
52492
+ ` 1. Quit Claude Code completely`,
52493
+ ` 2. npm i -g @girardmedia/bootspring@latest`,
52494
+ ` 3. Restart Claude Code so the MCP server reloads`
52495
+ ].join("\n");
52496
+ }
52497
+ function formatProxyError(error) {
52498
+ if (error?.status === 401) {
52499
+ return "Authentication expired. Run `bootspring auth login` to re-authenticate.";
52500
+ }
52501
+ if (error?.status === 403) {
52502
+ return "This MCP capability requires a paid Bootspring plan.";
52503
+ }
52504
+ if (error?.status === 404) {
52505
+ const serverMessage = typeof error?.message === "string" ? error.message : "";
52506
+ if (serverMessage && /mcp tool/i.test(serverMessage)) {
52507
+ return `${serverMessage}. This typically means the hosted API doesn't yet route that tool, or the CLI catalog is ahead of the server catalog.`;
52508
+ }
52509
+ return "This MCP tool is not available on the connected Bootspring API. Check that you are pointed at a current API server.";
52510
+ }
52511
+ if (error?.code === "ECONNREFUSED" || error?.code === "ENOTFOUND" || error?.code === "ETIMEDOUT" || error?.code === "EHOSTUNREACH") {
52512
+ return `Cannot reach Bootspring API (${error.code}). Check your internet connection or BOOTSPRING_API_URL.`;
52513
+ }
52514
+ return error?.message || "Unknown error from Bootspring API.";
52515
+ }
52516
+ var LOCAL_TOOLS = /* @__PURE__ */ new Set(["bootspring_build", "bootspring_seed", "bootspring_todo"]);
52517
+ function formatLocalToolGuidance(name, args) {
52518
+ const action = args && typeof args.action === "string" ? args.action : "";
52519
+ const base = name.replace(/^bootspring_/, "bootspring ");
52520
+ const cmd = action ? `${base} ${action}` : base;
52521
+ return [
52522
+ `\`${name}\` is a local-state tool \u2014 it reads and writes files in your project (.bootspring/state, planning/, etc.) and therefore cannot be executed from the hosted MCP API.`,
52523
+ ``,
52524
+ `Run this in your project terminal:`,
52525
+ ` ${cmd}`,
52526
+ ``,
52527
+ `Everything else in this conversation will still work \u2014 only local-state tools need to run from your shell.`
52528
+ ].join("\n");
52529
+ }
52484
52530
  async function resolveTools() {
52485
52531
  if (!auth2.isAuthenticated()) {
52486
52532
  return FALLBACK_TOOLS;
52487
52533
  }
52534
+ if (typeof api2?.listMcpTools !== "function") {
52535
+ return FALLBACK_TOOLS;
52536
+ }
52488
52537
  try {
52489
52538
  const response = await api2.listMcpTools();
52490
52539
  const apiTools = Array.isArray(response) ? response : response.tools || [];
@@ -52499,6 +52548,9 @@ async function resolveResources() {
52499
52548
  if (!auth2.isAuthenticated()) {
52500
52549
  return FALLBACK_RESOURCES;
52501
52550
  }
52551
+ if (typeof api2?.listMcpResources !== "function") {
52552
+ return FALLBACK_RESOURCES;
52553
+ }
52502
52554
  try {
52503
52555
  const response = await api2.listMcpResources();
52504
52556
  return Array.isArray(response) ? response : response.resources || FALLBACK_RESOURCES;
@@ -52507,18 +52559,34 @@ async function resolveResources() {
52507
52559
  }
52508
52560
  }
52509
52561
  async function proxyToolCall(name, args) {
52562
+ if (LOCAL_TOOLS.has(name)) {
52563
+ return {
52564
+ content: [{ type: "text", text: formatLocalToolGuidance(name, args) }]
52565
+ };
52566
+ }
52510
52567
  if (!auth2.isAuthenticated()) {
52511
52568
  return createAuthError("Authentication required. Run `bootspring auth login` first.");
52512
52569
  }
52570
+ const surfaceError = diagnoseApiSurface();
52571
+ if (surfaceError) {
52572
+ return {
52573
+ content: [{ type: "text", text: surfaceError }],
52574
+ isError: true
52575
+ };
52576
+ }
52513
52577
  try {
52514
52578
  const response = await api2.callMcpTool(name, args || {});
52579
+ if (response && response.result && response.result.status === "local_execution_required") {
52580
+ return {
52581
+ content: [{ type: "text", text: response.result.message || formatLocalToolGuidance(name, args) }]
52582
+ };
52583
+ }
52515
52584
  return {
52516
52585
  content: [{ type: "text", text: formatTextContent(response.result || response) }]
52517
52586
  };
52518
52587
  } catch (error) {
52519
- const message = error.status === 403 ? "This MCP capability requires a paid Bootspring plan." : error.message;
52520
52588
  return {
52521
- content: [{ type: "text", text: `Error: ${message}` }],
52589
+ content: [{ type: "text", text: `Error: ${formatProxyError(error)} (bootspring v${VERSION})` }],
52522
52590
  isError: true
52523
52591
  };
52524
52592
  }
@@ -52533,6 +52601,16 @@ async function proxyResourceRead(uri) {
52533
52601
  }]
52534
52602
  };
52535
52603
  }
52604
+ const surfaceError = diagnoseApiSurface();
52605
+ if (surfaceError) {
52606
+ return {
52607
+ contents: [{
52608
+ uri,
52609
+ mimeType: "text/plain",
52610
+ text: surfaceError
52611
+ }]
52612
+ };
52613
+ }
52536
52614
  try {
52537
52615
  const response = await api2.getMcpResource(uri);
52538
52616
  return {
@@ -52547,7 +52625,7 @@ async function proxyResourceRead(uri) {
52547
52625
  contents: [{
52548
52626
  uri,
52549
52627
  mimeType: "text/plain",
52550
- text: `Error: ${error.message}`
52628
+ text: `Error: ${formatProxyError(error)} (bootspring v${VERSION})`
52551
52629
  }]
52552
52630
  };
52553
52631
  }
@@ -52577,6 +52655,10 @@ async function main() {
52577
52655
  const transport = new StdioServerTransport();
52578
52656
  await server.connect(transport);
52579
52657
  console.error(`Bootspring MCP proxy v${VERSION} started`);
52658
+ const surfaceError = diagnoseApiSurface();
52659
+ if (surfaceError) {
52660
+ console.error("[bootspring-mcp] WARNING: " + surfaceError.split("\n").join(" "));
52661
+ }
52580
52662
  }
52581
52663
  if (require.main === module) {
52582
52664
  main().catch((error) => {
@@ -52591,5 +52673,24 @@ module.exports = {
52591
52673
  resourceHandlers,
52592
52674
  FALLBACK_TOOLS,
52593
52675
  FALLBACK_RESOURCES,
52594
- main
52676
+ main,
52677
+ // Exposed for tests — lock in the stale-install regression guard
52678
+ _diagnoseApiSurface: diagnoseApiSurface,
52679
+ _formatProxyError: formatProxyError,
52680
+ _LOCAL_TOOLS: LOCAL_TOOLS,
52681
+ _formatLocalToolGuidance: formatLocalToolGuidance,
52682
+ _proxyToolCall: proxyToolCall,
52683
+ _diagnoseFromApi: function diagnoseFromApi(apiShim, version) {
52684
+ const required = ["callMcpTool", "listMcpTools", "listMcpResources", "getMcpResource"];
52685
+ const missing = required.filter((fn) => typeof apiShim?.[fn] !== "function");
52686
+ if (missing.length === 0) return null;
52687
+ return [
52688
+ `Bootspring MCP server v${version} is missing required API methods: ${missing.join(", ")}.`,
52689
+ `This usually means the installed @girardmedia/bootspring package is out of date.`,
52690
+ `Fix:`,
52691
+ ` 1. Quit Claude Code completely`,
52692
+ ` 2. npm i -g @girardmedia/bootspring@latest`,
52693
+ ` 3. Restart Claude Code so the MCP server reloads`
52694
+ ].join("\n");
52695
+ }
52595
52696
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@girardmedia/bootspring",
3
- "version": "2.5.7",
3
+ "version": "2.5.9",
4
4
  "description": "Thin client for Bootspring cloud MCP, hosted agents, and paywalled workflow intelligence",
5
5
  "keywords": [
6
6
  "ai",
@@ -6,6 +6,7 @@ const path = require('path');
6
6
 
7
7
  const c = {
8
8
  reset: '\x1b[0m',
9
+ bold: '\x1b[1m',
9
10
  green: '\x1b[32m',
10
11
  yellow: '\x1b[33m',
11
12
  cyan: '\x1b[36m',
@@ -207,11 +208,31 @@ function registerAllMcp() {
207
208
  return [registerClaudeMcp(), registerCodexMcp(), registerGeminiMcp()];
208
209
  }
209
210
 
211
+ function isFirstInstall() {
212
+ // Heuristic: a first install is one where Claude Code config does NOT yet
213
+ // have a bootspring entry. Updates to an existing install will already
214
+ // have one and shouldn't see the welcome screen.
215
+ try {
216
+ const claudeConfig = path.join(HOME, '.claude.json');
217
+ if (!fs.existsSync(claudeConfig)) return true;
218
+ const raw = fs.readFileSync(claudeConfig, 'utf8');
219
+ if (!raw.trim()) return true;
220
+ const parsed = JSON.parse(raw);
221
+ return !parsed?.mcpServers?.bootspring;
222
+ } catch {
223
+ return false;
224
+ }
225
+ }
226
+
210
227
  function main() {
211
228
  if (process.env.CI || process.env.BOOTSPRING_SKIP_POSTINSTALL) {
212
229
  return;
213
230
  }
214
231
 
232
+ // Capture this BEFORE we run any registration so the welcome message
233
+ // only fires the first time bootspring is installed on this machine.
234
+ const firstInstall = isFirstInstall();
235
+
215
236
  let totalCommandsInstalled = 0;
216
237
  let totalSkillsInstalled = 0;
217
238
  const installedTo = [];
@@ -260,9 +281,20 @@ ${c.dim}Installed:${c.reset}
260
281
  console.log(`${c.yellow}Note:${c.reset} ${c.dim}MCP registration skipped for ${mcpSkipped.map((r) => r.name).join(', ')} — run \`bootspring setup\` to retry.${c.reset}`);
261
282
  }
262
283
 
263
- console.log(`
284
+ if (firstInstall) {
285
+ console.log(`
286
+ ${c.bold}Next steps:${c.reset}
287
+ ${c.cyan}1.${c.reset} Restart your assistant (Claude Code / Codex / Gemini) so MCP loads
288
+ ${c.cyan}2.${c.reset} ${c.green}bootspring auth login${c.reset} ${c.dim}# authenticate (opens browser)${c.reset}
289
+ ${c.cyan}3.${c.reset} ${c.green}cd${c.reset} into a project, then ${c.green}bootspring go${c.reset} ${c.dim}# one-shot setup${c.reset}
290
+
291
+ ${c.dim}Run ${c.reset}${c.green}bootspring${c.reset}${c.dim} with no args to see the welcome screen.${c.reset}
292
+ `);
293
+ } else {
294
+ console.log(`
264
295
  ${c.dim}Restart your assistant (Claude Code, Codex, or Gemini CLI) to load the bootspring MCP tools.${c.reset}
265
296
  `);
297
+ }
266
298
  }
267
299
  }
268
300