@bridge_gpt/mcp-server 0.1.16 → 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 CHANGED
@@ -47,7 +47,8 @@ npx -y @bridge_gpt/mcp-server start-tickets [flags] KEY [KEY ...]
47
47
  | `--terminal terminal\|iterm` | auto-detect via `$TERM_PROGRAM` | Override the macOS terminal app (honored on macOS only) |
48
48
  | `--dry-run` | off | Print intended actions; create no worktrees, open no tabs (any OS) |
49
49
  | `--branch KEY=BRANCH` | `feature/<KEY>` | Use a custom branch for that ticket (repeatable) |
50
- | `--no-refresh-main` | off | Skip `git fetch origin main` + fast-forward of local `main` |
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. |
51
52
  | `--max-parallel N` | `3` | Max worktrees created concurrently |
52
53
  | `-h`, `--help` | — | Show usage |
53
54
 
@@ -244,6 +245,40 @@ Commands are slash commands you invoke from your AI assistant's chat. Most orche
244
245
 
245
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.
246
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
+
247
282
  ## Available Tools
248
283
 
249
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.
@@ -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 {};