/** * `jdcodec setup [--no-connector] [--no-docs]` — one-shot * MCP wiring helper. * * Two MCP servers are exposed by JD Codec: * * - **connector** (`jdcodec`) — the local stdio MCP server in this * package. Wired so the customer's AI agent can take browser * snapshots through JD Codec. * - **docs** (`jdcodec-docs`) — an HTTP MCP server at * `https://jdcodec.com/docs/mcp`. Wired so the customer's AI * agent can answer questions about JD Codec from the live docs * instead of training data. * * Four targets are supported today, in two flavours. * * The target name is what the customer types — it does *not* always * map 1:1 with the AI agent the customer is using. Two of the * targets reach more agents than their name implies: * * - `claude-code` writes to `~/.claude.json` via `claude mcp add`. * That config file is read by both the Claude Code CLI (terminal) * AND Anthropic's Claude VS Code extension. So this target wires * JD Codec into both. Customers running the Claude extension * inside VS Code should pick this target — NOT `vscode` below. * - `vscode` writes to VS Code's own `mcp.json` via `code --add-mcp`. * That config is read by VS Code's native Copilot agent (and any * other extension that consumes VS Code's MCP config). It is NOT * read by the Claude VS Code extension. * * CLI clients (auto-execute, fall back to printed commands): * - `claude-code` — `claude mcp add ...` * also covers Anthropic's Claude VS Code extension * (same `~/.claude.json` config file). * - `claude-vscode` — alias of `claude-code`. Same flow, same * config destination. Provided so customers * running the Claude VS Code extension can * reach for the name they think in. * - `vscode` — `code --add-mcp '{json}'` * covers VS Code's native Copilot agent + other * extensions reading VS Code's `mcp.json`. Does * NOT cover the Claude extension; that uses * `claude-code` (or `claude-vscode`) above. * * Manual clients (print config path + stable inputs + docs link): * - `cursor` — `agent` CLI exists but only manages already- * registered servers; no `agent mcp add`, so * registration requires editing `~/.cursor/mcp.json`. * - `windsurf` — no CLI add. GUI + JSON editing. The * `windsurf://windsurf-mcp-registry?serverName=...` * deeplink only works for servers already in * Windsurf's MCP marketplace; JDC isn't listed * there yet. * * The split between CLI and manual is per-client capability, not a * stylistic choice. Each CLI client provides a `buildArgs(server)` * function that turns a ServerSpec into the right add-args for that * client — Claude Code uses positional args, VS Code packs the * config into a `--add-mcp '{json}'` flag. * * Default behaviour: `jdcodec setup ` wires **both** servers. * Pass `--no-connector` or `--no-docs` to opt out of one. Passing * both is rejected (no-op). * * Why no idempotency pre-check on the CLI paths: parsing each * client's "list" output couples this code to a format we don't * control. Re-running setup is safe; the "already exists" failure * mode is benign and we say so. */ import { DisplayIO } from "./display.js"; export type ServerKey = "connector" | "docs"; export type Transport = "stdio" | "http"; export interface ServerSpec { key: ServerKey; /** MCP server name as registered in client configs. */ name: string; /** Human-readable label for status messages. */ label: string; /** Transport flavour — drives how each CLI client formats its add-args. */ transport: Transport; /** stdio command, e.g. `"jdcodec"`. Set when transport === "stdio". */ command?: string; /** HTTP URL. Set when transport === "http". */ url?: string; /** Plain-text description for manual-add clients. */ manualDescription: string; } export declare const SERVERS: Record; interface CliClient { kind: "cli"; /** Display name for the client. */ name: string; /** Executable to detect on PATH. */ cmd: string; /** URL to the client's install / shell-command-setup instructions. */ installUrl: string; /** * Build the `cmd`-specific add-args for a single server. Each CLI * client formats its add-args differently — Claude Code uses * positional args, VS Code packs the config into a `--add-mcp` * JSON flag. */ buildArgs: (server: ServerSpec) => string[]; } interface ManualClient { kind: "manual"; /** Display name for the client. */ name: string; /** Where the customer should add the MCP server config. */ configHint: string; /** URL to the client's official MCP setup docs. */ docsUrl: string; } export type ClientSpec = CliClient | ManualClient; export declare const CLIENTS: Record; export declare function isClient(arg: string | undefined): arg is keyof typeof CLIENTS; export interface SpawnResult { exitCode: number | null; stdout: string; stderr: string; } export interface SetupIO { /** Defaults to a real `which` lookup via spawnSync. */ which?: (cmd: string) => string | null; /** Defaults to spawning a real subprocess. */ spawnAsync?: (cmd: string, args: string[]) => Promise; /** Defaults to defaultDisplay. */ display?: DisplayIO; } export interface ParsedSetupArgs { /** True if --help / -h was passed. */ help: boolean; /** Client key (validated against CLIENTS), or null if missing. */ client: string | null; /** True unless --no-connector was passed. */ wantConnector: boolean; /** True unless --no-docs was passed. */ wantDocs: boolean; /** Unrecognized positional or flag, surfaced for error reporting. */ unknown: string[]; } export declare function parseSetupArgs(args: string[]): ParsedSetupArgs; export declare function printSetupHelp(display?: DisplayIO): void; export declare function runSetup(args: string[], opts?: SetupIO): Promise; export {};