backends

At least one backend is required in YAML-only mode. Admin mode may start empty so the first backend can be registered in the UI. Each id must match [A-Za-z0-9_-]{1,32} and be unique case-insensitively; uppercase letters are allowed.

Field Default Description
id none External namespace and configured ID for tool/prompt names; dots are not allowed. Uppercase letters are retained in those names, while resource/template URI authorities use the lowercase ID.
url none Required absolute URL. HTTPS is required by default; HTTP is accepted only when allow_insecure_http: true and the host is localhost or an IPv4/IPv6 loopback. Fragments are rejected.
required false Required backends affect /readyz. A runtime disconnect makes readiness 503 while the reconnect loop continues.
require_client_grant false Enforces client grants for this endpoint; requires the user portal. Personal Vault accounts must explicitly set it to true.
credentials none Vault shared / personal source; requires global vault, and excludes service oauth and conflicting static auth headers on this backend. See Vault.
required_scopes [] JWT scopes required for this backend, checked with all-of semantics; scope entries cannot contain whitespace or duplicates.
published_tools [] Exact, case-sensitive original tool names approved for use; no wildcards. Empty publishes no tools.
tool_rules [] Optional backend-local tool policies. Each rule has a match glob and at least one of effect, approval, required_scopes, or resource_rules. effect: read permits direct execution; write or an omitted classification requires approval. Matching uses Go path.Match against the original backend tool name, full-string and case-sensitive.
request_timeout inherits server.request_timeout Timeout for this backend's connection, discovery, refresh, and calls; must be positive.
rate_limit {} Shared endpoint rate, burst and concurrency limits; unlimited by default.
allow_insecure_http false Loopback-only local HTTP switch. It does not relax HTTPS requirements for server.public_url or any issuer.
headers {} Static headers added to every backend MCP HTTP request. Values support environment expansion, may not contain CR/LF, and names are case-insensitively unique. Accept, Content-Type, any Mcp-* header, and transport-managed headers such as Host, Content-Length, Connection, Proxy-Authorization, and Proxy-Authenticate are rejected.
oauth none Backend OAuth configuration. The only accepted type is client_credentials, and it cannot be combined with a static Authorization header.

oauth fields:

Field Description
type Must be client_credentials.
issuer Required absolute HTTPS OAuth issuer; its metadata issuer must match exactly.
client_id / client_secret Required; preferably supplied only through ${...} environment variables.
scopes Scopes requested from the backend OAuth token endpoint. These are independent of required_scopes, which gate the JWT presented to MCPHub.

Backend OAuth discovery and token requests do not receive the backend's static headers; data-plane requests do and automatically reuse/refresh the client-credentials token. Discovery probes RFC 8414/OIDC metadata for an exact issuer and token_endpoint only; it does not require interactive authorization or PKCE metadata. OAuth metadata responses are capped at 1 MiB. Backend and OIDC HTTP clients do not follow redirects.

Optional service-account OAuth fragment, excluded from the base template: add this entry under backends only when connecting such a service and set all 4 variables for it. required: false only changes connection-failure handling. Tools still require review and explicit publication.

- id: crm
  url: ${MCPHUB_CRM_BACKEND_URL}
  required: false
  required_scopes: [mcp:crm.read]
  published_tools: []
  oauth:
    type: client_credentials
    issuer: ${MCPHUB_CRM_OAUTH_ISSUER}
    client_id: ${MCPHUB_CRM_CLIENT_ID}
    client_secret: ${MCPHUB_CRM_CLIENT_SECRET}
    scopes: [crm.read]