@bridge_gpt/mcp-server 0.2.56 → 0.2.57
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/README.md +19 -5
- package/build/codex-bridge-profile.js +151 -0
- package/build/codex-home.js +7 -0
- package/build/codex-launch-scope.js +12 -7
- package/build/doctor.js +6 -1
- package/build/epic-implementer-bin.js +3 -3
- package/build/index.js +88 -84
- package/build/install-bridge.js +47 -1
- package/build/mcp-host-config.js +4 -0
- package/build/mcp-host-targets.js +3 -0
- package/build/readme.generated.js +1 -1
- package/build/start-tickets.js +76 -17
- package/build/version.generated.js +3 -3
- package/package.json +1 -1
package/build/start-tickets.js
CHANGED
|
@@ -58,9 +58,10 @@ import { readFile, writeFile, mkdir, mkdtemp, stat, lstat, symlink, unlink, copy
|
|
|
58
58
|
import os from "node:os";
|
|
59
59
|
import { createHash } from "node:crypto";
|
|
60
60
|
import path from "path";
|
|
61
|
+
import { validateHttpBaseUrl } from "./base-url.js";
|
|
61
62
|
import { VERSION } from "./version.generated.js";
|
|
62
63
|
import { resolveBapiCredentials, getPrimaryCredentialStorePath, } from "./credential-store.js";
|
|
63
|
-
import { MCP_PACKAGE_NAME } from "./mcp-identity.js";
|
|
64
|
+
import { LEGACY_SERVER_NAMES, MCP_PACKAGE_NAME, MCP_SERVER_NAME } from "./mcp-identity.js";
|
|
64
65
|
// BAPI-941: the shared drift diagnostic formatter. The leaf drift module imports
|
|
65
66
|
// nothing from here, so this direction stays acyclic.
|
|
66
67
|
import { formatClaudeReviewWorkflowDriftDiagnostic } from "./claude-review-workflow-drift.js";
|
|
@@ -560,7 +561,7 @@ resumeMode = false, workflow = "implement", reviewRounds,
|
|
|
560
561
|
// conductor runs always, and (BAPI-801/BAPI-847) for every plain run whose base
|
|
561
562
|
// resolved, `main` included — and threaded (BAPI-593) into the spawned workflow
|
|
562
563
|
// command.
|
|
563
|
-
baseBranch) {
|
|
564
|
+
baseBranch, bridgeApiBaseUrlOverride) {
|
|
564
565
|
if (!isSupportedStartTicketsPlatform(deps.platform)) {
|
|
565
566
|
return { ok: false, error: unsupportedPlatformMessage(deps.platform) };
|
|
566
567
|
}
|
|
@@ -571,6 +572,7 @@ baseBranch) {
|
|
|
571
572
|
// conductor-only — a plain worker's prompt stays bare and learns the base from
|
|
572
573
|
// the env plus the create-PR instruction files.
|
|
573
574
|
const prBaseBranch = resolvePrBaseBranchEnvValue(conductorEnabled, baseBranch);
|
|
575
|
+
const bridgeApiBaseUrl = bridgeApiBaseUrlOverride ?? resolveSpawnBridgeApiBaseUrl(deps.env);
|
|
574
576
|
return {
|
|
575
577
|
ok: true,
|
|
576
578
|
config: {
|
|
@@ -580,7 +582,7 @@ baseBranch) {
|
|
|
580
582
|
// falls back to the basename-derived repo name (the 403 root cause), and
|
|
581
583
|
// (BAPI-586/BAPI-801) the run base so the spawned worker opens its PR
|
|
582
584
|
// against it. The base assignment stays outermost.
|
|
583
|
-
buildAgentShellCommand: (key, worktreePath, modelAlias, launchArgs) => prependBaseBranchEnvAssignment(prependRepoNameEnvAssignment(buildAgentShellCommand(agent, key, worktreePath, platform, autoApprove, modelAlias, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, launchArgs), repoName, platform), prBaseBranch, platform),
|
|
585
|
+
buildAgentShellCommand: (key, worktreePath, modelAlias, launchArgs) => prependBaseBranchEnvAssignment(prependRepoNameEnvAssignment(buildAgentShellCommand(agent, key, worktreePath, platform, autoApprove, modelAlias, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, launchArgs, bridgeApiBaseUrl), repoName, platform), prBaseBranch, platform),
|
|
584
586
|
spawnTerminalTab: deps.spawnTerminalTab,
|
|
585
587
|
},
|
|
586
588
|
};
|
|
@@ -610,6 +612,51 @@ export function prependRepoNameEnvAssignment(command, repoName, platform = "darw
|
|
|
610
612
|
}
|
|
611
613
|
return `export BAPI_REPO_NAME='${shSquoteInner(repoName)}' && ${command}`;
|
|
612
614
|
}
|
|
615
|
+
/** Carry the parent's non-secret Bridge endpoint into a newly opened terminal. */
|
|
616
|
+
export function prependBridgeApiBaseUrlEnvAssignment(command, baseUrl, platform = "darwin") {
|
|
617
|
+
if (!baseUrl)
|
|
618
|
+
return command;
|
|
619
|
+
if (platform === "win32") {
|
|
620
|
+
return `$env:BAPI_BASE_URL = ${powershellSquote(baseUrl)}; ${command}`;
|
|
621
|
+
}
|
|
622
|
+
return `export BAPI_BASE_URL='${shSquoteInner(baseUrl)}' && ${command}`;
|
|
623
|
+
}
|
|
624
|
+
/** Validate before placing an endpoint in a launch script or MCP registration. */
|
|
625
|
+
export function resolveSpawnBridgeApiBaseUrl(env) {
|
|
626
|
+
const raw = env.BAPI_BASE_URL;
|
|
627
|
+
if (!raw || !raw.trim())
|
|
628
|
+
return undefined;
|
|
629
|
+
const result = validateHttpBaseUrl(raw);
|
|
630
|
+
return result.ok ? result.baseUrl : undefined;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* A shell-spawned CLI cannot see the parent MCP process's environment. Read only
|
|
634
|
+
* the non-secret endpoint from the selected host's project registration when the
|
|
635
|
+
* shell did not inherit BAPI_BASE_URL (common for Cursor launched from the GUI).
|
|
636
|
+
*/
|
|
637
|
+
export async function resolveStartTicketsBridgeApiBaseUrl(deps, agent) {
|
|
638
|
+
const inherited = resolveSpawnBridgeApiBaseUrl(deps.env);
|
|
639
|
+
if (inherited)
|
|
640
|
+
return inherited;
|
|
641
|
+
const configPath = agent.name === "cursor-agent"
|
|
642
|
+
? path.join(deps.cwd, ".cursor", "mcp.json")
|
|
643
|
+
: path.join(deps.cwd, ".mcp.json");
|
|
644
|
+
try {
|
|
645
|
+
const raw = await (deps.readFile ?? ((filePath) => readFile(filePath, "utf-8")))(configPath);
|
|
646
|
+
const parsed = JSON.parse(raw);
|
|
647
|
+
const bridge = parsed.mcpServers?.[MCP_SERVER_NAME] ?? parsed.mcpServers?.[LEGACY_SERVER_NAMES[0]];
|
|
648
|
+
if (!bridge)
|
|
649
|
+
return undefined;
|
|
650
|
+
const args = Array.isArray(bridge.args) ? bridge.args : [];
|
|
651
|
+
const flagIndex = args.indexOf("--base-url");
|
|
652
|
+
const candidate = bridge.env?.BAPI_BASE_URL ?? (flagIndex >= 0 ? args[flagIndex + 1] : undefined);
|
|
653
|
+
const validated = validateHttpBaseUrl(candidate);
|
|
654
|
+
return validated.ok ? validated.baseUrl : undefined;
|
|
655
|
+
}
|
|
656
|
+
catch {
|
|
657
|
+
return undefined;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
613
660
|
/**
|
|
614
661
|
* BAPI-801/BAPI-847: decide the `BAPI_BASE_BRANCH` value a spawned worker's shell
|
|
615
662
|
* should carry — the single rule shared by the real spawn builder
|
|
@@ -1347,14 +1394,14 @@ export function buildAgentInvocation(agent, prompt, quote, modelAlias, launchArg
|
|
|
1347
1394
|
}
|
|
1348
1395
|
}
|
|
1349
1396
|
/** POSIX agent shell command: `cd '<path>' && <agent> [--model '<alias>'] '<prompt>'`. */
|
|
1350
|
-
export function buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false, workflow = "implement", reviewRounds, baseBranch, launchArgs = []) {
|
|
1397
|
+
export function buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false, workflow = "implement", reviewRounds, baseBranch, launchArgs = [], bridgeApiBaseUrl) {
|
|
1351
1398
|
const invocation = buildAgentInvocation(agent, buildAgentPrompt(key, { autoApprove, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, agentName: agent.name }), (p) => `'${shSquoteInner(p)}'`, modelAlias, agent.name === "cursor-agent" && autoApprove ? worktreePath : launchArgs);
|
|
1352
|
-
return `cd '${shSquoteInner(worktreePath)}' && ${invocation}`;
|
|
1399
|
+
return `cd '${shSquoteInner(worktreePath)}' && ${prependBridgeApiBaseUrlEnvAssignment(invocation, bridgeApiBaseUrl, "darwin")}`;
|
|
1353
1400
|
}
|
|
1354
1401
|
/** PowerShell agent shell command: `Set-Location -LiteralPath '<path>'; <agent> [--model '<alias>'] '<prompt>'`. */
|
|
1355
|
-
export function buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false, workflow = "implement", reviewRounds, baseBranch, launchArgs = []) {
|
|
1402
|
+
export function buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false, workflow = "implement", reviewRounds, baseBranch, launchArgs = [], bridgeApiBaseUrl) {
|
|
1356
1403
|
const invocation = buildAgentInvocation(agent, buildAgentPrompt(key, { autoApprove, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, agentName: agent.name }), powershellSquote, modelAlias, agent.name === "cursor-agent" && autoApprove ? worktreePath : launchArgs);
|
|
1357
|
-
return `Set-Location -LiteralPath ${powershellSquote(worktreePath)}; ${invocation}`;
|
|
1404
|
+
return `Set-Location -LiteralPath ${powershellSquote(worktreePath)}; ${prependBridgeApiBaseUrlEnvAssignment(invocation, bridgeApiBaseUrl, "win32")}`;
|
|
1358
1405
|
}
|
|
1359
1406
|
/**
|
|
1360
1407
|
* Build the shell command run inside each spawned tab/session, dispatched by
|
|
@@ -1364,10 +1411,10 @@ export function buildPowerShellAgentShellCommand(agent, key, worktreePath, autoA
|
|
|
1364
1411
|
* injected as `--model` at the spawn boundary. `conductorEnabled` appends the
|
|
1365
1412
|
* BAPI-586 PR-base contract instruction to the prompt (opt-in via `--conductor`).
|
|
1366
1413
|
*/
|
|
1367
|
-
export function buildAgentShellCommand(agent, key, worktreePath, platform = "darwin", autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false, workflow = "implement", reviewRounds, baseBranch, launchArgs = []) {
|
|
1414
|
+
export function buildAgentShellCommand(agent, key, worktreePath, platform = "darwin", autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false, workflow = "implement", reviewRounds, baseBranch, launchArgs = [], bridgeApiBaseUrl) {
|
|
1368
1415
|
if (platform === "win32")
|
|
1369
|
-
return buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, launchArgs);
|
|
1370
|
-
return buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, launchArgs);
|
|
1416
|
+
return buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, launchArgs, bridgeApiBaseUrl);
|
|
1417
|
+
return buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled, resumeMode, workflow, reviewRounds, baseBranch, launchArgs, bridgeApiBaseUrl);
|
|
1371
1418
|
}
|
|
1372
1419
|
/**
|
|
1373
1420
|
* Build the shell command run inside a spawned tab/session for an ARBITRARY
|
|
@@ -2008,7 +2055,7 @@ export function getDryRunPlatformDetails(agent, platform = process.platform, env
|
|
|
2008
2055
|
// buildAgentShellCommand/buildAgentPrompt path as a real spawn. A Codex
|
|
2009
2056
|
// dry-run has no created worktree to bind, so its preview omits the
|
|
2010
2057
|
// process-local -C/-c MCP scope that the real spawn resolves later.
|
|
2011
|
-
buildAgentShellCommand: (key, worktreePath, modelAlias, launchArgs) => prependBaseBranchEnvAssignment(prependRepoNameEnvAssignment(buildAgentShellCommand(agent, key, worktreePath, platform, autoApprove, modelAlias, conductorEnabled, false, workflow, reviewRounds, baseBranch, launchArgs), repoName, platform), resolvePrBaseBranchEnvValue(conductorEnabled, baseBranch), platform),
|
|
2058
|
+
buildAgentShellCommand: (key, worktreePath, modelAlias, launchArgs) => prependBaseBranchEnvAssignment(prependRepoNameEnvAssignment(buildAgentShellCommand(agent, key, worktreePath, platform, autoApprove, modelAlias, conductorEnabled, false, workflow, reviewRounds, baseBranch, launchArgs, resolveSpawnBridgeApiBaseUrl(env)), repoName, platform), resolvePrBaseBranchEnvValue(conductorEnabled, baseBranch), platform),
|
|
2012
2059
|
};
|
|
2013
2060
|
}
|
|
2014
2061
|
/**
|
|
@@ -2017,7 +2064,7 @@ export function getDryRunPlatformDetails(agent, platform = process.platform, env
|
|
|
2017
2064
|
* the `bapi` target. Lists both registration files and the version-pinned shim
|
|
2018
2065
|
* command. Pure formatting — implies no credentials and writes no files.
|
|
2019
2066
|
*/
|
|
2020
|
-
export function buildDryRunMcpProvisioningLines(worktreePath, platform = process.platform, mcpServerInvocation) {
|
|
2067
|
+
export function buildDryRunMcpProvisioningLines(worktreePath, platform = process.platform, mcpServerInvocation, bridgeApiBaseUrl) {
|
|
2021
2068
|
const api = platform === "win32" ? path.win32 : path.posix;
|
|
2022
2069
|
const mcpJson = api.join(worktreePath, ".mcp.json");
|
|
2023
2070
|
const cursorJson = api.join(worktreePath, ".cursor", "mcp.json");
|
|
@@ -2038,6 +2085,7 @@ export function buildDryRunMcpProvisioningLines(worktreePath, platform = process
|
|
|
2038
2085
|
`DRY-RUN: ${mcpJson}`,
|
|
2039
2086
|
`DRY-RUN: ${cursorJson}`,
|
|
2040
2087
|
`DRY-RUN: ${shim}`,
|
|
2088
|
+
...(bridgeApiBaseUrl ? [`DRY-RUN: bapi shim adds --base-url ${bridgeApiBaseUrl}`] : []),
|
|
2041
2089
|
];
|
|
2042
2090
|
}
|
|
2043
2091
|
/**
|
|
@@ -2062,7 +2110,7 @@ export function buildDryRunDetailLines(agent, key, branch, platform = process.pl
|
|
|
2062
2110
|
`DRY-RUN: ${worktrunkBinary} ${wtArgs.join(" ")}`,
|
|
2063
2111
|
`DRY-RUN: ${agentInvocation}`,
|
|
2064
2112
|
...(prBaseBranch ? [`DRY-RUN: PR base: ${prBaseBranch}`] : []),
|
|
2065
|
-
...buildDryRunMcpProvisioningLines("<worktree-path>", platform, mcpServerInvocation),
|
|
2113
|
+
...buildDryRunMcpProvisioningLines("<worktree-path>", platform, mcpServerInvocation, resolveSpawnBridgeApiBaseUrl(env)),
|
|
2066
2114
|
];
|
|
2067
2115
|
}
|
|
2068
2116
|
/**
|
|
@@ -2136,13 +2184,15 @@ export function formatSummaryReport(rows) {
|
|
|
2136
2184
|
* Provisioning needs real `fs/promises` ops (not part of the command-runner DI
|
|
2137
2185
|
* boundary), but inherits the platform and cwd from the orchestration deps.
|
|
2138
2186
|
*/
|
|
2139
|
-
export function buildMcpProvisioningDeps(deps) {
|
|
2187
|
+
export function buildMcpProvisioningDeps(deps, bridgeApiBaseUrlOverride) {
|
|
2140
2188
|
return {
|
|
2189
|
+
env: deps.env,
|
|
2141
2190
|
readFile: deps.readFile ?? ((filePath) => readFile(filePath, "utf-8")),
|
|
2142
2191
|
writeFile: deps.writeFile ?? ((filePath, data) => writeFile(filePath, data, "utf-8")),
|
|
2143
2192
|
mkdir: deps.mkdir ?? ((dirPath, options) => mkdir(dirPath, options)),
|
|
2144
2193
|
platform: deps.platform,
|
|
2145
2194
|
cwd: deps.cwd,
|
|
2195
|
+
bridgeApiBaseUrl: bridgeApiBaseUrlOverride ?? resolveSpawnBridgeApiBaseUrl(deps.env),
|
|
2146
2196
|
// Resolve how the worker MCP shim launches at dispatch time from the running
|
|
2147
2197
|
// conductor's own on-disk build (absolute-build-path primary, npm-channel
|
|
2148
2198
|
// fallback) — never from process.cwd(). `nodeExecutable` is kept as "node"
|
|
@@ -3199,6 +3249,7 @@ export async function orchestrateStartTickets(deps, options, overrides = {}) {
|
|
|
3199
3249
|
// Fail-open: an unresolved name is warned about loudly but never aborts the run.
|
|
3200
3250
|
const resolveRepoNameFn = overrides.resolveRepoName ?? resolveStartTicketsRepoName;
|
|
3201
3251
|
const resolvedRepoName = await resolveRepoNameFn(deps);
|
|
3252
|
+
const bridgeApiBaseUrl = await resolveStartTicketsBridgeApiBaseUrl(deps, agent);
|
|
3202
3253
|
if (!resolvedRepoName) {
|
|
3203
3254
|
overrides.repoNameWarningLog?.("Warning: could not resolve the repo name (set BAPI_REPO_NAME or add a valid " +
|
|
3204
3255
|
".bridge/config). Spawned worktrees may fall back to the directory name and " +
|
|
@@ -3211,7 +3262,7 @@ export async function orchestrateStartTickets(deps, options, overrides = {}) {
|
|
|
3211
3262
|
// epic.base_branch override applied above) so the spawned worker gets
|
|
3212
3263
|
// BAPI_BASE_BRANCH — every conductor worker, and a plain worker whose base
|
|
3213
3264
|
// is non-default.
|
|
3214
|
-
options.baseBranch);
|
|
3265
|
+
options.baseBranch, bridgeApiBaseUrl);
|
|
3215
3266
|
if (!platformConfig.ok)
|
|
3216
3267
|
return { ok: false, error: platformConfig.error };
|
|
3217
3268
|
// BAPI-527: resolve the base start point new worktrees are cut from BEFORE any
|
|
@@ -3261,7 +3312,7 @@ export async function orchestrateStartTickets(deps, options, overrides = {}) {
|
|
|
3261
3312
|
const provisionCommandsFn = overrides.provisionCommands ??
|
|
3262
3313
|
((rows, d) => provisionCommandsForCreatedWorktrees(rows, buildCommandProvisioningDeps(d), agent.name === "codex"));
|
|
3263
3314
|
const provisionFn = overrides.provisionMcpRegistrations ??
|
|
3264
|
-
((rows, d) => provisionMcpRegistrationsForCreatedWorktrees(rows, buildMcpProvisioningDeps(d)));
|
|
3315
|
+
((rows, d) => provisionMcpRegistrationsForCreatedWorktrees(rows, buildMcpProvisioningDeps(d, bridgeApiBaseUrl)));
|
|
3265
3316
|
const materializeFn = overrides.materializeFileCredentials ?? materializeFileCredentialsForCreatedWorktrees;
|
|
3266
3317
|
const detectTerminalFn = overrides.detectTerminal ?? detectTerminal;
|
|
3267
3318
|
const spawnTabsFn = overrides.spawnTabsForCreatedWorktrees ?? spawnTabsForCreatedWorktrees;
|
|
@@ -3427,7 +3478,7 @@ export async function runStartTicketsCli(argv, overrides = {}) {
|
|
|
3427
3478
|
return 1;
|
|
3428
3479
|
}
|
|
3429
3480
|
const options = parsed.options;
|
|
3430
|
-
const
|
|
3481
|
+
const rawDeps = overrides.deps ?? createDefaultStartTicketsDeps();
|
|
3431
3482
|
const orchestrate = overrides.orchestrate ?? orchestrateStartTickets;
|
|
3432
3483
|
// The parser validates `--agent`, so this resolves to a real spec; the guard
|
|
3433
3484
|
// is defensive only.
|
|
@@ -3436,6 +3487,14 @@ export async function runStartTicketsCli(argv, overrides = {}) {
|
|
|
3436
3487
|
errorLog(`Error: Unknown agent: '${options.agentName}'. Launchable agents: ${formatStartTicketsAgentNames()}.`);
|
|
3437
3488
|
return 1;
|
|
3438
3489
|
}
|
|
3490
|
+
// The editor's MCP registration can have a local endpoint that its Bash tool
|
|
3491
|
+
// does not inherit. Use that endpoint for the CLI's own routing as well as for
|
|
3492
|
+
// its generated worktree registration and terminal command. Never mutate the
|
|
3493
|
+
// caller's environment or read/copy its API key from the registration.
|
|
3494
|
+
const bridgeApiBaseUrl = await resolveStartTicketsBridgeApiBaseUrl(rawDeps, agent);
|
|
3495
|
+
const deps = bridgeApiBaseUrl
|
|
3496
|
+
? { ...rawDeps, env: { ...rawDeps.env, BAPI_BASE_URL: bridgeApiBaseUrl } }
|
|
3497
|
+
: rawDeps;
|
|
3439
3498
|
// BAPI-642: a malformed `--tier` value is fail-open — emit ONE concise,
|
|
3440
3499
|
// secret-free warning and continue (routing applies the premium fallback). It
|
|
3441
3500
|
// never aborts the launch or changes the numeric exit code.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
|
|
2
|
-
export const VERSION = "0.2.
|
|
3
|
-
export const BUILD_COMMIT = "
|
|
4
|
-
export const LAUNCHER_ARGS = ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
2
|
+
export const VERSION = "0.2.57";
|
|
3
|
+
export const BUILD_COMMIT = "dcfa5632b4eb";
|
|
4
|
+
export const LAUNCHER_ARGS = ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.57", "serve"];
|