Skip to content
Install

docs/catalog-rest.md

Catalog REST compatibility (B83)

v1 catalog and control routes over the opt-in adapter.

The opt-in HTTP adapter exposes v1 catalog/control routes through native daemon services and additive catalog.rest commands. The listener remains off by default and loopback-only with existing token auth. Every route below requires a full token, including catalogs: extensions can load code, MCP discovery can contact services, and tool/command catalogs contain user content. None is in READ_ONLY_COMMANDS. Directory/workspace routing, size limits, CORS and revocation use the existing HTTP adapter.

Method and pathResult
GET /config/providers{providers, default} for configured native/plugin providers
PUT/DELETE /auth/:providerIDtrue; import/remove one private credential without removing models/settings
GET /experimental/tool?provider=ID&model=ID{id, description, parameters}[], real native/project schemas, permissions applied
GET /experimental/tool/idseligible native/project tool IDs
GET /commandproject/user/extension/MCP command entries with template
GET /agent, /skillnative agents; skills include location pointing to SKILL.md
GET /lsp, /formatteractive language-server roots/state; enabled formatter registry
GET /mcpname-keyed {status: connected/disabled/needs_auth/failed/pending}; pending includes expiresAt
POST /mcpstage native project config for local /mcp approval; HTTP 202 pending status map, no connection
POST /mcp/:name/auth{authorizationUrl, oauthState}; PKCE flow, caller opens URL
POST /mcp/:name/auth/callback{code} completes pending flow, restarts server and returns status
POST /mcp/:name/auth/authenticatewaits for an existing flow; otherwise HTTP 202 plus authorization URL
DELETE /mcp/:name/authforget registration/tokens and disconnect; {success: true}
POST /mcp/:name/connect, /disconnecttrue; disconnect suppresses lazy discovery until explicit reconnect
GET /provider{all, default, connected} with native/preset/plugin model metadata
GET /provider/authprovider-keyed indexed {type, label, prompts?}[]
POST /provider/:providerID/oauth/authorize{method, inputs?} → {url, method, instructions}
POST /provider/:providerID/oauth/callback{method, code?} → true, only for this project's pending method
GET /experimental/resourcename-keyed MCP resources with client server name (B47 bridge)

The existing POST /command framed-command bridge is unchanged. client.restCatalog(directory, input) exposes native catalog control without importing runtime schemas into CLI startup. OpenAPI includes both bridges and strict credential, OAuth and local/remote MCP body schemas. HTTP errors are sanitized; credentials never appear in catalogs/replies. Stores retain private atomic writes. Unknown MCP names return 404; unavailable adapters 501.

Integration MCP requests persist across restart, expire in 24 hours and share a daemon-wide cap of 10. In local /mcp, review command/args/environment names or URL, then a approves and x rejects. Peers cannot send mcp.decide. REST edits suspend the existing client and require a new review; MCP config PATCH requests follow the same conservative gate. See pending approval.

Compatibility decisions: retain v1 paths/envelopes with native metadata, without inventing model cost/context limits; MCP additions persist in project .mendcode/mcp.json rather than donor process-only config. Disconnect is process-local and never changes the config's enabled flag. OAuth is explicit, opens no browser and uses existing loopback callbacks, PKCE/state validation and one-use code exchange. Authenticate returns 202 when human authorization is needed; pending waits are cancellable and bounded to 55 seconds. Indexed methods map to native browser/device ChatGPT, Copilot and registered plugin flows, rather than inventing provider adapters.

Credential import supports API keys for configured/preset providers and registered plugins, ChatGPT OAuth, and registered plugin OAuth. R9 adds, through the existing provider stores (no network call is made by an import): API metadata for providers that have a native equivalent (Azure resourceName, Cloudflare Workers AI accountId, Cloudflare AI Gateway accountId/gatewayId; any other key or provider is a 400 and nothing is saved); wellknown credentials, stored privately in provider-metadata-auth.json (0600) and resolved by a provider's apiKeyEnv, which is set on a configured provider of that id (never exported to the process environment); and manual github-copilot OAuth (also github-copilot-enterprise) into the Copilot credential store, with enterpriseUrl mapped to https://copilot-api.<domain> (HTTPS domain, or a loopback origin for local fakes; credentials, paths and queries are refused) and the refresh token dropped for enterprise since it cannot refresh against another issuer. Enterprise OAuth for ChatGPT/OpenAI and plugin credentials with metadata still return 501 without mutation. DELETE also drops a stored well-known credential. Environment credentials survive DELETE because this endpoint owns only v2's private stores. External-engine tool schemas are owned by that engine and return 501. Real provider/MCP service acceptance remains unverified; tests inject only local fakes.

The existing bordered /mcps grid displays native state events, including temporary disconnect and OAuth. It no longer claims every disabled server was disabled in config or adds no output filler. Headers and compact stacking stay intact. Copy confirmation lives in the header, without overlaying a panel, and settled authorization clears obsolete URLs. Frames: bun scripts/render-frames.ts .agents-frames/B83 --b83 100x30 180x50.