# description
Single generator-of-record for the prebuilt MCP-server marketplace. One TOML, three projections: the browser catalog (catalog.gen.ts), the vendor/BAA rows (vendors.toml class="mcp"), and the perimeter egress hosts (perimeter.firewall runtime + OAuth + DCR blocks).

Projections:
  • clients/web/surfaces/app/src/data/mcp/catalog.gen.ts — MCP_CATALOG + catalogForServerName
  • contracts/trust/vendors/vendors.toml — @mcpgen:vendors-runtime / vendors-oauth spliced blocks
  • infra/network/spec/perimeter.firewall — @mcpgen:firewall-runtime / firewall-oauth / firewall-dcr spliced blocks

Cross-checks:
  • infra/network/tooling/checks/perimeter/vendors.py — tri-directional bijection (catalog ↔ firewall ↔ vendors)
  • scripts/codegen/forward/trust/mcp/compile.py --check — byte-parity drift gate

Entry order is significant — it is the marketplace display order.

# $defs.entry.properties.id.description
Stable card id (unique across the catalog).

# $defs.entry.properties.server_name.description
Stable mcp_servers.name Billy writes to the DB — the install detector.

# $defs.entry.properties.brand.description
Brand glyph key (resolved by data/mcp/brandGlyphs.tsx).

# $defs.entry.properties.category.description
One of the 7 category ids declared in data/mcp/categories.ts.

# $defs.entry.properties.url.description
Public hosted MCP endpoint. The egress runtime host is the URL hostname.

# $defs.entry.properties.auth_mode.description
none: public; oauth: server hosts the dance (backend brokers token exchange); token: user pastes a PAT; api-key: user pastes a key in a custom header.

# $defs.entry.properties.auth_header.description
Header carrying the secret (default Authorization). Present for token/api-key entries that override the default.

# $defs.entry.properties.auth_prefix.description
Prefix prepended to the secret (e.g. 'Bearer ', or '' for a raw value).

# $defs.entry.properties.auth_hint.description
Install-dialog help text shown when collecting the credential.

# $defs.entry.properties.credential_url.description
Where the user issues/finds the credential.

# $defs.entry.properties.prompt_hints.description
Sample prompts the agent can satisfy once installed.

# $defs.entry.properties.featured.description
Featured card (highlighted in the marketplace).

# $defs.entry.properties.capability.description
Optional capability tag (ADR-250). 'computer_use' marks a remote computer-use / browser-automation server so the marketplace can group it and Billy's control doctrine knows it overlaps the native @control surface (prefer native on a paired machine; remote MCP for unreachable surfaces).

# $defs.entry.properties.vendor_name.description
vendors.toml class="mcp" runtime row name. Required unless vendor_ref is set.

# $defs.entry.properties.purpose.description
vendors.toml purpose limitation for the runtime row. Required unless vendor_ref is set.

# $defs.entry.properties.data_classes.description
Data classes the LLM can transmit through the user's tools. Required unless vendor_ref is set.

# $defs.entry.properties.pii_allowed.description
vendors.toml pii_allowed for the runtime row (phi_allowed is always false for MCP). Required unless vendor_ref is set.

# $defs.entry.properties.byok_only.description
If true, the user owns the upstream relationship (BYOK passthrough).

# $defs.entry.properties.baa_note.description
vendors.toml runtime row baa.notes (status='none', eligible=false). Required unless vendor_ref is set.

# $defs.entry.properties.firewall_note.description
AI-egress perimeter.firewall host note. Multi-line strings are emitted as a folded block scalar. Always present, even when vendor_ref is set.

# $defs.entry.properties.vendor_ref.description
When set, emit NO class="mcp" vendor row — the runtime host reuses an existing non-MCP vendor row by this host key. The AI-egress firewall runtime host is still emitted.

# $defs.oauth.description
The OAuth posture for this vendor — both the endpoints the backend engine dials and the trust rows that admission depends on.

Endpoints are declared as full URLs and every egress *host* is derived from them (as the runtime host is derived from `url`), so a host and its URL cannot disagree. Whether a derived host gets a vendors.toml row and a perimeter.firewall entry is governed by the presence of that host's `*_firewall_note` / `*_baa_note`: the note is the operator's declaration that this host needs its own egress admission. An authorize endpoint the user's browser dials needs no backend egress and so carries no note.

# $defs.oauth.properties.authorize_url.description
OAuth 2.x authorization endpoint — where the user's browser is redirected to consent.

# $defs.oauth.properties.token_url.description
OAuth 2.x token endpoint the backend dials for code → token and for refresh. Its host is the backend-egress token host.

# $defs.oauth.properties.registration_url.description
RFC-7591 dynamic-client-registration endpoint. Presence is what makes a vendor DCR-capable: with it the engine registers a client per (provider, frontend origin) and caches the credentials; without it the vendor needs pre-registered credentials.

# $defs.oauth.properties.scopes.description
Scopes requested at authorize time, one per element. The generator joins them with `scope_join`.

# $defs.oauth.properties.scope_join.description
Separator the vendor expects in the authorize `scope` parameter. Defaults to a space (RFC 6749); Notion wants a comma.

# $defs.oauth.properties.client_auth.description
How the client authenticates at the token endpoint. `secret` is a confidential client (client_secret required). `none` is a public client authenticating by PKCE alone — the posture for a vendor whose `token_endpoint_auth_methods_supported` includes "none" (Spotify), where requiring a secret would fail closed against a credential the vendor never issues.

# $defs.oauth.properties.pre_registered.description
Credentials come from the environment (Secret Manager) rather than DCR. Mutually exclusive with registration_url — a vendor either registers dynamically or is registered ahead of time.

# $defs.oauth.properties.env_prefix.description
Env-var basename for a pre-registered vendor: the engine reads MCP_OAUTH_<env_prefix>_CLIENT_ID (and _CLIENT_SECRET unless client_auth is "none"). Required when pre_registered is set.

# $defs.oauth.properties.prompt_param.description
Value for the vendor's consent re-prompt parameter (`prompt=consent` for Google-style flows).

# $defs.oauth.properties.token_baa_note.description
vendors.toml OAuth row baa.notes for the token host. Emitting the row requires this.

# $defs.oauth.properties.token_firewall_note.description
backend-egress perimeter.firewall note for the token host. Emitting the egress entry requires this.

# $defs.oauth.properties.authorize_baa_note.description
vendors.toml OAuth row baa.notes for the authorize host (derived from authorize_url). Only for a consent host the backend itself must reach.

# $defs.oauth.properties.authorize_firewall_note.description
backend-egress perimeter.firewall note for the authorize host. Only for a consent host the backend itself must reach.

# $defs.oauth.properties.dcr_firewall_note.description
backend-egress perimeter.firewall note for the DCR host (derived from registration_url). Omit when the DCR host is already admitted as the token host.

# $defs.oauth.properties.shared_host.description
The OAuth hosts are shared with a hand-authored non-MCP flow (github.com, which also backs the standalone GitHub login) — emit no vendors.toml row and no firewall entry for them, while the engine still reads the endpoints declared here.