@bridge_gpt/mcp-server 0.2.25 → 0.2.27

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 (73) hide show
  1. package/README.md +59 -9
  2. package/build/agents.generated.js +1 -1
  3. package/build/bridge-api-urls.js +31 -0
  4. package/build/commands.generated.js +4 -4
  5. package/build/conductor-bin.js +68 -9267
  6. package/build/conductor-bundle-artifacts.js +802 -0
  7. package/build/conductor-bundle-cli.js +256 -0
  8. package/build/conductor-claude-hook-bin.js +2 -172
  9. package/build/decision-page-template.js +2 -31
  10. package/build/docs.generated.js +2 -1
  11. package/build/doctor.js +148 -1
  12. package/build/env-flags.js +31 -0
  13. package/build/index.js +4659 -34836
  14. package/build/init.js +87 -59
  15. package/build/install-bridge.js +380 -22
  16. package/build/mcp-host-config.js +521 -0
  17. package/build/mcp-host-targets.js +194 -0
  18. package/build/mcp-install-state.js +175 -0
  19. package/build/pipelines.generated.js +5 -4
  20. package/build/readme.generated.js +1 -1
  21. package/build/start-tickets.js +118 -5
  22. package/build/tool-surface-gating.js +396 -0
  23. package/build/version.generated.js +1 -1
  24. package/docs/install/mcp-tool-integrations.md +2 -2
  25. package/package.json +5 -7
  26. package/design-assets/favicon/android-chrome-192x192.png +0 -0
  27. package/design-assets/favicon/android-chrome-512x512.png +0 -0
  28. package/design-assets/favicon/apple-touch-icon.png +0 -0
  29. package/design-assets/favicon/favicon-16x16.png +0 -0
  30. package/design-assets/favicon/favicon.ico +0 -0
  31. package/design-assets/favicon/site.webmanifest +0 -1
  32. package/public/css/main.min.css +0 -4971
  33. package/public/css/main.min.css.map +0 -1
  34. package/public/fonts/OFL.txt +0 -93
  35. package/public/fonts/SourceSansPro-Black.ttf +0 -0
  36. package/public/fonts/SourceSansPro-BlackItalic.ttf +0 -0
  37. package/public/fonts/SourceSansPro-Bold.ttf +0 -0
  38. package/public/fonts/SourceSansPro-BoldItalic.ttf +0 -0
  39. package/public/fonts/SourceSansPro-ExtraLight.ttf +0 -0
  40. package/public/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
  41. package/public/fonts/SourceSansPro-Italic.ttf +0 -0
  42. package/public/fonts/SourceSansPro-Light.ttf +0 -0
  43. package/public/fonts/SourceSansPro-LightItalic.ttf +0 -0
  44. package/public/fonts/SourceSansPro-Regular.ttf +0 -0
  45. package/public/fonts/SourceSansPro-SemiBold.ttf +0 -0
  46. package/public/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
  47. package/public/img/bridge-logo-160x51.webp +0 -0
  48. package/public/img/bridge-logo-300x92.webp +0 -0
  49. package/public/img/favicon/android-chrome-192x192.png +0 -0
  50. package/public/img/favicon/android-chrome-512x512.png +0 -0
  51. package/public/img/favicon/apple-touch-icon.png +0 -0
  52. package/public/img/favicon/favicon-16x16.png +0 -0
  53. package/public/img/favicon/favicon-32x32.png +0 -0
  54. package/public/img/favicon/favicon.ico +0 -0
  55. package/public/img/favicon/site.webmanifest +0 -1
  56. package/public/img/installation/bitbucket/app-password-1.png +0 -0
  57. package/public/img/installation/bitbucket/app-password-2.png +0 -0
  58. package/public/img/installation/bitbucket/create-token-1.png +0 -0
  59. package/public/img/installation/bitbucket/create-token-2.png +0 -0
  60. package/public/img/installation/bitbucket/webhook-1.png +0 -0
  61. package/public/img/installation/github/github-review-webhook.png +0 -0
  62. package/public/img/installation/jira/credentials/api-key.png +0 -0
  63. package/public/img/installation/jira/webhook/create-rule.png +0 -0
  64. package/public/img/installation/jira/webhook/project-settings.png +0 -0
  65. package/public/img/installation/jira/webhook/rule-create-1.png +0 -0
  66. package/public/img/installation/jira/webhook/rule-create-2.png +0 -0
  67. package/public/img/installation/jira/webhook/rule-create-3.png +0 -0
  68. package/public/img/installation/pinecone/pinecone-api-key.png +0 -0
  69. package/public/img/installation/pinecone/pinecone-index.png +0 -0
  70. package/public/js/main.min.js +0 -10427
  71. package/public/js/main.min.js.map +0 -1
  72. package/smoke-test/SMOKE-TEST.md +0 -560
  73. package/smoke-test/smoke-test-mcp.md +0 -23
