@bridge_gpt/mcp-server 0.2.26 → 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.
- package/build/commands.generated.js +1 -1
- package/build/conductor-bin.js +68 -9267
- package/build/conductor-claude-hook-bin.js +2 -172
- package/build/decision-page-template.js +2 -31
- package/build/index.js +4652 -37042
- package/build/init.js +80 -56
- package/build/install-bridge.js +36 -20
- package/build/version.generated.js +1 -1
- package/package.json +1 -3
- package/design-assets/favicon/android-chrome-192x192.png +0 -0
- package/design-assets/favicon/android-chrome-512x512.png +0 -0
- package/design-assets/favicon/apple-touch-icon.png +0 -0
- package/design-assets/favicon/favicon-16x16.png +0 -0
- package/design-assets/favicon/favicon.ico +0 -0
- package/design-assets/favicon/site.webmanifest +0 -1
- package/public/css/main.min.css +0 -4971
- package/public/css/main.min.css.map +0 -1
- package/public/fonts/OFL.txt +0 -93
- package/public/fonts/SourceSansPro-Black.ttf +0 -0
- package/public/fonts/SourceSansPro-BlackItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-Bold.ttf +0 -0
- package/public/fonts/SourceSansPro-BoldItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-ExtraLight.ttf +0 -0
- package/public/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-Italic.ttf +0 -0
- package/public/fonts/SourceSansPro-Light.ttf +0 -0
- package/public/fonts/SourceSansPro-LightItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-Regular.ttf +0 -0
- package/public/fonts/SourceSansPro-SemiBold.ttf +0 -0
- package/public/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
- package/public/img/bridge-logo-160x51.webp +0 -0
- package/public/img/bridge-logo-300x92.webp +0 -0
- package/public/img/favicon/android-chrome-192x192.png +0 -0
- package/public/img/favicon/android-chrome-512x512.png +0 -0
- package/public/img/favicon/apple-touch-icon.png +0 -0
- package/public/img/favicon/favicon-16x16.png +0 -0
- package/public/img/favicon/favicon-32x32.png +0 -0
- package/public/img/favicon/favicon.ico +0 -0
- package/public/img/favicon/site.webmanifest +0 -1
- package/public/img/installation/bitbucket/app-password-1.png +0 -0
- package/public/img/installation/bitbucket/app-password-2.png +0 -0
- package/public/img/installation/bitbucket/create-token-1.png +0 -0
- package/public/img/installation/bitbucket/create-token-2.png +0 -0
- package/public/img/installation/bitbucket/webhook-1.png +0 -0
- package/public/img/installation/github/github-review-webhook.png +0 -0
- package/public/img/installation/jira/credentials/api-key.png +0 -0
- package/public/img/installation/jira/webhook/create-rule.png +0 -0
- package/public/img/installation/jira/webhook/project-settings.png +0 -0
- package/public/img/installation/jira/webhook/rule-create-1.png +0 -0
- package/public/img/installation/jira/webhook/rule-create-2.png +0 -0
- package/public/img/installation/jira/webhook/rule-create-3.png +0 -0
- package/public/img/installation/pinecone/pinecone-api-key.png +0 -0
- package/public/img/installation/pinecone/pinecone-index.png +0 -0
- package/public/js/main.min.js +0 -10409
- package/public/js/main.min.js.map +0 -1
- package/smoke-test/SMOKE-TEST.md +0 -560
- 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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
|
|
288
|
-
|
|
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)
|
|
@@ -312,20 +345,21 @@ export async function runInit(cwd) {
|
|
|
312
345
|
// project root; content is never secret.
|
|
313
346
|
const docsWritten = new Set();
|
|
314
347
|
const docsSkipped = new Set();
|
|
315
|
-
|
|
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]) => {
|
|
316
353
|
const target = path.join(cwd, relTarget);
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
await writeFile(target, content, "utf-8");
|
|
327
|
-
docsWritten.add(relTarget);
|
|
328
|
-
}
|
|
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
|
+
});
|
|
329
363
|
const docsTotal = Object.keys(DOCS).length;
|
|
330
364
|
if (docsTotal > 0) {
|
|
331
365
|
console.log(`\nDocumentation: scaffolded ${docsTotal} doc asset${docsTotal === 1 ? "" : "s"}`);
|
|
@@ -341,42 +375,32 @@ export async function runInit(cwd) {
|
|
|
341
375
|
// Always scaffold to .claude/agents/
|
|
342
376
|
const claudeAgentsDir = path.join(cwd, ".claude", "agents");
|
|
343
377
|
await mkdir(claudeAgentsDir, { recursive: true });
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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") {
|
|
351
386
|
agentSkipped.add(filename);
|
|
352
|
-
|
|
387
|
+
return;
|
|
353
388
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
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);
|
|
360
397
|
// Scaffold to .github/agents/ for VS Code / Copilot
|
|
361
398
|
if (ideDetection.vscode) {
|
|
362
399
|
const copilotAgentsDir = path.join(cwd, ".github", "agents");
|
|
363
400
|
await mkdir(copilotAgentsDir, { recursive: true });
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const target = path.join(copilotAgentsDir, filename);
|
|
368
|
-
try {
|
|
369
|
-
const existing = await readFile(target, "utf-8");
|
|
370
|
-
if (existing === content) {
|
|
371
|
-
agentSkipped.add(filename);
|
|
372
|
-
continue;
|
|
373
|
-
}
|
|
374
|
-
agentOverwritten.add(filename);
|
|
375
|
-
}
|
|
376
|
-
catch { /* file doesn't exist */ }
|
|
377
|
-
await writeFile(target, content, "utf-8");
|
|
378
|
-
agentWritten.add(filename);
|
|
379
|
-
}
|
|
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);
|
|
380
404
|
}
|
|
381
405
|
// TODO: Add Cursor agent scaffolding when Cursor publishes a formal agent spec
|
|
382
406
|
// A file written in any directory takes priority over skipped
|
package/build/install-bridge.js
CHANGED
|
@@ -113,7 +113,11 @@ export const MCP_TIMEOUT_GUIDANCE = "Note: if your MCP client has a very short c
|
|
|
113
113
|
"(the initial npx package resolution/download can exceed a short connect timeout).";
|
|
114
114
|
/** The exact, version-pinned launcher spec the pre-warm spawns (fast-exiting --version). */
|
|
115
115
|
export function buildPrewarmArgs() {
|
|
116
|
-
|
|
116
|
+
// `--prefer-offline`: the initial `@latest` bootstrap already populated the npm
|
|
117
|
+
// cache with the exact tarball this `@${VERSION}`-pinned warm needs, so resolve
|
|
118
|
+
// from cache and skip the redundant registry-metadata round-trip (falls back to
|
|
119
|
+
// the network on a genuine miss).
|
|
120
|
+
return ["-y", "--prefer-offline", `@bridge_gpt/mcp-server@${VERSION}`, "--version"];
|
|
117
121
|
}
|
|
118
122
|
/** Secret-free preview of the pre-warm command (no env, no key). */
|
|
119
123
|
export function buildPrewarmCommandPreview() {
|
|
@@ -1942,6 +1946,21 @@ export async function runInstallBridgeCli(argv, overrides = {}) {
|
|
|
1942
1946
|
"Check that the system temporary directory is writable so the launch script can be used.");
|
|
1943
1947
|
return 1;
|
|
1944
1948
|
}
|
|
1949
|
+
// ---- Step 3b (kickoff) — pre-warm the @${VERSION}-pinned _npx bucket ----
|
|
1950
|
+
// The @${VERSION}-pinned launcher written below lives in a DIFFERENT _npx bucket
|
|
1951
|
+
// than the @latest bucket this `npx … install-bridge` invocation warmed, so the
|
|
1952
|
+
// first real MCP launch would otherwise pay a cold install inline (which can
|
|
1953
|
+
// exceed the client's connect deadline). Nothing before the Step 5 terminal spawn
|
|
1954
|
+
// depends on the warmed bucket — only the spawned session's first MCP launch does
|
|
1955
|
+
// — so START the warm HERE (fire-and-forget) and AWAIT it just before that spawn.
|
|
1956
|
+
// Its multi-second `npx` resolve then overlaps the network round-trips (ping /
|
|
1957
|
+
// exchange), the scaffold, and the config/credential writes instead of adding to
|
|
1958
|
+
// them serially. Strictly fail-open: the default impl always RESOLVES (never
|
|
1959
|
+
// rejects), so a later abort-return that skips the await leaves no unhandled
|
|
1960
|
+
// rejection. Positioned AFTER the launch-command guards above so an aborted run
|
|
1961
|
+
// that never reaches an install side effect also never spawns the pre-warm.
|
|
1962
|
+
log(" pre-warming the version-pinned launcher bucket (in the background)…");
|
|
1963
|
+
const prewarmPromise = deps.spawnPrewarm("npx", buildPrewarmArgs(), deps.env);
|
|
1945
1964
|
const credentialWriteDeps = {
|
|
1946
1965
|
env: deps.env,
|
|
1947
1966
|
homedir: deps.homedir,
|
|
@@ -2238,25 +2257,6 @@ export async function runInstallBridgeCli(argv, overrides = {}) {
|
|
|
2238
2257
|
// ensureGitignored for the state file can still throw — also advisory.
|
|
2239
2258
|
errorLog("Warning: could not persist the install-state file (non-fatal).");
|
|
2240
2259
|
}
|
|
2241
|
-
// ---- Step 3b — pre-warm the @${VERSION}-pinned _npx bucket (BAPI-451 W3) ----
|
|
2242
|
-
// The launcher just written is pinned to @${VERSION}, a DIFFERENT _npx bucket
|
|
2243
|
-
// than the @latest bucket this `npx … install-bridge` invocation warmed. Spawn
|
|
2244
|
-
// the exact pinned launcher once with the fast-exiting `--version` flag so the
|
|
2245
|
-
// first real MCP launch resolves from a warm bucket instead of paying the cold
|
|
2246
|
-
// install inline (which can exceed the client's connect deadline). Strictly
|
|
2247
|
-
// fail-open: a failure warns (secret-free) but never fails the install.
|
|
2248
|
-
log(" pre-warming the version-pinned launcher bucket…");
|
|
2249
|
-
const prewarm = await deps.spawnPrewarm("npx", buildPrewarmArgs(), deps.env);
|
|
2250
|
-
if (prewarm.ok) {
|
|
2251
|
-
log(" launcher bucket warmed (the first MCP launch will not pay a cold install).");
|
|
2252
|
-
log(` ${MCP_TIMEOUT_GUIDANCE}`);
|
|
2253
|
-
}
|
|
2254
|
-
else {
|
|
2255
|
-
// Escalate to a stronger, still secret-free warning when pre-warm didn't
|
|
2256
|
-
// complete cleanly — but the install itself still succeeds (exit unaffected).
|
|
2257
|
-
errorLog(`Warning: could not pre-warm the version-pinned launcher bucket${prewarm.warning ? ` (${prewarm.warning})` : ""}. ` +
|
|
2258
|
-
`The first MCP launch may pay a one-time cold install and could be slow. ${MCP_TIMEOUT_GUIDANCE}`);
|
|
2259
|
-
}
|
|
2260
2260
|
// ---- Step 4 — persist the credential ----
|
|
2261
2261
|
if (bootstrapInviteMode) {
|
|
2262
2262
|
// FAIL-CLOSED (unlike normal mode below). The pending secret IS the minted admin
|
|
@@ -2306,6 +2306,22 @@ export async function runInstallBridgeCli(argv, overrides = {}) {
|
|
|
2306
2306
|
// observe GitHub as configured if the user connects it here, and running it after the
|
|
2307
2307
|
// spawn would put two prompts on the same terminal at once.
|
|
2308
2308
|
await offerGithubConnection(repoName, deps, log);
|
|
2309
|
+
// ---- Step 3b (await) — settle the background pre-warm before the session opens ----
|
|
2310
|
+
// The warm was kicked off right after the launch-command guards (above); await it
|
|
2311
|
+
// HERE so the bucket is settled before the spawned session's first MCP launch, but
|
|
2312
|
+
// AFTER all the work it overlapped with. Strictly fail-open — the exit code is
|
|
2313
|
+
// never affected, mirroring the original inline Step 3b behavior.
|
|
2314
|
+
const prewarm = await prewarmPromise;
|
|
2315
|
+
if (prewarm.ok) {
|
|
2316
|
+
log(" launcher bucket warmed (the first MCP launch will not pay a cold install).");
|
|
2317
|
+
log(` ${MCP_TIMEOUT_GUIDANCE}`);
|
|
2318
|
+
}
|
|
2319
|
+
else {
|
|
2320
|
+
// Escalate to a stronger, still secret-free warning when pre-warm didn't
|
|
2321
|
+
// complete cleanly — but the install itself still succeeds (exit unaffected).
|
|
2322
|
+
errorLog(`Warning: could not pre-warm the version-pinned launcher bucket${prewarm.warning ? ` (${prewarm.warning})` : ""}. ` +
|
|
2323
|
+
`The first MCP launch may pay a one-time cold install and could be slow. ${MCP_TIMEOUT_GUIDANCE}`);
|
|
2324
|
+
}
|
|
2309
2325
|
// ---- Step 5 — spawn a fresh agent session for the agentic remainder ----
|
|
2310
2326
|
log(`Step 5/5 — opening a ${agent.name} session for /install-bridge configuration + capability report…`);
|
|
2311
2327
|
const terminal = detectTerminal(undefined, deps.env);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
|
|
2
|
-
export const VERSION = "0.2.
|
|
2
|
+
export const VERSION = "0.2.27";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bridge_gpt/mcp-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.27",
|
|
4
4
|
"description": "Bridge API MCP server — exposes Jira endpoints as MCP tools for Claude Code agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,9 +15,7 @@
|
|
|
15
15
|
"!build/**/*.test.js",
|
|
16
16
|
"!build/integration/**",
|
|
17
17
|
"pipelines/",
|
|
18
|
-
"smoke-test/",
|
|
19
18
|
"design-assets/",
|
|
20
|
-
"public/",
|
|
21
19
|
"README.md",
|
|
22
20
|
"docs/",
|
|
23
21
|
"LICENSE"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|