@bridge_gpt/mcp-server 0.2.3 → 0.2.6

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.
@@ -503,6 +503,12 @@ export async function buildProductionEpicRuntimeDeps(epicKey) {
503
503
  throw new Error(`dispatchSeam called before fetchPlan for epic ${ek} ticket ${tk}; cachedPlanVersion is 0`);
504
504
  }
505
505
  const kind = automationMap.get(tk) ?? "start-tickets";
506
+ // Operator dry-run: when BAPI_CONDUCTOR_DISPATCH_DRY_RUN=1, dispatch resolves
507
+ // the spawn command + model routing but opens NO terminal, creates NO worktree,
508
+ // and opens NO PR (start-tickets/review-tickets dryRun). The full loop dispatch
509
+ // path (ready-set → claim key → dispatch → correlate run_id) still exercises;
510
+ // dry-run rows carry no runId, so a synthetic one is substituted for correlation.
511
+ const dispatchDryRun = process.env.BAPI_CONDUCTOR_DISPATCH_DRY_RUN === "1";
506
512
  const identity = {
507
513
  epic_key: ek,
508
514
  epic_run_id: ek,
@@ -516,7 +522,7 @@ export async function buildProductionEpicRuntimeDeps(epicKey) {
516
522
  keys: [tk],
517
523
  epic: identity,
518
524
  agentName: "claude",
519
- dryRun: false,
525
+ dryRun: dispatchDryRun,
520
526
  maxParallel: 1,
521
527
  auto: true,
522
528
  reviewOverrides: {},
@@ -531,7 +537,7 @@ export async function buildProductionEpicRuntimeDeps(epicKey) {
531
537
  keys: [tk],
532
538
  epic: identity,
533
539
  agentName: "claude",
534
- dryRun: false,
540
+ dryRun: dispatchDryRun,
535
541
  autoApprove: true,
536
542
  maxParallel: 1,
537
543
  refreshMain: false,
@@ -543,6 +549,11 @@ export async function buildProductionEpicRuntimeDeps(epicKey) {
543
549
  }
544
550
  runId = result.rows[0]?.runId;
545
551
  }
552
+ if (!runId && dispatchDryRun) {
553
+ // Dry-run dispatch produced no real run_id; substitute a synthetic id so the
554
+ // idempotent correlate step still runs and the dispatch row is observable.
555
+ runId = `dry-run:${identity.dispatch_key}`;
556
+ }
546
557
  if (!runId) {
547
558
  throw new Error(`dispatch returned no runId for ticket ${tk}`);
548
559
  }
package/build/index.js CHANGED
@@ -526,6 +526,78 @@ async function resolveTextOrFile(textValue, filePath, textLabel) {
526
526
  }
527
527
  return { ok: true, text: resolvedText, note };
528
528
  }
529
+ const BINARY_EXTENSIONS = new Set([
530
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".heic", ".heif",
531
+ ".bmp", ".tiff", ".pdf", ".zip", ".docx", ".xlsx", ".pptx",
532
+ ]);
533
+ async function resolveUploadAttachment(textValue, filePath, textLabel) {
534
+ if (!filePath && !textValue) {
535
+ return {
536
+ ok: false,
537
+ errorResponse: {
538
+ content: [{
539
+ type: "text",
540
+ text: JSON.stringify({ error: "BAD_REQUEST", status: 400, message: `Either ${textLabel} or file_path must be provided.` }),
541
+ }],
542
+ },
543
+ };
544
+ }
545
+ if (!filePath) {
546
+ return { ok: true, text: textValue, encoding: undefined, note: "" };
547
+ }
548
+ try {
549
+ const fileStat = await stat(filePath);
550
+ if (fileStat.size > 10 * 1024 * 1024) { // mirrors MAX_ATTACHMENT_SIZE in api/library/jira/jira_lib.py
551
+ return {
552
+ ok: false,
553
+ errorResponse: {
554
+ content: [{
555
+ type: "text",
556
+ text: JSON.stringify({ error: "BAD_REQUEST", status: 400, message: `File at ${filePath} exceeds 10MB size limit.` }),
557
+ }],
558
+ },
559
+ };
560
+ }
561
+ const ext = path.extname(filePath).toLowerCase();
562
+ const buf = await readFile(filePath);
563
+ let isBinary = BINARY_EXTENSIONS.has(ext);
564
+ if (!isBinary) {
565
+ try {
566
+ new TextDecoder("utf-8", { fatal: true }).decode(buf);
567
+ }
568
+ catch {
569
+ isBinary = true;
570
+ }
571
+ }
572
+ const note = textValue ? `\n\nNote: Both file_path and ${textLabel} were provided. file_path content was used.` : "";
573
+ if (isBinary) {
574
+ return { ok: true, text: buf.toString("base64"), encoding: "base64", note };
575
+ }
576
+ if (buf.length > 1_048_576) {
577
+ return {
578
+ ok: false,
579
+ errorResponse: {
580
+ content: [{
581
+ type: "text",
582
+ text: JSON.stringify({ error: "BAD_REQUEST", status: 400, message: `Text file at ${filePath} exceeds 1MB size limit.` }),
583
+ }],
584
+ },
585
+ };
586
+ }
587
+ return { ok: true, text: buf.toString("utf8"), encoding: undefined, note };
588
+ }
589
+ catch (err) {
590
+ return {
591
+ ok: false,
592
+ errorResponse: {
593
+ content: [{
594
+ type: "text",
595
+ text: JSON.stringify({ error: "BAD_REQUEST", status: 400, message: `Error reading file at ${filePath}: ${err instanceof Error ? err.message : String(err)}` }),
596
+ }],
597
+ },
598
+ };
599
+ }
600
+ }
529
601
  async function pollForResult(getUrl, timeoutMs, label) {
530
602
  const startTime = Date.now();
531
603
  let pollIntervalMs = 15_000;
@@ -575,7 +647,7 @@ const TICKET_ARTIFACTS = {
575
647
  requestErrorPrefix: "Failed to request architecture generation: ",
576
648
  confirmationText: (n) => `Architecture generation requested for ${n}. ` +
577
649
  `Processing typically takes 2-4 minutes. ` +
578
- `Use get_architecture with ticket_number "${n}" to retrieve the architecture plan once processing completes.`,
650
+ `Use get_architecture with ticket_number "${n}" (or get_doc with doc_type "tdd") to retrieve the architecture plan once processing completes.`,
579
651
  pollLabel: (n) => `Architecture generation for ${n}`,
580
652
  },
581
653
  fsd: {
@@ -599,7 +671,7 @@ const TICKET_ARTIFACTS = {
599
671
  requestErrorPrefix: "Failed to request PRD generation: ",
600
672
  confirmationText: (n) => `PRD generation requested for ${n}. ` +
601
673
  `Processing typically takes 2-4 minutes. ` +
602
- `Use get_prd with ticket_number "${n}" to retrieve the PRD once processing completes.`,
674
+ `Use get_prd with ticket_number "${n}" (or get_doc with doc_type "prd") to retrieve the PRD once processing completes.`,
603
675
  pollLabel: (n) => `PRD generation for ${n}`,
604
676
  },
605
677
  clarifying_questions: {
@@ -2350,11 +2422,14 @@ registerTool("upload_attachment", {
2350
2422
  openWorldHint: true,
2351
2423
  },
2352
2424
  description: "Upload a local file as an attachment to a Jira ticket. " +
2353
- "Supports text/UTF-8 files only (markdown, plain text, etc.). " +
2354
- "Optionally syncs the content to Bridge API's tickets_links table so retrieval endpoints " +
2425
+ "Supports binary files up to `10 MB` and text files up to `1 MB`. " +
2426
+ "Binary files are auto-detected (extension list or UTF-8 probe) and sent as base64. " +
2427
+ "Optionally syncs text content to Bridge API's tickets_links table so retrieval endpoints " +
2355
2428
  "(get_clarifying_questions, get_ticket_critique, get_plan) return the updated content without re-generation. " +
2356
2429
  "Use link_type to specify which retrieval endpoint should serve this content. " +
2357
- "Known link_type values: clarifying-questions.md, debugging-guidance.md, ticket-quality-critique.md, architecture-plan.md, fsd-plan.md, prd-plan.md.",
2430
+ "Known link_type values: clarifying-questions.md, debugging-guidance.md, ticket-quality-critique.md, architecture-plan.md, fsd-plan.md, prd-plan.md. " +
2431
+ "Note: link_type is text-only; cannot be used with base64 uploads. " +
2432
+ "⚠️ SECURITY: Binary bytes cannot be secret-redacted by automated text scrubbers; review sensitive visual content before upload.",
2358
2433
  inputSchema: {
2359
2434
  ticket_number: z
2360
2435
  .string()
@@ -2363,13 +2438,13 @@ registerTool("upload_attachment", {
2363
2438
  .string()
2364
2439
  .optional()
2365
2440
  .describe("Path to a local file to upload as an attachment. " +
2366
- "The file must be UTF-8 encoded and under 1MB. " +
2441
+ "Binary files (images, PDFs, etc.) are supported up to `10 MB`; text files up to `1 MB`. " +
2367
2442
  "If both file_path and content are provided, file_path takes precedence."),
2368
2443
  content: z
2369
2444
  .string()
2370
2445
  .max(1_048_576)
2371
2446
  .optional()
2372
- .describe("Inline text content to upload (max 1MB). Optional if file_path is provided."),
2447
+ .describe("Inline text content to upload (max `1 MB`). Optional if file_path is provided."),
2373
2448
  file_name: z
2374
2449
  .string()
2375
2450
  .optional()
@@ -2380,7 +2455,8 @@ registerTool("upload_attachment", {
2380
2455
  .optional()
2381
2456
  .describe("When provided, also syncs the content to Bridge API's tickets_links table. " +
2382
2457
  "Known values: clarifying-questions.md, debugging-guidance.md, ticket-quality-critique.md, architecture-plan.md, fsd-plan.md, prd-plan.md. " +
2383
- "Unknown values are accepted with a warning."),
2458
+ "Unknown values are accepted with a warning. " +
2459
+ "Cannot be used with binary file uploads."),
2384
2460
  replace_existing: z
2385
2461
  .boolean()
2386
2462
  .optional()
@@ -2389,7 +2465,7 @@ registerTool("upload_attachment", {
2389
2465
  "Set to false to allow duplicate filenames."),
2390
2466
  },
2391
2467
  }, async ({ ticket_number, file_path, content, file_name, link_type, replace_existing }) => {
2392
- const resolved = await resolveTextOrFile(content, file_path, "content");
2468
+ const resolved = await resolveUploadAttachment(content, file_path, "content");
2393
2469
  if (!resolved.ok)
2394
2470
  return resolved.errorResponse;
2395
2471
  const derivedFileName = file_name
@@ -2400,6 +2476,9 @@ registerTool("upload_attachment", {
2400
2476
  file_name: derivedFileName,
2401
2477
  replace_existing,
2402
2478
  };
2479
+ if (resolved.encoding) {
2480
+ payload.encoding = resolved.encoding;
2481
+ }
2403
2482
  if (link_type) {
2404
2483
  payload.link_type = link_type;
2405
2484
  }
@@ -1,2 +1,2 @@
1
1
  // AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
2
- export const VERSION = "0.2.3";
2
+ export const VERSION = "0.2.6";
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@bridge_gpt/mcp-server",
3
- "version": "0.2.3",
3
+ "version": "0.2.6",
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",
7
7
  "bin": {
8
+ "mcp-server": "./build/index.js",
8
9
  "bridge-api-mcp-server": "./build/index.js",
9
10
  "conductor": "./build/conductor-bin.js",
10
11
  "conductor-claude-hook": "./build/conductor-claude-hook-bin.js"
@@ -25,7 +26,7 @@
25
26
  "check:version-generated": "node scripts/bundle-version.js && node scripts/check-version-generated.js",
26
27
  "postbuild": "node scripts/prepend-shebang.cjs",
27
28
  "start": "node build/index.js",
28
- "test": "node --test build/pipeline-utils.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/doctor.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/doctor.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-judgment.test.js build/conductor/supervisor-judgment-python-adapter.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/merge-ledger.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js && node --experimental-test-module-mocks --test build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/cli-git-hooks.test.js",
29
+ "test": "node --test build/pipeline-utils.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/doctor.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/doctor.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-judgment.test.js build/conductor/supervisor-judgment-python-adapter.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/merge-ledger.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js && node --experimental-test-module-mocks --test build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/cli-git-hooks.test.js",
29
30
  "test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/doctor.integration.test.js build/integration/agent-capabilities.integration.test.js build/integration/conductor-producer.integration.test.js build/integration/conductor-message-relay.integration.test.js",
30
31
  "prepublishOnly": "node scripts/bundle-assets.js && npm run build && node scripts/verify-shebang.cjs"
31
32
  },
@@ -489,7 +489,7 @@ and raw protocol noise.** Sensitive values are redacted.
489
489
 
490
490
  ---
491
491
 
492
- ## Full 56-Tool Smoke Tier Matrix
492
+ ## Full 62-Tool Smoke Tier Matrix
493
493
 
494
494
  Every registered MCP tool appears **exactly once** below with its smoke tier.
495
495
  Tier 4 (mutating/hazardous) tools are **deferred in v1**.