package/build/init.js CHANGED
@@ -33,9 +33,16 @@ export function buildBridgeApiEntry(cwd) {
33
33
  // where 0.2.6 persisted despite an upgrade). Pinning keeps the running
34
34
  // configuration predictable and visible in version control. The `install-bridge`
35
35
  // config write reuses this same entry so both install paths agree.
36
+ //
37
+ // `--prefer-offline` makes npx resolve the (immutable, exact-pinned) version
38
+ // from the local npm cache and skip the redundant registry-metadata round-trip
39
+ // on every boot, only hitting the network on a genuine cache miss (unlike
40
+ // `--offline`, it falls back automatically). It cannot resurrect a stale build
41
+ // — the BAPI-429 hazard above was specific to UNPINNED specs; here the exact
42
+ // `@${VERSION}` is immutable, so a cache hit is always the right build.
36
43
  return {
37
44
  command: "npx",
38
- args: ["-y", `@bridge_gpt/mcp-server@${VERSION}`],
45
+ args: ["-y", "--prefer-offline", `@bridge_gpt/mcp-server@${VERSION}`],
39
46
  env: {
40
47
  BAPI_BASE_URL: "https://bridgegpt-api.com",
41
48
  BAPI_REPO_NAME: "YOUR_REPO_NAME",
@@ -143,6 +150,32 @@ async function ensureGitignored(cwd, filePath) {
143
150
  mkdir: (p, options) => mkdir(p, options),
144
151
  });
145
152
  }
153
+ /**
154
+ * Read-compare-write a single scaffold file. Returns "skipped" when the target
155
+ * already holds identical bytes (no write), "overwritten" when it existed with
156
+ * different bytes, and "written" when it was absent. Optionally ensures `mkdirDir`
157
+ * exists first (used by the DOCS phase, whose targets span different subdirs).
158
+ *
159
+ * Extracted so the COMMANDS/DOCS/AGENTS phases can run their per-file work
160
+ * concurrently via Promise.all instead of one-await-at-a-time: on a slow disk the
161
+ * sequential syscalls dominated `runInit`. The caller applies each outcome to its
162
+ * summary Sets AFTER the batch, iterating the ordered results, so behavior and
163
+ * console output are byte-for-byte identical to the sequential version.
164
+ */
165
+ async function scaffoldFile(target, content, mkdirDir) {
166
+ if (mkdirDir !== undefined)
167
+ await mkdir(mkdirDir, { recursive: true });
168
+ let existed = false;
169
+ try {
170
+ const existing = await readFile(target, "utf-8");
171
+ if (existing === content)
172
+ return "skipped";
173
+ existed = true;
174
+ }
175
+ catch { /* file doesn't exist */ }
176
+ await writeFile(target, content, "utf-8");
177
+ return existed ? "overwritten" : "written";
178
+ }
146
179
  /**
147
180
  * Core initialization logic shared by --init and --upgrade.
148
181
  * Runs all scaffolding phases without calling process.exit().
@@ -272,22 +305,22 @@ export async function runInit(cwd) {
272
305
  const writtenFiles = new Set();
273
306
  const skippedFiles = new Set();
274
307
  const overwrittenFiles = new Set();
308
+ const commandEntries = Object.entries(COMMANDS);
275
309
  for (const dir of commandDirs) {
276
310
  await mkdir(dir, { recursive: true });
277
- for (const [filename, content] of Object.entries(COMMANDS)) {
278
- const target = path.join(dir, filename);
279
- try {
280
- const existing = await readFile(target, "utf-8");
281
- if (existing === content) {
282
- skippedFiles.add(filename);
283
- continue;
284
- }
285
- overwrittenFiles.add(filename);
311
+ // Per-file read/compare/write runs concurrently; outcomes are applied to the
312
+ // Sets afterward in entry order so the summary counts are unchanged.
313
+ const outcomes = await Promise.all(commandEntries.map(([filename, content]) => scaffoldFile(path.join(dir, filename), content)));
314
+ commandEntries.forEach(([filename], i) => {
315
+ const outcome = outcomes[i];
316
+ if (outcome === "skipped") {
317
+ skippedFiles.add(filename);
318
+ return;
286
319
  }
287
- catch { /* file doesn't exist */ }
288
- await writeFile(target, content, "utf-8");
320
+ if (outcome === "overwritten")
321
+ overwrittenFiles.add(filename);
289
322
  writtenFiles.add(filename);
