@bridge_gpt/mcp-server 0.1.14 → 0.1.17
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 +80 -0
- package/build/agent-launchers/claude.js +85 -0
- package/build/agent-launchers/index.js +17 -0
- package/build/agent-launchers/types.js +1 -0
- package/build/agent-registry.js +68 -0
- package/build/chain-orchestrator.js +1150 -0
- package/build/chain-utils.js +68 -0
- package/build/commands.generated.js +3 -1
- package/build/doctor.js +172 -0
- package/build/fetch-stub.js +139 -0
- package/build/index.js +321 -38
- package/build/pipeline-orchestrator.js +57 -0
- package/build/pipelines.generated.js +133 -4
- package/build/schedule-run.js +951 -0
- package/build/schedule-store.js +132 -0
- package/build/scheduler-backends/at-fallback.js +144 -0
- package/build/scheduler-backends/escaping.js +113 -0
- package/build/scheduler-backends/index.js +72 -0
- package/build/scheduler-backends/launchd.js +216 -0
- package/build/scheduler-backends/systemd-user.js +237 -0
- package/build/scheduler-backends/task-scheduler.js +219 -0
- package/build/scheduler-backends/types.js +23 -0
- package/build/start-tickets-prereqs.js +346 -0
- package/build/start-tickets.js +1270 -0
- package/build/version.generated.js +1 -1
- package/package.json +9 -7
- package/pipelines/full-automation.json +47 -0
- package/pipelines/idea-to-ticket.json +71 -0
- package/smoke-test/SMOKE-TEST.md +509 -0
- package/smoke-test/smoke-test-mcp.md +23 -0
package/README.md
CHANGED
|
@@ -33,6 +33,49 @@ This runs `npm i @bridge_gpt/mcp-server@latest`, prints a before/after version s
|
|
|
33
33
|
|
|
34
34
|
The MCP server also checks for updates automatically on startup. If a newer version is available, you'll see a notice in your editor's MCP output logs with the upgrade command to run. This check is cached for 24 hours and never blocks server startup.
|
|
35
35
|
|
|
36
|
+
### CLI subcommand: `start-tickets`
|
|
37
|
+
|
|
38
|
+
Beyond `--init` / `--upgrade`, the package ships a `start-tickets` subcommand that spawns one Worktrunk worktree + selected-agent session per Jira ticket. The agent defaults to **Claude Code** (`claude`) and is configurable via `--agent`. It is part of the **existing `bridge-api-mcp-server` bin** — not a separate binary — so it travels with the package to every consumer. It also backs the `/start-tickets` slash command.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
npx -y @bridge_gpt/mcp-server start-tickets [flags] KEY [KEY ...]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
| Flag | Default | Meaning |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `--agent claude\|cursor-agent` | `claude` | Agent command to launch in each worktree |
|
|
47
|
+
| `--terminal terminal\|iterm` | auto-detect via `$TERM_PROGRAM` | Override the macOS terminal app (honored on macOS only) |
|
|
48
|
+
| `--dry-run` | off | Print intended actions; create no worktrees, open no tabs (any OS) |
|
|
49
|
+
| `--branch KEY=BRANCH` | `feature/<KEY>` | Use a custom branch for that ticket (repeatable) |
|
|
50
|
+
| `--base-branch <BRANCH>` | `main` | Cut new worktrees from `<BRANCH>` and refresh `origin/<BRANCH>` instead of `main` |
|
|
51
|
+
| `--no-refresh-main` | off (the configured base branch is refreshed) | Skip refresh of the configured base branch (default `main`). Historical flag name preserved for backward compatibility — despite the name, it now skips refresh of whatever `--base-branch` resolves to. |
|
|
52
|
+
| `--max-parallel N` | `3` | Max worktrees created concurrently |
|
|
53
|
+
| `-h`, `--help` | — | Show usage |
|
|
54
|
+
|
|
55
|
+
Each `KEY` must match `[A-Z]+-[0-9]+` (e.g., `BAPI-248`). The CLI creates/switches each worktree up front (throttled by `--max-parallel`), then opens one tab/session per successful worktree running the selected agent's `'/implement-ticket <KEY>'` — `claude '/implement-ticket <KEY>'` by default, or `cursor-agent '/implement-ticket <KEY>'` with `--agent cursor-agent`. The `/implement-ticket <KEY>` prompt is unchanged for both agents. To launch Cursor Agent instead of Claude Code:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
npx -y @bridge_gpt/mcp-server start-tickets --agent cursor-agent BAPI-248
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Cross-platform spawning.** The CLI routes spawning per platform; `--dry-run` previews the platform-correct command form on any OS. An unsupported `process.platform` (not `darwin`/`win32`/`linux`) fails fast with a clear "unsupported platform" message.
|
|
62
|
+
|
|
63
|
+
- **macOS** — opens a Terminal.app or iTerm tab via `osascript`.
|
|
64
|
+
- **Windows** — creates worktrees with **`git-wt`** (Worktrunk's winget alias) and opens a tab via **Windows Terminal (`wt.exe new-tab`)**, falling back to **`Start-Process powershell.exe`** when Windows Terminal is absent. Requires **Git for Windows / Git Bash** (Worktrunk runs its `pre-start` / `post-start` hooks via Git Bash). The Worktrunk binary (`git-wt`) and the tab launcher (`wt.exe`) are resolved independently and never conflated.
|
|
65
|
+
- **Linux** — creates one detached **tmux** session per ticket (pane kept open after the agent exits); attach with `tmux attach -t <session>`. A missing `tmux` produces a clear, actionable error.
|
|
66
|
+
|
|
67
|
+
Per-OS prerequisites: macOS `wt`, `git`, `osascript`; Windows `git-wt`, Git for Windows / Git Bash, Windows Terminal or PowerShell; Linux `wt`, `git`, `tmux`. Set `BAPI_WORKTRUNK_BIN` to override the Worktrunk executable name/path for nonstandard installs (`doctor` honors it too). The read-only `doctor` subcommand (below) additionally surfaces a missing `uv` — Worktrunk's `pre-start` hook runs `uv`, but live preflight does not check it — and the selected agent's command; run `doctor --agent cursor-agent` to also check `cursor-agent` (it prints `cursor-agent login` as an informational auth reminder).
|
|
68
|
+
|
|
69
|
+
### CLI subcommand: `doctor`
|
|
70
|
+
|
|
71
|
+
The package also ships a strictly **read-only** `doctor` subcommand that diagnoses the `start-tickets` prerequisites for the current OS without changing anything:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
npx -y @bridge_gpt/mcp-server doctor [--agent <name>]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
It is **read-only**: it never installs anything, modifies your system, adds an npm `postinstall`, spawns a terminal, or starts the MCP server, and there is no `--fix`. For each prerequisite it prints found/missing and, when missing, the exact per-OS install command **as a manual instruction you run yourself**. The checked set is the `start-tickets` preflight prerequisites **plus `uv`** **plus the selected agent's command** (`claude` by default, or `cursor-agent` with `--agent cursor-agent`). The Worktrunk binary is probed via the resolved name (honoring `BAPI_WORKTRUNK_BIN`), not a hard-coded one. **Exit code:** `0` when all required prerequisites are present, non-zero when any is missing or the platform is unsupported. A failing `start-tickets` preflight now hints you to run `doctor` for an actionable diagnostics report.
|
|
78
|
+
|
|
36
79
|
### 2. Generate an API Key
|
|
37
80
|
|
|
38
81
|
1. Log in to [Bridge API](https://bridgegpt-api.com) and navigate to your project's **Security** page
|
|
@@ -195,12 +238,47 @@ Commands are slash commands you invoke from your AI assistant's chat. Most orche
|
|
|
195
238
|
| `/review-ticket PROJ-123` | Two-round ticket quality review with critiques from multiple LLM providers |
|
|
196
239
|
| `/run-tests` | Run the full test suite, triage failures, and classify issues as test bugs vs. implementation bugs |
|
|
197
240
|
| `/scan-tickets` | Sync recently-updated Jira tickets and backfill workflow timestamps |
|
|
241
|
+
| `/start-tickets KEY [KEY ...]` | Spawn one Worktrunk worktree + selected-agent session per ticket via the packaged `start-tickets` CLI (Claude Code by default, `--agent cursor-agent` for Cursor; macOS Terminal/iTerm, Windows Terminal/PowerShell, or Linux tmux) |
|
|
198
242
|
| `/teach-bridge` | Update a Bridge API configuration field via natural-language instructions |
|
|
199
243
|
| `/update-ticket PROJ-123` | Fetch clarifying questions and critique, then rewrite the ticket description and push to Jira |
|
|
200
244
|
| `/write-ticket` | Draft a new Jira ticket from a prompt and upload it |
|
|
201
245
|
|
|
202
246
|
> Commands are designed for Claude Code. Other editors may support slash commands differently — check your editor's documentation for how to invoke prompt files.
|
|
203
247
|
|
|
248
|
+
## Smoke testing
|
|
249
|
+
|
|
250
|
+
The package ships a canonical, **opt-in** in-host smoke-test runbook at
|
|
251
|
+
`smoke-test/SMOKE-TEST.md`. An AI agent running inside your host (Claude Code,
|
|
252
|
+
Cursor, Codex, Windsurf, or VS Code/Copilot) executes it to verify that the MCP
|
|
253
|
+
server actually works end-to-end *inside that host* — it calls the real tools and
|
|
254
|
+
records a PASS/FAIL verdict for each one in a markdown report.
|
|
255
|
+
|
|
256
|
+
- `smoke-test/SMOKE-TEST.md` **ships with the npm package** and is the
|
|
257
|
+
**canonical** source of truth for the smoke test.
|
|
258
|
+
- The smoke test **adds no MCP tool** and **does not change the registered
|
|
259
|
+
tool surface** (the server still registers its existing 51 tools).
|
|
260
|
+
- It is **opt-in**: default `--init` **does not scaffold `/smoke-test-mcp`**, so
|
|
261
|
+
consumer command palettes are not polluted.
|
|
262
|
+
|
|
263
|
+
### Running it
|
|
264
|
+
|
|
265
|
+
You have two options:
|
|
266
|
+
|
|
267
|
+
1. **Copy the opt-in command manually.** Copy the packaged command stub into your
|
|
268
|
+
host's command directory, then invoke `/smoke-test-mcp`:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Claude Code
|
|
272
|
+
cp node_modules/@bridge_gpt/mcp-server/smoke-test/smoke-test-mcp.md .claude/commands/smoke-test-mcp.md
|
|
273
|
+
# Cursor
|
|
274
|
+
cp node_modules/@bridge_gpt/mcp-server/smoke-test/smoke-test-mcp.md .cursor/commands/smoke-test-mcp.md
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
2. **Open the runbook directly.** Alternatively, open
|
|
278
|
+
`smoke-test/SMOKE-TEST.md` and ask the host agent to execute it.
|
|
279
|
+
|
|
280
|
+
Reports are written to `<BAPI_DOCS_DIR>/smoke-test/REPORT-<host>-<timestamp>.md`.
|
|
281
|
+
|
|
204
282
|
## Available Tools
|
|
205
283
|
|
|
206
284
|
MCP tools are the low-level primitives Bridge exposes to your AI assistant. You don't call them directly — ask your AI assistant to perform the task you need, or compose them into a custom pipeline.
|
|
@@ -350,3 +428,5 @@ If a custom pipeline has the same key as a built-in pipeline, the custom version
|
|
|
350
428
|
| `BAPI_PROJECT_ROOT` | No | _(auto-set by --init)_ | Absolute path to project root. Anchors `BAPI_DOCS_DIR` and `BAPI_PIPELINES_DIR` resolution |
|
|
351
429
|
| `BAPI_DOCS_DIR` | No | `docs/tmp` | Local directory for saving plans, critiques, and research reports |
|
|
352
430
|
| `BAPI_PIPELINES_DIR` | No | `.bridge/pipelines` | Directory for user-defined custom pipeline JSON files |
|
|
431
|
+
| `BAPI_WORKTRUNK_BIN` | No | `wt` (`git-wt` on Windows) | Override the Worktrunk executable name/path used by `start-tickets` for nonstandard installs |
|
|
432
|
+
| `BAPI_TMUX_SESSION` | No | `bridge-start-tickets` | Override the tmux session-name prefix used by `start-tickets` on Linux |
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The v1 `claude` agent launcher (BAPI-327).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the `claude` binary against the *baked schedule-time PATH* (not the
|
|
5
|
+
* ambient process default), builds the locked
|
|
6
|
+
* `/full-automation --scheduled-at <T> --idea-file <abs> [--auto-approve]`
|
|
7
|
+
* prompt, and emits `{ exe, args: ["-p", prompt] }`. Claude Code has no
|
|
8
|
+
* working-directory flag, so the cwd is always set by the scheduler unit — this
|
|
9
|
+
* adapter must never add a cwd argument to the invocation.
|
|
10
|
+
*/
|
|
11
|
+
import { pathApiForPlatform } from "../scheduler-backends/types.js";
|
|
12
|
+
import { posixShellQuote, windowsCmdQuote } from "../scheduler-backends/escaping.js";
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a bare command to an absolute path using the platform PATH-probe,
|
|
15
|
+
* forcing the baked PATH so the schedule resolves the same binary the user had
|
|
16
|
+
* at creation time. On Windows both `PATH` and `Path` are overridden (Node and
|
|
17
|
+
* `where.exe` disagree on casing). Returns the first non-empty *absolute* path
|
|
18
|
+
* from stdout, or `null` when the probe fails or yields only relative paths.
|
|
19
|
+
*/
|
|
20
|
+
export async function resolveCommandOnPath(command, envPath, deps) {
|
|
21
|
+
const pathApi = pathApiForPlatform(deps.platform);
|
|
22
|
+
const probe = deps.platform === "win32" ? "where.exe" : "which";
|
|
23
|
+
const env = { ...deps.env, PATH: envPath };
|
|
24
|
+
if (deps.platform === "win32") {
|
|
25
|
+
// Windows env var lookup is case-insensitive but Node preserves the literal
|
|
26
|
+
// key; override both casings so neither the probe nor child sees a stale one.
|
|
27
|
+
env.Path = envPath;
|
|
28
|
+
}
|
|
29
|
+
const result = await deps.runCommand(probe, [command], { env });
|
|
30
|
+
if (result.exitCode !== 0)
|
|
31
|
+
return null;
|
|
32
|
+
const candidate = result.stdout
|
|
33
|
+
.split(/\r?\n/)
|
|
34
|
+
.map((line) => line.trim())
|
|
35
|
+
.find((line) => line.length > 0);
|
|
36
|
+
if (!candidate)
|
|
37
|
+
return null;
|
|
38
|
+
if (!pathApi.isAbsolute(candidate))
|
|
39
|
+
return null;
|
|
40
|
+
return pathApi.normalize(candidate);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Quote the idea-file path so it survives as a single `/full-automation`
|
|
44
|
+
* argument even when it contains spaces or markup-significant characters
|
|
45
|
+
* (`&`, `<`, `>`, …) that would otherwise be split or mangled when the slash
|
|
46
|
+
* command is parsed. Only an embedded double quote needs escaping; the same
|
|
47
|
+
* absolute path is additionally baked into `BRIDGE_GPT_IDEA_FILE` by every
|
|
48
|
+
* backend as a robust environment fallback.
|
|
49
|
+
*/
|
|
50
|
+
export function quoteIdeaFileForPrompt(ideaFile) {
|
|
51
|
+
return `"${ideaFile.replace(/"/g, '\\"')}"`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build the exact full-automation prompt. `--auto-approve` is appended by
|
|
55
|
+
* default; it is omitted only when the caller selected `--no-auto-approve`.
|
|
56
|
+
*/
|
|
57
|
+
export function buildClaudePrompt(input) {
|
|
58
|
+
const base = `/full-automation --scheduled-at ${input.runAtIso} ` +
|
|
59
|
+
`--idea-file ${quoteIdeaFileForPrompt(input.ideaFile)}`;
|
|
60
|
+
return input.autoApprove ? `${base} --auto-approve` : base;
|
|
61
|
+
}
|
|
62
|
+
const CLAUDE_CAPABILITY = {
|
|
63
|
+
name: "claude",
|
|
64
|
+
command: "claude",
|
|
65
|
+
supportsCwdFlag: false,
|
|
66
|
+
promptFlag: "-p",
|
|
67
|
+
};
|
|
68
|
+
/** Create the v1 Claude agent launcher. */
|
|
69
|
+
export function createClaudeLauncher() {
|
|
70
|
+
return {
|
|
71
|
+
capability: CLAUDE_CAPABILITY,
|
|
72
|
+
resolveBinary(envPath, deps) {
|
|
73
|
+
return resolveCommandOnPath("claude", envPath, deps);
|
|
74
|
+
},
|
|
75
|
+
buildInvocation(exe, input) {
|
|
76
|
+
const prompt = buildClaudePrompt(input);
|
|
77
|
+
// No working-directory flag: cwd is owned by the scheduler unit.
|
|
78
|
+
return { exe, args: [CLAUDE_CAPABILITY.promptFlag, prompt], prompt };
|
|
79
|
+
},
|
|
80
|
+
formatInvocationLine(invocation, platform) {
|
|
81
|
+
const quote = platform === "win32" ? windowsCmdQuote : posixShellQuote;
|
|
82
|
+
return [invocation.exe, ...invocation.args].map((part) => quote(part)).join(" ");
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-launcher registry (BAPI-327). v1 ships only `claude`; the lookup returns
|
|
3
|
+
* `null` for every other name so the CLI can reject unsupported agents with a
|
|
4
|
+
* clear message rather than silently falling back.
|
|
5
|
+
*/
|
|
6
|
+
import { createClaudeLauncher } from "./claude.js";
|
|
7
|
+
export { createClaudeLauncher } from "./claude.js";
|
|
8
|
+
const CLAUDE_LAUNCHER = createClaudeLauncher();
|
|
9
|
+
/** Return the launcher for a name, or `null` when unsupported in v1. */
|
|
10
|
+
export function getAgentLauncher(name) {
|
|
11
|
+
return name === "claude" ? CLAUDE_LAUNCHER : null;
|
|
12
|
+
}
|
|
13
|
+
/** Comma-separated list of valid agent-launcher names (just `claude` in v1). */
|
|
14
|
+
export function formatValidAgentLauncherNames() {
|
|
15
|
+
const names = ["claude"];
|
|
16
|
+
return names.join(", ");
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-registry — the single source of truth for the agents the packaged
|
|
3
|
+
* `start-tickets` CLI (and the read-only `doctor` subcommand) know how to launch.
|
|
4
|
+
*
|
|
5
|
+
* BAPI-305 replaced the former module-level `AGENT_COMMAND = "claude"` swap point
|
|
6
|
+
* in `start-tickets.ts` with this registry so the agent name -> command mapping
|
|
7
|
+
* lives in exactly one place. New agents are added by extending `AGENT_REGISTRY`;
|
|
8
|
+
* no other production module hard-codes an agent command.
|
|
9
|
+
*
|
|
10
|
+
* The module is intentionally dependency-free (it imports nothing from
|
|
11
|
+
* `start-tickets.ts` / `start-tickets-prereqs.ts` / `doctor.ts`) so every other
|
|
12
|
+
* module can import it without risking a circular dependency.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* The registry: the ONLY place mapping an agent name to its command/spec. Seeded
|
|
16
|
+
* with exactly `claude` (default) and `cursor-agent`. `as const satisfies` keeps
|
|
17
|
+
* the literal keys (so `AgentName` is a precise union) while type-checking each
|
|
18
|
+
* value against `AgentSpec`.
|
|
19
|
+
*/
|
|
20
|
+
export const AGENT_REGISTRY = {
|
|
21
|
+
claude: {
|
|
22
|
+
name: "claude",
|
|
23
|
+
command: "claude",
|
|
24
|
+
promptArgStyle: "positional",
|
|
25
|
+
installHint: {
|
|
26
|
+
darwin: "npm install -g @anthropic-ai/claude-code",
|
|
27
|
+
linux: "npm install -g @anthropic-ai/claude-code",
|
|
28
|
+
win32: "npm install -g @anthropic-ai/claude-code",
|
|
29
|
+
},
|
|
30
|
+
authNote: "Claude Code authenticates interactively on first run — follow its login/auth prompt if asked.",
|
|
31
|
+
},
|
|
32
|
+
"cursor-agent": {
|
|
33
|
+
name: "cursor-agent",
|
|
34
|
+
command: "cursor-agent",
|
|
35
|
+
promptArgStyle: "positional",
|
|
36
|
+
installHint: {
|
|
37
|
+
darwin: "curl https://cursor.com/install -fsSL | bash",
|
|
38
|
+
linux: "curl https://cursor.com/install -fsSL | bash",
|
|
39
|
+
win32: "irm 'https://cursor.com/install?win32=true' | iex",
|
|
40
|
+
},
|
|
41
|
+
authNote: "Run cursor-agent login to authenticate; doctor checks PATH presence only, not login state.",
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
/** The default agent used when `--agent` is omitted. */
|
|
45
|
+
export const DEFAULT_AGENT_NAME = "claude";
|
|
46
|
+
/** Registry keys in deterministic (insertion) order. */
|
|
47
|
+
export function listAgentNames() {
|
|
48
|
+
return Object.keys(AGENT_REGISTRY);
|
|
49
|
+
}
|
|
50
|
+
/** Type guard: true only for a registered agent name. */
|
|
51
|
+
export function isAgentName(value) {
|
|
52
|
+
return listAgentNames().includes(value);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve an agent name to its spec. An omitted name defaults to
|
|
56
|
+
* `DEFAULT_AGENT_NAME`; any unknown name (including `""` and wrong-case) returns
|
|
57
|
+
* `null` so callers can surface a validation error listing the valid names.
|
|
58
|
+
*/
|
|
59
|
+
export function resolveAgentSpec(name) {
|
|
60
|
+
const resolved = name ?? DEFAULT_AGENT_NAME;
|
|
61
|
+
if (!isAgentName(resolved))
|
|
62
|
+
return null;
|
|
63
|
+
return AGENT_REGISTRY[resolved];
|
|
64
|
+
}
|
|
65
|
+
/** Comma-delimited valid agent names for CLI validation errors (`claude, cursor-agent`). */
|
|
66
|
+
export function formatValidAgentNames() {
|
|
67
|
+
return listAgentNames().join(", ");
|
|
68
|
+
}
|