diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f02c944..0bc5b5aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,13 @@ jobs: - name: Build run: pnpm run build + - name: Check REFERENCE.md is up to date + # REFERENCE.md is captured from the CLI's own --help output, so any change to + # help text has to be regenerated and committed with it. Node version does not + # affect the output, so one column of the matrix is enough. + if: matrix.node-version == 24 + run: pnpm run check:reference + - name: Unit tests run: pnpm run test:unit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f5dacc85..7f4e4603 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -121,6 +121,10 @@ jobs: if: inputs.type == 'release' run: pnpm run build:readme + - name: Update REFERENCE.md + if: inputs.type == 'release' + run: pnpm run build:reference + - name: Report install size id: install-size # Measures the tarball/unpacked/full-install size of what will be @@ -288,7 +292,7 @@ jobs: NEW_VERSION="${{ steps.release.outputs.version }}" git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add package.json pnpm-lock.yaml CHANGELOG.md README.md + git add package.json pnpm-lock.yaml CHANGELOG.md README.md REFERENCE.md git commit -m "v${NEW_VERSION}" git tag -a "v${NEW_VERSION}" -m "Release v${NEW_VERSION}" git push origin main diff --git a/CHANGELOG.md b/CHANGELOG.md index fd7174e0..ef9de5e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- New [REFERENCE.md](REFERENCE.md) with the full `--help` output of every mcpc command, generated from the CLI itself so it always matches the release. + ## [0.6.0] - 2026-08-02 ### Added diff --git a/CLAUDE.md b/CLAUDE.md index 48406a73..0886fff4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -161,7 +161,7 @@ mcpc/ - `mcpc clean [sessions|profiles|logs|all ...]` - Clean up mcpc data - `mcpc help [command]` - Show help for a specific command (`--skill` prints the agent guide) -Run `mcpc --help` and `mcpc help ` for the authoritative, always-current inventory — the usage block in README.md is generated from it. +Run `mcpc --help` and `mcpc help ` for the authoritative, always-current inventory — the usage block in README.md and the whole of REFERENCE.md are generated from it. **Server formats for `connect`, `login`, `logout`:** @@ -638,6 +638,8 @@ For any non-trivial change (new feature, bug fix, behaviour change, or notable r Whenever a change touches the user-facing CLI surface — adding, renaming, or removing commands or flags, changing argument syntax, defaults, session states, or workflows — check the agent skill at `skills/mcpc/SKILL.md` (printed by `mcpc help --skill`) and update it so it keeps matching the actual CLI behaviour and README. The skill is a curated guide, not an exhaustive reference: it must never contradict the CLI, but it doesn't need to enumerate every flag — keep it concise and only add features that matter to agents. Purely internal changes don't need a skill update; as a rule of thumb, any change that warrants a `CHANGELOG.md` entry also warrants a quick skill check. +Any change to help text — a description, an option, an `addHelpText` section, a new command — also changes `REFERENCE.md`, which is captured verbatim from `mcpc --help` and `mcpc help `. Never edit it by hand: run `pnpm run build:reference` and commit the result. CI runs `pnpm run check:reference` and fails when the committed file has drifted from the CLI, so this is not optional. + Keep the MCP conformance tests up to date the same way you keep the e2e tests up to date. Whenever a change touches protocol behaviour, the OAuth/authentication flows, or transport handling, check `test/conformance/` in the same PR: update the adapter (`test/conformance/client.mjs`) if the change alters what a scenario observes, and wire up a matching upstream scenario when a new feature has one. Run the affected scenario locally before finishing — see `test/conformance/README.md` for the command, the current coverage table, and the list of scenarios that are not covered yet. A deliberate behaviour change that breaks the adapter must be fixed in the PR that makes the change, not discovered later when a release is gated on it. Keep each changelog entry to one or two short sentences focused on the user-visible behaviour. Do not enumerate implementation details, internal class names, or step-by-step breakdowns — readers want to know what changed for them, not how it was built. If an entry needs subheadings or its own bulleted breakdown, it's too long. @@ -785,7 +787,7 @@ Before releasing: 2. Ensure your branch is clean, up-to-date with `origin/main`, and all CI checks pass 3. Run `pnpm run release` (or `pnpm run release:minor` / `pnpm run release:major`) -The script validates preconditions locally (including `pnpm run check:deps-age`, see below), then triggers the `release.yml` GitHub Actions workflow which handles: dependency-age gate, lint, build, test, version bump, changelog update, README update, git commit/tag/push, npm publish (with provenance), and GitHub release creation. +The script validates preconditions locally (including `pnpm run check:deps-age`, see below), then triggers the `release.yml` GitHub Actions workflow which handles: dependency-age gate, lint, build, test, version bump, changelog update, README and REFERENCE update, git commit/tag/push, npm publish (with provenance), and GitHub release creation. ### Dependency-age gate diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16ce55ad..510337ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,6 +29,10 @@ If your change touches the user-facing CLI surface (commands, flags, argument sy or workflows), also update the built-in agent skill at [`skills/mcpc/SKILL.md`](./skills/mcpc/SKILL.md) (printed by `mcpc help --skill`) so it keeps matching the CLI and README. +If your change touches any help text, regenerate [`REFERENCE.md`](./REFERENCE.md) with +`pnpm run build:reference` and commit it — it is captured verbatim from `mcpc --help` and +`mcpc help `, and CI fails when it has drifted (`pnpm run check:reference`). + ## Development setup This repo uses [pnpm](https://pnpm.io/) 10 (pinned via `packageManager` in `package.json`). If you @@ -115,8 +119,8 @@ pnpm run release:major # major version bump (0.1.2 → 1.0.0) The script validates preconditions locally (clean branch, up-to-date with `origin/main`, dependency age), then triggers the `release.yml` GitHub Actions workflow which handles lint, build, test, version -bump, changelog update, README update, git commit/tag/push, npm publish (with provenance), and -GitHub release creation. +bump, changelog update, README and REFERENCE update, git commit/tag/push, npm publish (with +provenance), and GitHub release creation. ## Architecture diff --git a/README.md b/README.md index 002199e0..19936efc 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,9 @@ Run "mcpc --json" to get the same data as `{ sessions: [...], profiles: [...] }` Agent guide: mcpc help --skill ``` +For the full `--help` output of every command, see [REFERENCE.md](REFERENCE.md) +(also available in your terminal via `mcpc help `). + ### General actions With no arguments, `mcpc` lists all active sessions and saved OAuth profiles: diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 00000000..dbe45e1a --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,1003 @@ + + +# mcpc command reference + +Complete `--help` output for every `mcpc` command, in the order the commands are listed +by `mcpc --help`. It is generated from the CLI itself, so it always matches the installed +version — run `mcpc help ` to get the same text in your terminal. + +New to mcpc? Start with the [README](README.md), or run `mcpc help --skill` for the agent guide. + +- [`mcpc connect`](#mcpc-connect) +- [`mcpc close`](#mcpc-close) +- [`mcpc restart`](#mcpc-restart) +- [`mcpc login`](#mcpc-login) +- [`mcpc logout`](#mcpc-logout) +- [`mcpc clean`](#mcpc-clean) +- [`mcpc grep`](#mcpc-grep) +- [`mcpc x402`](#mcpc-x402) + - [`mcpc x402 init`](#mcpc-x402-init) + - [`mcpc x402 import`](#mcpc-x402-import) + - [`mcpc x402 remove`](#mcpc-x402-remove) + - [`mcpc x402 sign`](#mcpc-x402-sign) +- [`mcpc help`](#mcpc-help) +- [`mcpc @`](#mcpc-session) + - [`mcpc @ close`](#mcpc-session-close) + - [`mcpc @ restart`](#mcpc-session-restart) + - [`mcpc @ grep`](#mcpc-session-grep) + - [`mcpc @ tools-list`](#mcpc-session-tools-list) + - [`mcpc @ tools-get`](#mcpc-session-tools-get) + - [`mcpc @ tools-call`](#mcpc-session-tools-call) + - [`mcpc @ tasks-list`](#mcpc-session-tasks-list) + - [`mcpc @ tasks-get`](#mcpc-session-tasks-get) + - [`mcpc @ tasks-result`](#mcpc-session-tasks-result) + - [`mcpc @ tasks-cancel`](#mcpc-session-tasks-cancel) + - [`mcpc @ prompts-list`](#mcpc-session-prompts-list) + - [`mcpc @ prompts-get`](#mcpc-session-prompts-get) + - [`mcpc @ resources-list`](#mcpc-session-resources-list) + - [`mcpc @ resources-read`](#mcpc-session-resources-read) + - [`mcpc @ resources-subscribe`](#mcpc-session-resources-subscribe) + - [`mcpc @ resources-unsubscribe`](#mcpc-session-resources-unsubscribe) + - [`mcpc @ resources-templates-list`](#mcpc-session-resources-templates-list) + - [`mcpc @ skills-list`](#mcpc-session-skills-list) + - [`mcpc @ skills-get`](#mcpc-session-skills-get) + - [`mcpc @ logging-set-level`](#mcpc-session-logging-set-level) + - [`mcpc @ ping`](#mcpc-session-ping) + - [`mcpc @ server-discover`](#mcpc-session-server-discover) + - [`mcpc @ logs`](#mcpc-session-logs) + +## `mcpc` + +```text +Usage: mcpc [<@session>] [] [options] + +Universal command-line client for the Model Context Protocol (MCP). + +Commands: + connect [] [@session] Connect to an MCP server and start a new named @session + close <@session> Close a session + restart <@session> Restart a session (losing all state) + login Log in to a server and save an OAuth profile + logout Delete an OAuth profile for a server + clean [resources...] Clean up mcpc data (sessions, profiles, logs, all) + grep Search tools and instructions across all active sessions + x402 [subcommand] [args...] Configure an x402 payment wallet (EXPERIMENTAL) + help [command] [subcommand] Show help for a command + +Options: + --json Output in JSON format for scripting + --verbose Enable debug logging + --profile OAuth profile for the server ("default" if not provided) + --timeout Request timeout in seconds (default: 60) + --max-chars Truncate output to n characters (ignored in --json mode) + --insecure Skip TLS certificate verification (for self-signed certs) + -v, --version Output the version number + -h, --help Display help + +MCP session commands (after connecting): + <@session> Show MCP server info, capabilities, and tools overview + <@session> grep Search tools and instructions + <@session> tools-list List all server tools + <@session> tools-get Get tool details and schema + <@session> tools-call [arg:=val ... | | tasks-list + <@session> tasks-get + <@session> tasks-result + <@session> tasks-cancel + <@session> prompts-list + <@session> prompts-get [arg:=val ... | | resources-list + <@session> resources-read [-o | --raw] + <@session> resources-subscribe + <@session> resources-unsubscribe + <@session> resources-templates-list + <@session> skills-list + <@session> skills-get [--raw] + <@session> logging-set-level + <@session> ping + <@session> server-discover + <@session> logs [-n N] [--follow] [--since 1h] + +Run "mcpc" without arguments to show active sessions and OAuth profiles. +Run "mcpc --json" to get the same data as `{ sessions: [...], profiles: [...] }`. + +Agent guide: mcpc help --skill +``` + +## `mcpc connect` + +```text +Usage: mcpc connect [] [@session] [options] + +Connect to an MCP server and start a new named @session + +Options: + -H, --header
HTTP header (can be repeated) + --profile OAuth profile to use ("default" if skipped) + --no-profile Skip OAuth profile (connect anonymously) + --proxy <[host:]port> Start proxy MCP server for session + --proxy-bearer-token Require authentication for access to proxy server + --stdio Launch all local stdio servers from selected config files + --protocol-version Pin the MCP protocol version (see below) + --x402 [scheme] Enable x402 auto-payment (see below) + --json Output in JSON format + +Server formats: + mcp.apify.com Remote HTTP server (https:// auto-added) + ~/.vscode/mcp.json:puppeteer Config file entry (file:entry) + ~/.vscode/mcp.json Config file — connect every entry + (no server) Auto-discover configs and connect everything + +Auto-discovery (no server arg): + Scans ./ and ~ for .mcp.json, mcp.json, mcp_config.json, .cursor/mcp.json, + .vscode/mcp.json, .kiro/settings/mcp.json, ~/.claude.json, + ~/.codeium/windsurf/mcp_config.json, plus VS Code & Claude Desktop configs. + +Session name: + Omit @session to auto-generate from the server (mcp.apify.com → @apify) + or config entry. Matching sessions (same server, profile, header keys) + are reused. Bulk connects don't accept @session. + +Stdio servers (command-based, run locally): + Config entries spawn the command on connect, even if the handshake + later fails — only connect to configs you trust. Bulk connects skip + stdio by default; pass --stdio to include them. + +Protocol version: + mcpc negotiates the newest MCP version both sides support, from + 2026-07-28 down to 2024-10-07. Pass --protocol-version to pin one exact + version instead — the connection fails if the server does not offer it. + Run mcpc @session to see the negotiated version. + +x402 payments (experimental): + --x402 pays for paid tool calls from the wallet set up with mcpc x402. + Schemes: auto (default, prefers upto), upto, exact. + +Output: + For a single server, shows session, server info, capabilities, and tools. + Bulk connects list every session with its state, then a summary. + +JSON output (--json): + Array of `InitializeResult` or `DiscoverResult` objects extended with `toolNames` and `_mcpc`: + `[{ protocolVersion?, supportedVersions?, capabilities?, serverInfo?, instructions?, _meta?, toolNames?, _mcpc: { ... } }]` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#initializeresult + https://modelcontextprotocol.io/specification/2026-07-28/schema#discoverresult +``` + +## `mcpc close` + +```text +Usage: mcpc close <@session> [options] + +Close a session + +Options: + --json Output in JSON format + +JSON output (--json): + `{ sessionName, closed: true }` +``` + +## `mcpc restart` + +```text +Usage: mcpc restart <@session> [options] + +Restart a session (losing all state) + +Options: + --json Output in JSON format + +Output: + After restarting, shows session, server info, capabilities, and tools. + +JSON output (--json): + `InitializeResult` or `DiscoverResult` object extended with `toolNames` and `_mcpc`: + `{ protocolVersion?, supportedVersions?, capabilities?, serverInfo?, instructions?, _meta?, toolNames?, _mcpc: { ... } }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#initializeresult + https://modelcontextprotocol.io/specification/2026-07-28/schema#discoverresult +``` + +## `mcpc login` + +```text +Usage: mcpc login [options] + +Log in to a server and save an OAuth profile + +Options: + --profile Profile name (default: "default") + --scope OAuth scopes to request (e.g. --scope "read write") + --grant Grant: authorization-code (default), client-credentials, id-jag + --client-id Pre-registered OAuth client ID (skips CIMD and DCR) + --client-secret Pre-registered OAuth client secret (requires --client-id) + --client-key Private key (PEM path or literal) for private_key_jwt auth + --client-key-alg JWT signing algorithm for --client-key (default: RS256) + --token-endpoint OAuth token endpoint (client-credentials only, auto-discovered) + --idp Enterprise IdP issuer URL (id-jag only) + --idp-client-id Client ID pre-registered at the enterprise IdP (id-jag only) + --idp-client-secret Client secret for the enterprise IdP (id-jag only) + --idp-scope OIDC scopes for the IdP SSO (id-jag only, see below) + --client-metadata-url HTTPS URL of an OAuth CIMD (default: mcpc CIMD) + --no-client-metadata-url Disable CIMD; force DCR on CIMD-capable servers + --callback-port Loopback port for OAuth callback (default: 13316/31613/16133) + --callback-host OAuth callback host: 127.0.0.1 (default) or localhost + --json Output in JSON format + +Interactive login: + By default, the command opens your browser to authorize the server, + then saves the credentials as a reusable profile any session can use: + + default profile: mcpc login mcp.apify.com + named profile: mcpc login mcp.apify.com --profile work + then connect: mcpc connect mcp.apify.com @app --profile work + +Client registration (how mcpc identifies itself to the server): + 1. Client ID Metadata Documents (CIMD): the default. mcpc's hosted CIMD at + https://apify.github.io/mcpc/client-metadata.json identifies all mcpc + installs as one client. Override with --client-metadata-url , or + disable with --no-client-metadata-url. + 2. Pre-registration: pass --client-id (and --client-secret if issued). If the + client's redirect URI uses localhost (e.g. localhost:3118), match it with + --callback-host localhost --callback-port 3118. + 3. Dynamic Client Registration (DCR): fallback when CIMD is unsupported or + disabled and the server exposes a registration_endpoint. + + See https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization + +Machine-to-machine authentication (for CI/CD and daemons): + Pass --grant client-credentials, --client-id, and one credential: + + mcpc login mcp.example.com --grant client-credentials \ + --client-id my-svc --client-secret s3cr3t --scope "read write" + mcpc login mcp.example.com --grant client-credentials \ + --client-id my-svc --client-key ./key.pem + + --client-secret uses client_secret_basic; --client-key signs a private_key_jwt + assertion (RFC 7523). The token endpoint is auto-discovered; pin it with + --token-endpoint for servers without discoverable metadata. + + See https://modelcontextprotocol.io/extensions/auth/oauth-client-credentials + +Enterprise-managed authorization (SSO via your organization's IdP): + Pass --grant id-jag when your organization controls MCP server access + centrally through its identity provider (e.g. Okta). You sign in once with + your corporate SSO; mcpc then obtains MCP tokens via identity assertion + grants (ID-JAG) without any per-server consent screens: + + mcpc login mcp.example.com --grant id-jag \ + --idp https://acme.okta.com --idp-client-id \ + --client-id --client-secret + + Both clients are pre-registered by your IT team: --idp-client-id at the + enterprise IdP (add --idp-client-secret if it is a confidential client), + --client-id/--client-secret at the MCP server's authorization server. + --scope requests MCP-server scopes; --idp-scope overrides the OIDC scopes + used for the SSO itself (default: "openid profile email offline_access"). + + See https://modelcontextprotocol.io/extensions/auth/enterprise-managed-authorization + +JSON output (--json): + Interactive prompts go to stderr; stdout is a clean JSON object: + `{ profile, serverUrl, scopes }` +``` + +## `mcpc logout` + +```text +Usage: mcpc logout [options] + +Delete an OAuth profile for a server + +Options: + --profile Profile name (default: "default") + --json Output in JSON format + +JSON output (--json): + `{ profile, serverUrl, deleted: true, affectedSessions }` +``` + +## `mcpc clean` + +```text +Usage: mcpc clean [options] [resources...] + +Clean up mcpc data (sessions, profiles, logs, all) + +Options: + --json Output in JSON format + +Resources: + sessions Remove stale/crashed session records + profiles Remove authentication profiles + logs Remove bridge log files + all Remove all of the above + + Without arguments, performs safe cleanup of stale data only. + +JSON output (--json): + `{ crashedBridges, expiredSessions, orphanedBridgeLogs, sessions, profiles, logs }` +``` + +## `mcpc grep` + +```text +Usage: mcpc grep [options] + +Search tools and instructions across all active sessions + +Options: + --tools Search tools + --resources Search resources + --prompts Search prompts + --instructions Search server instructions + -E, --regex Treat pattern as a regular expression + -s, --case-sensitive Case-sensitive matching + -m, --max-results Limit the number of results + --json Output in JSON format + +Type filters: + By default, tools and instructions are searched. Use --resources or --prompts + to search those instead. Combine flags to search multiple types (e.g. --tools --resources). + +Examples: + mcpc grep "search" Search tools and instructions in all sessions + mcpc grep "search" --resources Search resources only + mcpc grep "search" --tools --prompts Search tools and prompts + mcpc grep "search|find" -E Regex search across tools and instructions + mcpc @apify grep "actor" Search within a single session + mcpc grep "file" --json JSON output for scripting + mcpc grep "actor" -m 5 Show at most 5 results + +Exit codes: + 0 = matches found, 1 = no matches (grep convention) + +JSON output (--json): + `[{ sessionName, tools?: Tool[], resources?: Resource[], prompts?: Prompt[], instructions?: string[] }]` +``` + +## `mcpc x402` + +```text +Usage: mcpc x402 [options] [command] + +x402 wallet management and payment signing (EXPERIMENTAL) + +Options: + --json Output in JSON format + --verbose Enable debug logging + -h, --help Display help + +Commands: + init Create a new x402 wallet (generates a random private key) + import Import an existing wallet from a private key + remove Remove the wallet + sign [options] Sign a payment from a base64 PAYMENT-REQUIRED header + help [command] Display help for command + +sign options: + --amount Override amount in USD (for upto: max authorization cap) + --expiry Override expiry in seconds + --scheme Payment scheme: auto (default), upto, or exact + --no-approve Skip the upto Permit2 allowance check & auto-approval + +JSON output (--json): + `{ address, createdAt, balances: { eth, usdc } | null }` (null if no wallet) +``` + +### `mcpc x402 init` + +```text +Usage: mcpc x402 init [options] + +Create a new x402 wallet (generates a random private key) + +Options: + -h, --help Display help + +JSON output (--json): + `{ address }` +``` + +### `mcpc x402 import` + +```text +Usage: mcpc x402 import [options] + +Import an existing wallet from a private key + +Options: + -h, --help Display help + +JSON output (--json): + `{ address }` +``` + +### `mcpc x402 remove` + +```text +Usage: mcpc x402 remove [options] + +Remove the wallet + +Options: + -h, --help Display help + +JSON output (--json): + `{ removed: true }` +``` + +### `mcpc x402 sign` + +```text +Usage: mcpc x402 sign [options] + +Sign a payment from a base64 PAYMENT-REQUIRED header + +Options: + --amount Override amount in USD (for upto: max authorization cap) + --expiry Override expiry in seconds + --scheme Payment scheme preference (default: "auto") + --no-approve Skip the upto Permit2 allowance check & auto-approval + -h, --help Display help + +Signs the given base64-encoded PAYMENT-REQUIRED header offline using the configured +wallet and prints the resulting PAYMENT-SIGNATURE header (plus an MCP config snippet) +to stdout. Useful for pre-signing payments or integrating with other MCP clients. + +JSON output (--json): + `{ paymentSignature, from, to, amount, amountAtomicUnits, network, expiresAt }` +``` + +## `mcpc help` + +```text +Usage: mcpc help [options] [command] [subcommand] + +Show help for a command + +Options: + --skill Print the agent skill (mental model, workflows, examples) + --json Output in JSON format +``` + +## `mcpc @` + +```text +Usage: mcpc @ [options] [command] + +Show MCP session info or execute commands. + +Options: + --json Output in JSON format for scripting and code mode + --verbose Enable debug logging + --profile OAuth profile override + --timeout Request timeout in seconds (default: 60) + --max-chars Truncate output to n characters (ignored in --json mode) + --insecure Skip TLS certificate verification (for self-signed certs) + -h, --help Display help + +Commands: + close Close MCP session. + restart Restart MCP session (losing all state). + grep Search MCP session objects. + tools-list List all MCP tools. + tools-get Get details and schema for an MCP tool. + tools-call [args...] Call an MCP tool with arguments. + tasks-list List all MCP tasks. + tasks-get Get MCP task status. + tasks-result Get MCP task final result (blocks until the task finishes). + tasks-cancel Cancel an MCP task. + resources-list List all MCP resources. + resources-read Read an MCP resource by URI. + resources-subscribe Subscribe to an MCP resource and sync it to a local file. + resources-unsubscribe Stop syncing a subscribed MCP resource (keeps the local file). + resources-templates-list List MCP resource templates. + skills-list [EXPERIMENTAL] List agent skills from the server (SEP-2640). + skills-get [EXPERIMENTAL] Read a skill's SKILL.md by name (SEP-2640). + prompts-list List all MCP prompts. + prompts-get [args...] Get an MCP prompt with arguments. + logging-set-level Set MCP server logging level (deprecated). + ping Ping the MCP server. + server-discover Ask the server what it supports (MCP 2026-07-28+). + logs Show or follow the bridge log file for this session. + +Output: + When no command is given, shows session, server info, capabilities, and tools. + +JSON output (--json): + `InitializeResult` or `DiscoverResult` object extended with `toolNames` and `_mcpc`: + `{ protocolVersion?, supportedVersions?, capabilities?, serverInfo?, instructions?, _meta?, toolNames?, _mcpc: { ... } }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#initializeresult + https://modelcontextprotocol.io/specification/2026-07-28/schema#discoverresult +``` + +### `mcpc @ close` + +```text +Usage: mcpc @ close [options] + +Close MCP session. + +Options: + --json Output in JSON format + +JSON output (--json): + `{ sessionName, closed: true }` +``` + +### `mcpc @ restart` + +```text +Usage: mcpc @ restart [options] + +Restart MCP session (losing all state). + +Options: + --json Output in JSON format + +Output: + After restarting, shows session, server info, capabilities, and tools. + +JSON output (--json): + `InitializeResult` or `DiscoverResult` object extended with `toolNames` and `_mcpc`: + `{ protocolVersion?, supportedVersions?, capabilities?, serverInfo?, instructions?, _meta?, toolNames?, _mcpc: { ... } }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#initializeresult + https://modelcontextprotocol.io/specification/2026-07-28/schema#discoverresult +``` + +### `mcpc @ grep` + +```text +Usage: mcpc @ grep [options] + +Search MCP session objects. + +Options: + --tools Search tools + --resources Search resources + --prompts Search prompts + --instructions Search server instructions + -E, --regex Treat pattern as a regular expression + -s, --case-sensitive Case-sensitive matching + -m, --max-results Limit the number of results + --json Output in JSON format + +Type filters: + By default, tools and instructions are searched. Use --resources or --prompts + to search those instead. Combine flags to search multiple types. + +Examples: + mcpc @ grep "search" Search tools and instructions + mcpc @ grep "search" --resources Search resources only + mcpc @ grep "search|find" -E Regex search + +Exit codes: + 0 = matches found, 1 = no matches (grep convention) + +JSON output (--json): + `{ tools?: Tool[], resources?: Resource[], prompts?: Prompt[], instructions?: string[] }` +``` + +### `mcpc @ tools-list` + +```text +Usage: mcpc @ tools-list [options] + +List all MCP tools. + +Options: + --full Show full tool details including schema + --json Output in JSON format + +JSON output (--json): + Array of `Tool` objects: + `[{ name, description?, inputSchema, outputSchema?, annotations? }, ...]` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#tool +``` + +### `mcpc @ tools-get` + +```text +Usage: mcpc @ tools-get [options] + +Get details and schema for an MCP tool. + +Options: + --schema Validate tool schema against expected schema + --schema-mode Schema validation mode: strict, compatible (default), ignore + --json Output in JSON format + +Schema validation: + --schema Validate against expected schema (save with tools-get --json) + --schema-mode strict | compatible (default) | ignore + +JSON output (--json): + `Tool` object: + `{ name, description?, inputSchema, outputSchema?, annotations? }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#tool +``` + +### `mcpc @ tools-call` + +```text +Usage: mcpc @ tools-call [options] [args...] + +Call an MCP tool with arguments. + +Options: + --task Use async task execution; Ctrl+C prints the task ID and exits (experimental) + --detach Start task and return immediately with task ID (implies --task) + --schema Validate tool schema against expected schema before calling + --schema-mode Schema validation mode: strict, compatible (default), ignore + --json Output in JSON format + +Arguments: + key:=value pairs mcpc @ tools-call search query:=hello limit:=10 + Inline JSON mcpc @ tools-call search '{"query":"hello"}' + Stdin pipe echo '{"query":"hello"}' | mcpc @ tools-call search + + Values are auto-parsed: strings, numbers, booleans, JSON objects/arrays. + To force a string, wrap in quotes: id:='"123"' + Tip: mcpc @ tools-call --help prints the tool's parameter schema. + +Async tasks (--task, --detach): + --task shows a progress spinner while the task runs on the server. + If you press Ctrl+C, the task keeps running and a hint with the task ID + is printed so you can fetch or cancel it later. + --detach returns the task ID immediately without waiting. + Both flags require a server that advertises the tasks capability and uses + MCP protocol 2025-11-25 (on 2026-07-28 servers tasks are an extension not + yet supported by mcpc). If it does not, the command fails instead of + running the tool synchronously — the flags change the output shape, so the + fallback would silently return a result where a task ID is expected. + Check per-tool support in tools-list: [task:optional|required|forbidden]. + +Schema validation: + --schema Validate tool schema before calling (save with tools-get --json) + --schema-mode strict | compatible (default) | ignore + +JSON output (--json): + `CallToolResult` object: + `{ content: [{ type, text?, ... }], isError?, structuredContent?: { ... } }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#calltoolresult + + With `--detach`: `CreateTaskResult` object: + `{ taskId: string, status: string }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#createtaskresult +``` + +### `mcpc @ tasks-list` + +```text +Usage: mcpc @ tasks-list [options] + +List all MCP tasks. + +Options: + --json Output in JSON format + +JSON output (--json): + `{ tasks: Task[] }`: + `{ tasks: [{ taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage?, pollInterval? }] }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#task +``` + +### `mcpc @ tasks-get` + +```text +Usage: mcpc @ tasks-get [options] + +Get MCP task status. + +Options: + --json Output in JSON format + +JSON output (--json): + `Task` object: + `{ taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage?, pollInterval? }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#task +``` + +### `mcpc @ tasks-result` + +```text +Usage: mcpc @ tasks-result [options] + +Get MCP task final result (blocks until the task finishes). + +Options: + --json Output in JSON format + +JSON output (--json): + `CallToolResult` object: + `{ content: [{ type, text?, ... }], isError?, structuredContent?: { ... } }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#calltoolresult +``` + +### `mcpc @ tasks-cancel` + +```text +Usage: mcpc @ tasks-cancel [options] + +Cancel an MCP task. + +Options: + --json Output in JSON format + +JSON output (--json): + `Task` object: + `{ taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage?, pollInterval? }` + Schema: https://modelcontextprotocol.io/specification/2025-11-25/schema#task +``` + +### `mcpc @ prompts-list` + +```text +Usage: mcpc @ prompts-list [options] + +List all MCP prompts. + +Options: + --json Output in JSON format + +JSON output (--json): + Array of `Prompt` objects: + `[{ name, description?, arguments?: [{ name, required? }] }, ...]` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#prompt +``` + +### `mcpc @ prompts-get` + +```text +Usage: mcpc @ prompts-get [options] [args...] + +Get an MCP prompt with arguments. + +Options: + --json Output in JSON format + +Arguments: + key:=value pairs mcpc @ prompts-get summarize style:=brief lang:=en + Inline JSON mcpc @ prompts-get summarize '{"style":"brief"}' + Stdin pipe echo '{"style":"brief"}' | mcpc @ prompts-get summarize + + Values are auto-parsed: strings, numbers, booleans, JSON objects/arrays. + To force a string, wrap in quotes: id:='"123"' + +JSON output (--json): + `GetPromptResult` object: + `{ description?, messages: [{ role, content: { type, text?, ... } }] }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#getpromptresult +``` + +### `mcpc @ resources-list` + +```text +Usage: mcpc @ resources-list [options] + +List all MCP resources. + +Options: + --json Output in JSON format + +JSON output (--json): + Array of `Resource` objects: + `[{ uri, name, description?, mimeType? }, ...]` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#resource +``` + +### `mcpc @ resources-read` + +```text +Usage: mcpc @ resources-read [options] + +Read an MCP resource by URI. + +Options: + -o, --output Save the resource to a file (decodes binary content) + --raw Print only the resource content, suitable for piping + --json Output in JSON format + +Output: + Default: pretty view; binary (blob) content is summarized, never dumped. + --raw prints the bare content (binary requires a redirect or -o). + -o saves the content; base64 `blob` data is decoded to bytes. + If the server returns multiple content items, --raw and -o use the item + matching (or the first one) — use --json to get all items. + +JSON output (--json): + `ReadResourceResult` object: + `{ contents: [{ uri, mimeType?, text? | blob? }], ttlMs?, cacheScope? }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#readresourceresult + + `ttlMs`/`cacheScope` are caching hints only present on 2026-07-28 connections. + With `-o`: `{ uri, file, bytes, mimeType? }` summary instead. +``` + +### `mcpc @ resources-subscribe` + +```text +Usage: mcpc @ resources-subscribe [options] + +Subscribe to an MCP resource and sync it to a local file. + +Options: + --json Output in JSON format + +Behavior: + Downloads the resource to now; afterwards the session bridge rewrites + the file whenever the server announces a change for (the MCP + notifications/resources/updated flow). Requires the server capability + `resources.subscribe` — check with `mcpc @`. Subscriptions are + re-established automatically when the session reconnects or restarts. + Subscribing to the same again just changes the target . + +Example: + mcpc @ resources-subscribe file:///app/config.json ./config.json + +JSON output (--json): + `{ subscribed: true, uri, file, bytes, mimeType? }` +``` + +### `mcpc @ resources-unsubscribe` + +```text +Usage: mcpc @ resources-unsubscribe [options] + +Stop syncing a subscribed MCP resource (keeps the local file). + +Options: + --json Output in JSON format + +JSON output (--json): + `{ unsubscribed: true, uri, file }` +``` + +### `mcpc @ resources-templates-list` + +```text +Usage: mcpc @ resources-templates-list [options] + +List MCP resource templates. + +Options: + --json Output in JSON format + +JSON output (--json): + Array of `ResourceTemplate` objects: + `[{ uriTemplate, name, description?, mimeType? }, ...]` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#resourcetemplate +``` + +### `mcpc @ skills-list` + +```text +Usage: mcpc @ skills-list [options] + +[EXPERIMENTAL] List agent skills from the server (SEP-2640). + +Options: + --json Output in JSON format + +Discovery: + Tries `skill://index.json`, else scans `skill://*/SKILL.md`. Types: + `skill-md`, `mcp-resource-template`, `archive` (use `resources-read `). + +JSON output (--json): + `[{ name, description, type, url }, ...]` + Schema: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2640 +``` + +### `mcpc @ skills-get` + +```text +Usage: mcpc @ skills-get [options] + +[EXPERIMENTAL] Read a skill's SKILL.md by name (SEP-2640). + +Options: + --raw Print only the SKILL.md text (Markdown), suitable for piping + --json Output in JSON format + +Names: + `name`, `nested/path`, or `skill://...` URI. For `archive` skills, use + `resources-read `. With --json, --raw is ignored. + +JSON output (--json): + `ReadResourceResult`: `{ contents: [{ uri, mimeType?, text? | blob? }], ttlMs?, cacheScope? }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#readresourceresult +``` + +### `mcpc @ logging-set-level` + +```text +Usage: mcpc @ logging-set-level [options] + +Set MCP server logging level (deprecated). + +Options: + --json Output in JSON format + +Deprecated: + MCP 2026-07-28 removed logging/setLevel, so this works on 2025-11-25 (and older) + servers only and will be removed in a future mcpc release. Use --verbose for + client-side logging instead. + +JSON output (--json): + `{ level: string }` +``` + +### `mcpc @ ping` + +```text +Usage: mcpc @ ping [options] + +Ping the MCP server. + +Options: + --json Output in JSON format + +Notes: + Measures the request roundtrip. MCP 2026-07-28 removed `ping`, so on modern + connections the liveness probe is `server/discover` instead — run + `mcpc @ server-discover` to see what that request returns. + +JSON output (--json): + `{ success: true, durationMs: number }` +``` + +### `mcpc @ server-discover` + +```text +Usage: mcpc @ server-discover [options] + +Ask the server what it supports (MCP 2026-07-28+). + +Options: + --json Output in JSON format + +Notes: + Sends `server/discover` and reports the answer: every protocol version the + server supports, its capabilities, instructions, and `_meta`. Unlike + `mcpc @`, which shows what the connection settled on at connect time, + this is a live request. + MCP 2026-07-28 introduced the method, so the command fails on 2025-11-25 (and + older) connections, where `initialize` carries the same data — run + `mcpc @` there instead. + +JSON output (--json): + `DiscoverResult` object, verbatim: + `{ supportedVersions: [...], capabilities: { ... }, instructions?, _meta? }` + Schema: https://modelcontextprotocol.io/specification/2026-07-28/schema#discoverresult +``` + +### `mcpc @ logs` + +```text +Usage: mcpc @ logs [options] + +Show or follow the bridge log file for this session. + +Options: + -n, --tail Number of recent lines to show (default: 50) + --follow Stream new log lines as they are written + --since Only show entries newer than a duration (30s, 5m, 2h, 1d) or ISO timestamp + --json Output in JSON format + +Examples: + mcpc @ logs Last 50 lines + mcpc @ logs -n 200 Last 200 lines + mcpc @ logs --follow Stream new lines (ESC/Ctrl+C/q to stop) + mcpc @ logs --since 1h Lines from the last hour + mcpc @ logs --since 30m -n 50 + +Notes: + Reads ~/.mcpc/logs/bridge-@.log and transparently spans + rotated files (.log.1 … .log.5) when -n or --since needs older lines. + Continuation lines (e.g. stack traces) fold into the preceding entry's msg. + +JSON output (--json): + Array of log records (JSONL when streaming with --follow): + `[{ time, level, context?, msg } | { raw }, ...]` +``` diff --git a/package.json b/package.json index ee38fbcf..2e148e1c 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "build": "tsc && node scripts/bundle-viem.mjs", "build:watch": "tsc --watch", "build:readme": "./scripts/update-readme.sh", + "build:reference": "node scripts/generate-reference.mjs", + "check:reference": "node scripts/generate-reference.mjs --check", "test": "pnpm run build && pnpm run test:unit && ./test/e2e/run.sh --no-build --parallel 8 && ./test/e2e/run.sh --no-build --parallel 8 --server-protocol modern && ./test/e2e/run.sh --no-build --parallel 8 --runtime bun", "test:unit": "vitest run", "test:watch": "vitest", diff --git a/scripts/generate-reference.mjs b/scripts/generate-reference.mjs new file mode 100644 index 00000000..75ee8b1a --- /dev/null +++ b/scripts/generate-reference.mjs @@ -0,0 +1,238 @@ +#!/usr/bin/env node +/** + * Generates REFERENCE.md — the `--help` output of every mcpc command, in the order + * the commands appear in `mcpc --help`. + * + * The CLI's help text is mcpc's primary documentation surface (see CLAUDE.md), so the + * reference is never hand-written: it is captured from the built CLI itself, exactly + * like the Usage block in README.md is. Run it with `--check` to fail when the + * committed file has drifted from the CLI. + * + * Usage: + * node scripts/generate-reference.mjs Write REFERENCE.md + * node scripts/generate-reference.mjs --check Verify REFERENCE.md is up to date + */ + +import { execFileSync } from 'node:child_process'; +import { mkdtempSync, readFileSync, rmSync, writeFileSync, existsSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const PROJECT_ROOT = dirname(dirname(fileURLToPath(import.meta.url))); +const CLI = join(PROJECT_ROOT, 'bin', 'mcpc'); +const OUTPUT_FILE = join(PROJECT_ROOT, 'REFERENCE.md'); + +/** + * Placeholder session name used for the session command help screens. The CLI accepts it + * and echoes it back in usage lines and examples, which keeps the reference generic + * instead of pinning it to whatever session happened to exist when it was generated. + */ +const SESSION = '@'; + +const checkOnly = process.argv.includes('--check'); + +/** + * Run the local CLI and return its stdout. + * + * The environment is scrubbed so the output depends only on the code: colors off (ANSI + * escapes would end up in the Markdown), MCPC_* unset (they change output mode), and + * MCPC_HOME_DIR pointed at a throwaway directory so no real session or profile data can + * leak into the generated file. + */ +function runCli(args, homeDir) { + return execFileSync(process.execPath, [CLI, ...args], { + encoding: 'utf8', + env: { + ...process.env, + MCPC_HOME_DIR: homeDir, + MCPC_JSON: '', + MCPC_VERBOSE: '', + NO_COLOR: '1', + FORCE_COLOR: '0', + }, + }); +} + +/** + * Collect the command names from a Commander `Commands:` block. Commander indents each + * command term by exactly two spaces and wraps long descriptions further to the right, + * so the two-space test picks the terms and skips continuation lines. + */ +function parseCommandsBlock(help) { + const names = []; + let inBlock = false; + for (const line of help.split('\n')) { + if (/^Commands:/.test(line)) { + inBlock = true; + continue; + } + if (/^\S/.test(line)) { + inBlock = false; + continue; + } + if (!inBlock) continue; + const match = line.match(/^ {2}(\S+)/); + if (match) names.push(match[1]); + } + return names; +} + +/** + * Collect the session command names from the "MCP session commands" block of the + * top-level help — this is the order the task asks the reference to follow. Lines + * without a command after the `<@session>` placeholder (the bare session screen) and + * argument placeholders are skipped. + */ +function parseSessionCommandsBlock(help) { + const names = []; + let inBlock = false; + for (const line of help.split('\n')) { + if (/^MCP session commands/.test(line)) { + inBlock = true; + continue; + } + if (/^\S/.test(line)) { + inBlock = false; + continue; + } + if (!inBlock) continue; + const match = line.match(/^ {2}<@session>\s+([a-z][a-z-]*)\b/); + if (match) names.push(match[1]); + } + return names; +} + +/** + * Order `all` by `preferred`, keeping the entries `preferred` does not mention. + * + * The top-level help's session block is hand-maintained prose, so it defines the order + * but cannot be trusted for completeness — the session program's own command list can. + * Anything missing from `preferred` is placed next to the neighbour it has in `all`, so a + * newly added session command shows up in the reference in a sensible spot even if nobody + * remembered to list it in the overview. + */ +function orderBy(preferred, all) { + const known = new Set(all); + const result = preferred.filter((name) => known.has(name)); + for (const [index, name] of all.entries()) { + if (result.includes(name)) continue; + const successor = all.slice(index + 1).find((other) => result.includes(other)); + const at = successor ? result.indexOf(successor) : result.length; + result.splice(at, 0, name); + } + return result; +} + +/** GitHub's heading slug rules, enough for the headings this file generates. */ +function slug(heading) { + return heading + .toLowerCase() + .replace(/[^\w\- ]/g, '') + .trim() + .replace(/ +/g, '-'); +} + +/** One reference section: a heading, the anchor for the table of contents, and the help. */ +function section(level, title, help) { + return { + level, + title, + anchor: slug(title), + body: `${'#'.repeat(level)} \`${title}\`\n\n\`\`\`text\n${help.trimEnd()}\n\`\`\`\n`, + }; +} + +function build() { + const homeDir = mkdtempSync(join(tmpdir(), 'mcpc-reference-')); + try { + // The top-level help is the spine of the whole file: it defines which commands exist + // and in which order they are documented. + // + // The "Full docs:" line is dropped for the same reason README.md drops it: it embeds + // the current package version, which would make the committed file go stale on every + // release and turn the --check gate into noise. + const topLevelHelp = runCli(['--help'], homeDir); + const topLevelCommands = parseCommandsBlock(topLevelHelp); + if (topLevelCommands.length === 0) { + throw new Error('no commands found in "mcpc --help" output'); + } + + const sections = [ + section(2, 'mcpc', topLevelHelp.replace(/^Full docs:.*\n?/m, '')), + ]; + + for (const command of topLevelCommands) { + const help = runCli(['help', command], homeDir); + sections.push(section(2, `mcpc ${command}`, help)); + + // Commands with their own Commander program (x402) document their subcommands on + // separate screens, which the parent screen only summarises. + for (const subcommand of parseCommandsBlock(help)) { + if (subcommand === 'help') continue; + sections.push( + section(3, `mcpc ${command} ${subcommand}`, runCli(['help', command, subcommand], homeDir)) + ); + } + } + + const sessionHelp = runCli([SESSION, '--help'], homeDir); + sections.push(section(2, `mcpc ${SESSION}`, sessionHelp)); + + const sessionCommands = orderBy( + parseSessionCommandsBlock(topLevelHelp), + parseCommandsBlock(sessionHelp) + ); + if (sessionCommands.length === 0) { + throw new Error(`no commands found in "mcpc ${SESSION} --help" output`); + } + for (const command of sessionCommands) { + sections.push( + section(3, `mcpc ${SESSION} ${command}`, runCli([SESSION, command, '--help'], homeDir)) + ); + } + + const toc = sections + .slice(1) + .map((s) => `${' '.repeat(s.level - 2)}- [\`${s.title}\`](#${s.anchor})`) + .join('\n'); + + return ` + +# mcpc command reference + +Complete \`--help\` output for every \`mcpc\` command, in the order the commands are listed +by \`mcpc --help\`. It is generated from the CLI itself, so it always matches the installed +version — run \`mcpc help \` to get the same text in your terminal. + +New to mcpc? Start with the [README](README.md), or run \`mcpc help --skill\` for the agent guide. + +${toc} + +${sections.map((s) => s.body).join('\n')}`; + } finally { + rmSync(homeDir, { recursive: true, force: true }); + } +} + +if (!existsSync(join(PROJECT_ROOT, 'dist', 'cli', 'index.js'))) { + console.error('ERROR: dist/cli/index.js not found — run "pnpm run build" first.'); + process.exit(1); +} + +const generated = build(); + +if (checkOnly) { + const current = existsSync(OUTPUT_FILE) ? readFileSync(OUTPUT_FILE, 'utf8') : ''; + if (current !== generated) { + console.error( + 'ERROR: REFERENCE.md is out of date with the CLI help output.\n' + + ' Run "pnpm run build:reference" and commit the result.' + ); + process.exit(1); + } + console.log('REFERENCE.md is up to date.'); +} else { + writeFileSync(OUTPUT_FILE, generated); + console.log(`REFERENCE.md updated (${generated.split('\n').length} lines).`); +}