290
- }
323
+ });
291
324
  }
292
325
  // A file written in any directory takes priority over skipped
293
326
  for (const f of writtenFiles)
@@ -303,25 +336,30 @@ export async function runInit(cwd) {
303
336
  console.log(` Skipped (unchanged): ${skippedFiles.size}`);
304
337
  console.log(` ${dirNames}`);
305
338
  // ---- Phase 4b: Scaffold shipped documentation assets ----
306
- // The capability catalog (docs/mcp-tool-integrations.md) the /install-bridge
307
- // capability report cites for each gate's human "why". Keyed by target path
308
- // RELATIVE to the consumer project root; content is never secret.
339
+ // Every doc asset the /install-bridge capability report points a human at,
340
+ // so no pointer it prints dangles inside an installed project: the
341
+ // capability catalog (docs/mcp-tool-integrations.md) that explains each
342
+ // gate's human "why", and the SFCC integration guide
343
+ // (docs/install/sfcc-integration.md) that the report's SFCC configure_in
344
+ // pointer names by path. Keyed by target path RELATIVE to the consumer
345
+ // project root; content is never secret.
309
346
  const docsWritten = new Set();
310
347
  const docsSkipped = new Set();
311
- for (const [relTarget, content] of Object.entries(DOCS)) {
348
+ const docEntries = Object.entries(DOCS);
349
+ // Each doc target may live in a different subdir, so mkdir(dirname) happens
350
+ // per-file inside scaffoldFile. Outcomes applied in entry order below preserve
351
+ // the insertion order of the joined summary list.
352
+ const docOutcomes = await Promise.all(docEntries.map(([relTarget, content]) => {
312
353
  const target = path.join(cwd, relTarget);
313
- await mkdir(path.dirname(target), { recursive: true });
314
- try {
315
- const existing = await readFile(target, "utf-8");
316
- if (existing === content) {
317
- docsSkipped.add(relTarget);
318
- continue;
319
- }
320
- }
321
- catch { /* file doesn't exist */ }
322
- await writeFile(target, content, "utf-8");
323
- docsWritten.add(relTarget);
324
- }
354
+ return scaffoldFile(target, content, path.dirname(target));
355
+ }));
356
+ docEntries.forEach(([relTarget], i) => {
357
+ // DOCS tracks only written vs skipped; an overwrite counts as written.
358
+ if (docOutcomes[i] === "skipped")
359
+ docsSkipped.add(relTarget);
360
+ else
361
+ docsWritten.add(relTarget);
362
+ });
325
363
  const docsTotal = Object.keys(DOCS).length;
326
364
  if (docsTotal > 0) {
327
365
  console.log(`\nDocumentation: scaffolded ${docsTotal} doc asset${docsTotal === 1 ? "" : "s"}`);
@@ -337,42 +375,32 @@ export async function runInit(cwd) {
337
375
  // Always scaffold to .claude/agents/
338
376
  const claudeAgentsDir = path.join(cwd, ".claude", "agents");
339
377
  await mkdir(claudeAgentsDir, { recursive: true });
340
- for (const [key, agent] of Object.entries(AGENTS)) {
341
- const filename = `${key}.md`;
342
- const content = reconstructAgentMarkdown(agent.frontmatter, agent.body);
343
- const target = path.join(claudeAgentsDir, filename);
344
- try {
345
- const existing = await readFile(target, "utf-8");
346
- if (existing === content) {
378
+ const agentEntries = Object.entries(AGENTS);
379
+ // Apply a batch of ordered outcomes to the agent Sets (same branches as the
380
+ // original per-file loop: skipped → skipped; overwritten → overwritten+written;
381
+ // written written).
382
+ const applyAgentOutcomes = (filenames, outcomes) => {
383
+ filenames.forEach((filename, i) => {
384
+ const outcome = outcomes[i];
385
+ if (outcome === "skipped") {
347
386
  agentSkipped.add(filename);
348
- continue;
387
+ return;
349
388
  }
350
- agentOverwritten.add(filename);
351
- }
352
- catch { /* file doesn't exist */ }
353
- await writeFile(target, content, "utf-8");
354
- agentWritten.add(filename);
355
- }
389
+ if (outcome === "overwritten")
390
+ agentOverwritten.add(filename);
391
+ agentWritten.add(filename);
392
+ });
393
+ };
394
+ const claudeAgentFilenames = agentEntries.map(([key]) => `${key}.md`);
395
+ const claudeAgentOutcomes = await Promise.all(agentEntries.map(([key, agent]) => scaffoldFile(path.join(claudeAgentsDir, `${key}.md`), reconstructAgentMarkdown(agent.frontmatter, agent.body))));
396
+ applyAgentOutcomes(claudeAgentFilenames, claudeAgentOutcomes);
356
397
  // Scaffold to .github/agents/ for VS Code / Copilot
357
398
  if (ideDetection.vscode) {
358
399
  const copilotAgentsDir = path.join(cwd, ".github", "agents");
359
400
  await mkdir(copilotAgentsDir, { recursive: true });
360
- for (const [key, agent] of Object.entries(AGENTS)) {
361
- const filename = `${key}.agent.md`;
362
- const content = translateAgentToCopilot(agent.frontmatter, agent.body);
363
- const target = path.join(copilotAgentsDir, filename);
364
- try {
365
- const existing = await readFile(target, "utf-8");
366
- if (existing === content) {
367
- agentSkipped.add(filename);
368
- continue;
369
- }
370
- agentOverwritten.add(filename);
371
- }
372
- catch { /* file doesn't exist */ }
373
- await writeFile(target, content, "utf-8");
374
- agentWritten.add(filename);
375
- }
401
+ const copilotAgentFilenames = agentEntries.map(([key]) => `${key}.agent.md`);
402
+ const copilotAgentOutcomes = await Promise.all(agentEntries.map(([key, agent]) => scaffoldFile(path.join(copilotAgentsDir, `${key}.agent.md`), translateAgentToCopilot(agent.frontmatter, agent.body))));
403
+ applyAgentOutcomes(copilotAgentFilenames, copilotAgentOutcomes);
376
404
  }
377
405
  // TODO: Add Cursor agent scaffolding when Cursor publishes a formal agent spec
378
406
  // A file written in any directory takes priority over skipped