diff --git a/.github/upstream-projects.yaml b/.github/upstream-projects.yaml index 74df9cb3..f1195f4d 100644 --- a/.github/upstream-projects.yaml +++ b/.github/upstream-projects.yaml @@ -44,7 +44,7 @@ projects: - id: toolhive repo: stacklok/toolhive - version: v0.49.0 + version: v0.50.0 # toolhive is a monorepo covering the CLI, the Kubernetes # operator, and the vMCP gateway. It also introduces cross- # cutting features that land in concepts/, integrations/, diff --git a/docs/toolhive/guides-cli/ai-plugins.mdx b/docs/toolhive/guides-cli/ai-plugins.mdx index b860a8eb..0c1baff7 100644 --- a/docs/toolhive/guides-cli/ai-plugins.mdx +++ b/docs/toolhive/guides-cli/ai-plugins.mdx @@ -327,6 +327,14 @@ them: thv ai-plugin sync --project-root . --adopt ``` +When adopting a key-pair-signed plugin, pass `--public-key` so ToolHive can +verify the installed content offline against the matching cosign public key +before recording the trust anchor: + +```bash +thv ai-plugin sync --project-root . --adopt --public-key ./cosign.pub +``` + Use `--prune` to remove installs that are no longer in the lock file. See the @@ -349,13 +357,21 @@ the new source, then repeat the command with `--allow-ref-change` if you intend to permit that repository move. ToolHive prompts before installing the planned changes; pass `--yes` in non-interactive environments. -Plugins pinned to an immutable reference (an OCI digest or a full Git commit -hash) are reported as not upgradable, because there is nothing newer to resolve -to. +Plugins pinned to a full Git commit hash are reported as not upgradable, because +there is nothing newer to resolve to. OCI-digest-pinned content is also +immutable, but its separately attached signatures can still change: pair +`--allow-signer-change` with `--public-key ` to re-anchor trust when +the publisher rotates their cosign key. The digest stays pinned and the content +is unchanged; only the recorded verification anchor is updated. + +```bash +thv ai-plugin upgrade my-plugin --project-root . \ + --allow-signer-change --public-key ./cosign-new.pub +``` Use `--preview` to see what would change without persisting anything, or -`--fail-on-changes` as a CI freshness gate that reports pending upgrades without -installing them. +`--fail-on-changes` as a CI freshness gate that reports content and trust +changes without installing them. See the [`thv ai-plugin upgrade` command reference](../reference/cli/thv_ai-plugin_upgrade.md) diff --git a/docs/toolhive/guides-cli/skills-management.mdx b/docs/toolhive/guides-cli/skills-management.mdx index 34fb5074..81ebd578 100644 --- a/docs/toolhive/guides-cli/skills-management.mdx +++ b/docs/toolhive/guides-cli/skills-management.mdx @@ -272,6 +272,14 @@ them: thv skill sync --project-root . --adopt ``` +When adopting a key-pair-signed skill, pass `--public-key` so ToolHive can +verify the installed content offline against the matching cosign public key +before recording the trust anchor: + +```bash +thv skill sync --project-root . --adopt --public-key ./cosign.pub +``` + Use `--prune` to remove installs that are no longer in the lock file. See the [`thv skill sync` command reference](../reference/cli/thv_skill_sync.md) @@ -293,13 +301,21 @@ the new source, then repeat the command with `--allow-ref-change` if you intend to permit that repository move. ToolHive prompts before installing the planned changes; pass `--yes` in non-interactive environments. -Skills pinned to an immutable reference (an OCI digest or a full Git commit -hash) are reported as not upgradable, because there is nothing newer to resolve -to. +Skills pinned to a full Git commit hash are reported as not upgradable, because +there is nothing newer to resolve to. OCI-digest-pinned content is also +immutable, but its separately attached signatures can still change: pair +`--allow-signer-change` with `--public-key ` to re-anchor trust when +the publisher rotates their cosign key. The digest stays pinned and the content +is unchanged; only the recorded verification anchor is updated. + +```bash +thv skill upgrade my-skill --project-root . \ + --allow-signer-change --public-key ./cosign-new.pub +``` Use `--preview` to see what would change without persisting anything, or -`--fail-on-changes` as a CI freshness gate that reports pending upgrades without -installing them. +`--fail-on-changes` as a CI freshness gate that reports content and trust +changes without installing them. See the [`thv skill upgrade` command reference](../reference/cli/thv_skill_upgrade.md) diff --git a/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx b/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx index d9134eaf..22afe1e8 100644 --- a/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx +++ b/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx @@ -1081,6 +1081,47 @@ refresh-token state), add `prompt: 'consent'` alongside `access_type: 'offline'`. Google then shows the consent screen on every login and re-issues a refresh token each time. +### Upstream-specific token-request parameters + +Some upstream authorization servers enforce +[RFC 8707 resource indicators](https://datatracker.ietf.org/doc/html/rfc8707) on +token requests, not only on authorization requests: the code exchange and +refresh are rejected with `invalid_target` unless the `resource` parameter is +also present in the token endpoint's POST form body. +`additionalAuthorizationParams` only reaches the authorize URL, so against such +a provider the embedded auth server passes authorization and then fails at the +code exchange. + +Set `additionalTokenParams` on the same `oidcConfig` or `oauth2Config` to add +form-body parameters to every token request (both the authorization-code +exchange and refresh): + +```yaml title="MCPExternalAuthConfig: token-request resource indicator" +upstreamProviders: + - name: mcp-authz + type: oauth2 + oauth2Config: + authorizationEndpoint: 'https://as.example.com/oauth/authorize' + tokenEndpoint: 'https://as.example.com/oauth/token' + clientId: '' + clientSecretRef: + name: upstream-idp-secret + key: client-secret + scopes: + - openid + additionalAuthorizationParams: + resource: 'https://api.example.com' + additionalTokenParams: + resource: 'https://api.example.com' +``` + +The following framework-managed parameters are reserved and rejected at +admission: `grant_type`, `code`, `redirect_uri`, `client_id`, `client_secret`, +`code_verifier`, `refresh_token`, `scope`, `client_assertion`, and +`client_assertion_type`. A `resource` entry is additionally validated as an +absolute URI with no fragment component so a malformed value fails at admission +rather than at first login. The map is capped at 16 entries. + ### Default callback URL for upstream providers When you omit `redirectUri` from an upstream provider's `oidcConfig` or diff --git a/docs/toolhive/guides-vmcp/configuration.mdx b/docs/toolhive/guides-vmcp/configuration.mdx index 0e936e23..fc186769 100644 --- a/docs/toolhive/guides-vmcp/configuration.mdx +++ b/docs/toolhive/guides-vmcp/configuration.mdx @@ -269,8 +269,27 @@ spec: perWorkload: slow-backend: 60s fast-backend: 10s + + # Optional cap on how long session initialization waits for a single + # backend to connect and hand back its capabilities. Unset by default. + backendInit: 5s ``` +`backendInit` bounds session initialization independently of request timeouts. +An explicit value is authoritative: it applies even when a workload's request +timeout is longer, so a heavy query wanting a 60s budget doesn't also grant 60s +to the handshake. Leave it unset unless a backend can stall the handshake. + +Set it when a backend accepts the persistent notification-stream subscription +that vMCP opens during `initialize` and then never services it. That case +typically arises with a stateless backend that requires per-user auth, where +vMCP's unauthenticated health probe can't classify the backend and falls back to +the persistent-connection path. A short value here lets session init fail fast, +which `partialFailureMode: best_effort` turns into a usable session. Pair it +with +[`operational.listChanged.disabledWorkloads`](#exclude-backends-from-live-list_changed-propagation) +to also skip subscribing to that backend's notification stream. + :::info[Changed in v0.45.0] `operational.timeouts.default` and `perWorkload` values are now applied to @@ -321,6 +340,33 @@ For detailed backend health monitoring, see [Verify backend status](./backend-discovery.mdx#verify-backend-status) in the Backend discovery guide. +### Exclude backends from live list_changed propagation + +vMCP subscribes to every backend's `list_changed` notification stream during +session initialization so tool, prompt, and resource list changes propagate +live. A backend that accepts the subscribe and then never services it stalls the +handshake, and clients with their own connect timeout give up first. Configure +`operational.listChanged` when a specific backend behaves this way so its +notification stream can be skipped while the rest stay subscribed: + +```yaml +spec: + config: + operational: + listChanged: + # Turn propagation on or off for every backend. Defaults to true. + enabled: true + # Backends to exclude while leaving the rest subscribed. + disabledWorkloads: + - grafana-cloud-mcp +``` + +An excluded backend loses live propagation only: its tools remain aggregated and +callable, and its list refreshes on the next session. Prefer `disabledWorkloads` +over setting `enabled: false` when a single backend misbehaves. Combine this +with [`operational.timeouts.backendInit`](#timeouts) so session initialization +also fails fast if the same backend stalls the handshake. + ## Forward client headers to backends By default, vMCP opens a fresh request to each backend and sends only its own diff --git a/docs/toolhive/reference/cli/thv_ai-plugin_sync.md b/docs/toolhive/reference/cli/thv_ai-plugin_sync.md index 1f38c6ea..7160ee5a 100644 --- a/docs/toolhive/reference/cli/thv_ai-plugin_sync.md +++ b/docs/toolhive/reference/cli/thv_ai-plugin_sync.md @@ -41,6 +41,7 @@ thv ai-plugin sync [flags] -h, --help help for sync --project-root string Project root path (default: auto-detected from the current directory) --prune Remove installs no longer present in the lock file + --public-key string Path to the cosign public key used to verify key-pair-signed plugins during --adopt --yes Skip the confirmation prompt (required when not running interactively) ``` diff --git a/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md b/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md index 27bc6105..ce8aaefd 100644 --- a/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md +++ b/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md @@ -17,8 +17,9 @@ Upgrade project plugins to newer pinned content Re-resolve a project's lock entries and install newer content where available. -Plugins pinned to an immutable reference (an OCI digest or a full git commit -hash) are reported not-upgradable — there is nothing newer to resolve to. +Plugins pinned to a full git commit hash are not upgradable. OCI digest content +is also immutable, but --allow-signer-change --public-key can evaluate its +separately attached signatures for a trust-only update. Use --preview to see what would change without persisting anything (OCI sources are still fetched into the local artifact store to compare digests), and --allow-ref-change to permit the artifact moving to a different @@ -46,6 +47,7 @@ thv ai-plugin upgrade [plugin-name...] [flags] -h, --help help for upgrade --preview Report what would change without persisting anything (OCI sources are still fetched to compare digests) --project-root string Project root path (default: auto-detected from the current directory) + --public-key string Path to a cosign public key proposed as the replacement trust anchor (requires --allow-signer-change) --yes Skip the confirmation prompt (required when not running interactively) ``` diff --git a/docs/toolhive/reference/cli/thv_skill_sync.md b/docs/toolhive/reference/cli/thv_skill_sync.md index d2f2f39b..e85b18c6 100644 --- a/docs/toolhive/reference/cli/thv_skill_sync.md +++ b/docs/toolhive/reference/cli/thv_skill_sync.md @@ -41,6 +41,7 @@ thv skill sync [flags] -h, --help help for sync --project-root string Project root path (default: auto-detected from the current directory) --prune Remove installs no longer present in the lock file + --public-key string Path to the cosign public key used to verify key-pair-signed skills during --adopt --yes Skip the confirmation prompt (required when not running interactively) ``` diff --git a/docs/toolhive/reference/cli/thv_skill_upgrade.md b/docs/toolhive/reference/cli/thv_skill_upgrade.md index 75076c28..87694703 100644 --- a/docs/toolhive/reference/cli/thv_skill_upgrade.md +++ b/docs/toolhive/reference/cli/thv_skill_upgrade.md @@ -17,8 +17,9 @@ Upgrade project skills to newer pinned content Re-resolve a project's lock entries and install newer content where available. -Skills pinned to an immutable reference (an OCI digest or a full git commit -hash) are reported not-upgradable — there is nothing newer to resolve to. +Skills pinned to a full git commit hash are not upgradable. OCI digest content +is also immutable, but --allow-signer-change --public-key can evaluate its +separately attached signatures for a trust-only update. Use --preview to see what would change without persisting anything (OCI sources are still fetched into the local artifact store to compare digests), and --allow-ref-change to permit the artifact moving to a different @@ -27,9 +28,9 @@ this guard blocks). --fail-on-changes evaluates the same plan and never installs: it is a CI freshness gate. -Unless --preview is set, upgrade prompts for confirmation before installing — -skill content is a set of AI-followed instructions. Pass --yes to skip the -prompt (required in non-interactive contexts such as CI). +Unless --preview or --fail-on-changes is set, upgrade prompts for confirmation +before installing. Skill content is a set of AI-followed instructions. Pass +--yes to skip the prompt (required in non-interactive contexts such as CI). ``` thv skill upgrade [skill-name...] [flags] @@ -46,6 +47,7 @@ thv skill upgrade [skill-name...] [flags] -h, --help help for upgrade --preview Report what would change without persisting anything (OCI sources are still fetched to compare digests) --project-root string Project root path (default: auto-detected from the current directory) + --public-key string Path to a cosign public key proposed as the replacement trust anchor (requires --allow-signer-change) --yes Skip the confirmation prompt (required when not running interactively) ``` diff --git a/static/api-specs/toolhive-api.yaml b/static/api-specs/toolhive-api.yaml index 39c8a943..ebdf9f9d 100644 --- a/static/api-specs/toolhive-api.yaml +++ b/static/api-specs/toolhive-api.yaml @@ -331,6 +331,14 @@ components: authorization requests. Useful for provider-specific parameters like Google's access_type=offline. type: object + additional_token_params: + additionalProperties: + type: string + description: |- + AdditionalTokenParams are extra form-body parameters to include in + token requests (authorization code exchange and refresh). Useful for + providers that enforce RFC 8707 resource indicators on token requests. + type: object allow_private_ips: description: |- AllowPrivateIPs permits the upstream provider's HTTP client to connect to @@ -418,6 +426,14 @@ components: authorization requests. Useful for provider-specific parameters like Google's access_type=offline. type: object + additional_token_params: + additionalProperties: + type: string + description: |- + AdditionalTokenParams are extra form-body parameters to include in + token requests (authorization code exchange and refresh). Useful for + providers that enforce RFC 8707 resource indicators on token requests. + type: object allow_private_ips: description: |- AllowPrivateIPs permits the OIDC discovery and token HTTP clients to @@ -579,6 +595,17 @@ components: via RFC 8693 token exchange. Specified as a Go duration string (e.g., "15m"). If empty, defaults to 15 minutes. type: string + device_flow_enabled: + description: |- + DeviceFlowEnabled enables the RFC 8628 OAuth 2.0 Device Authorization + Grant: POST /oauth/device_authorization is mounted and + urn:ietf:params:oauth:grant-type:device_code is registered at the + token endpoint and advertised in discovery. The minimum polling + interval (RFC 8628 Section 3.5) is fixed at + oauthserver.DefaultDeviceCodeInterval; this is a deliberate + simplification to keep this config surface minimal — a future + increment may add an override. + type: boolean disable_upstream_token_injection: description: |- DisableUpstreamTokenInjection prevents the upstream swap middleware from being added. @@ -2414,8 +2441,8 @@ components: type: string new_digest: description: |- - NewDigest is the digest the source currently resolves to. Equal to - OldDigest when Status is UpgradeStatusUpToDate. + NewDigest is the digest the source currently resolves to. It may equal + OldDigest when only the resolved reference or trust material changed. type: string new_resolved_reference: description: NewResolvedReference is the new resolvedReference when it changed. @@ -2433,6 +2460,11 @@ components: $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_skills.FailureReason' status: $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_skills.UpgradeStatus' + trust_anchor_changed: + description: |- + TrustAnchorChanged reports that the operation selected a different + verified provenance or unsigned trust state than the lock recorded. + type: boolean type: object github_com_stacklok_toolhive_pkg_skills.UpgradeResult: properties: @@ -2448,6 +2480,7 @@ components: enum: - upgraded - up-to-date + - trust-updated - not-upgradable - ref-change-blocked - signer-change-blocked @@ -2456,6 +2489,7 @@ components: x-enum-varnames: - UpgradeStatusUpgraded - UpgradeStatusUpToDate + - UpgradeStatusTrustUpdated - UpgradeStatusNotUpgradable - UpgradeStatusRefChangeBlocked - UpgradeStatusSignerChangeBlocked @@ -3830,6 +3864,9 @@ components: description: Prune removes project-scoped plugins installed but not present in the lock file type: boolean + public_key: + description: PublicKey supplies the cosign public key for key-signed adoption. + type: string type: object pkg_api_v1.syncSkillsRequest: description: Request to restore a project's installed skills to match its lock @@ -3864,6 +3901,9 @@ components: description: Prune removes project-scoped skills installed but not present in the lock file type: boolean + public_key: + description: PublicKey supplies the cosign public key for key-signed adoption. + type: string type: object pkg_api_v1.toolOverride: description: Tool override @@ -4059,6 +4099,10 @@ components: description: ProjectRoot is the project root path whose lock file should be upgraded type: string + public_key: + description: PublicKey proposes a cosign public key as the replacement trust + anchor. + type: string type: object pkg_api_v1.upgradeRequest: description: Request to apply an available upgrade to a workload. All fields @@ -4103,8 +4147,8 @@ components: type: array uniqueItems: false fail_on_changes: - description: FailOnChanges exits with an error when any mutable source would - upgrade + description: FailOnChanges reports content and trust changes without applying + them type: boolean names: description: Names restricts the upgrade to specific skill names. Empty @@ -4121,6 +4165,10 @@ components: description: ProjectRoot is the project root path whose lock file should be upgraded type: string + public_key: + description: PublicKey proposes a cosign public key as the replacement trust + anchor. + type: string type: object pkg_api_v1.validatePluginRequest: description: Request to validate a plugin definition diff --git a/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json b/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json index 58c99e66..02e37e45 100644 --- a/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json +++ b/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json @@ -1068,7 +1068,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { @@ -1255,6 +1255,14 @@ "maxProperties": 16, "type": "object" }, + "additionalTokenParams": { + "additionalProperties": { + "type": "string" + }, + "description": "AdditionalTokenParams are extra form-body parameters to include in\ntoken requests (authorization code exchange and refresh) sent to the\nupstream provider's token endpoint.\nThis is useful for providers that enforce RFC 8707 resource indicators\non token requests, where the resource parameter must accompany the code\nexchange and refresh, not only the authorization request.\nFramework-managed parameters (grant_type, code, redirect_uri, client_id,\nclient_secret, code_verifier, refresh_token, scope) are not allowed.", + "maxProperties": 16, + "type": "object" + }, "allowPrivateIPs": { "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). Use only when the upstream is\nhosted inside the same cluster and has no public endpoint. HTTP-scheme\nrestrictions are unchanged — HTTPS is still required for non-localhost\nhosts unless InsecureAllowHTTP is set. Defaults to false.", "type": "boolean" @@ -1271,7 +1279,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { @@ -1547,6 +1555,14 @@ "maxProperties": 16, "type": "object" }, + "additionalTokenParams": { + "additionalProperties": { + "type": "string" + }, + "description": "AdditionalTokenParams are extra form-body parameters to include in\ntoken requests (authorization code exchange and refresh) sent to the\nupstream provider's token endpoint.\nThis is useful for providers that enforce RFC 8707 resource indicators\non token requests, where the resource parameter must accompany the code\nexchange and refresh, not only the authorization request.\nFramework-managed parameters (grant_type, code, redirect_uri, client_id,\nclient_secret, code_verifier, refresh_token, scope) are not allowed.", + "maxProperties": 16, + "type": "object" + }, "allowPrivateIPs": { "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). Use only when the upstream is\nhosted inside the same cluster and has no public endpoint.", "type": "boolean" @@ -1558,7 +1574,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { diff --git a/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json b/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json index 9c83e5ee..82bc7225 100644 --- a/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json +++ b/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json @@ -24,7 +24,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { diff --git a/static/api-specs/toolhive-crds/mcpserverentries.schema.json b/static/api-specs/toolhive-crds/mcpserverentries.schema.json index 8205f970..179474b7 100644 --- a/static/api-specs/toolhive-crds/mcpserverentries.schema.json +++ b/static/api-specs/toolhive-crds/mcpserverentries.schema.json @@ -26,7 +26,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { diff --git a/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json b/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json index 9c5d2115..de052834 100644 --- a/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json +++ b/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json @@ -24,7 +24,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { diff --git a/static/api-specs/toolhive-crds/virtualmcpservers.schema.json b/static/api-specs/toolhive-crds/virtualmcpservers.schema.json index 42c4b16e..e8149e0e 100644 --- a/static/api-specs/toolhive-crds/virtualmcpservers.schema.json +++ b/static/api-specs/toolhive-crds/virtualmcpservers.schema.json @@ -959,7 +959,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { @@ -1146,6 +1146,14 @@ "maxProperties": 16, "type": "object" }, + "additionalTokenParams": { + "additionalProperties": { + "type": "string" + }, + "description": "AdditionalTokenParams are extra form-body parameters to include in\ntoken requests (authorization code exchange and refresh) sent to the\nupstream provider's token endpoint.\nThis is useful for providers that enforce RFC 8707 resource indicators\non token requests, where the resource parameter must accompany the code\nexchange and refresh, not only the authorization request.\nFramework-managed parameters (grant_type, code, redirect_uri, client_id,\nclient_secret, code_verifier, refresh_token, scope) are not allowed.", + "maxProperties": 16, + "type": "object" + }, "allowPrivateIPs": { "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). Use only when the upstream is\nhosted inside the same cluster and has no public endpoint. HTTP-scheme\nrestrictions are unchanged — HTTPS is still required for non-localhost\nhosts unless InsecureAllowHTTP is set. Defaults to false.", "type": "boolean" @@ -1162,7 +1170,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { @@ -1438,6 +1446,14 @@ "maxProperties": 16, "type": "object" }, + "additionalTokenParams": { + "additionalProperties": { + "type": "string" + }, + "description": "AdditionalTokenParams are extra form-body parameters to include in\ntoken requests (authorization code exchange and refresh) sent to the\nupstream provider's token endpoint.\nThis is useful for providers that enforce RFC 8707 resource indicators\non token requests, where the resource parameter must accompany the code\nexchange and refresh, not only the authorization request.\nFramework-managed parameters (grant_type, code, redirect_uri, client_id,\nclient_secret, code_verifier, refresh_token, scope) are not allowed.", + "maxProperties": 16, + "type": "object" + }, "allowPrivateIPs": { "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). Use only when the upstream is\nhosted inside the same cluster and has no public endpoint.", "type": "boolean" @@ -1449,7 +1465,7 @@ "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { - "description": "The key to select.", + "description": "The key to select from the ConfigMap's Data field.\nKeys in the BinaryData field are not currently propagated to container env vars.", "type": "string" }, "name": { @@ -2526,6 +2542,24 @@ }, "type": "object" }, + "listChanged": { + "description": "ListChanged configures live list_changed propagation from backends.", + "properties": { + "disabledWorkloads": { + "description": "DisabledWorkloads names backends to exclude while leaving the rest\nsubscribed. Prefer this over Enabled when a single backend misbehaves.", + "items": { + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, + "enabled": { + "description": "Enabled turns propagation on or off for every backend. Defaults to true.", + "type": "boolean" + } + }, + "type": "object" + }, "logLevel": { "description": "LogLevel sets the logging level for the Virtual MCP server.\nThe only valid value is \"debug\" to enable debug logging.\nWhen omitted or empty, the server uses info level logging.", "enum": [ @@ -2536,6 +2570,11 @@ "timeouts": { "description": "Timeouts configures timeout settings.", "properties": { + "backendInit": { + "description": "BackendInit caps how long session initialization waits for a single\nbackend to connect and hand back its capabilities. Unlike Default, which\nonly ever extends that deadline, an explicit BackendInit is authoritative:\nit bounds session init even when a workload's request timeout is longer.\n\nLeave it unset unless a backend can stall the handshake. It exists for\nbackends that neither answer nor fail promptly: a stateless MCP server\nthat requires per-user auth cannot be classified by the unauthenticated\nhealth probe, so vMCP opens the persistent connection its Modern skip\npath would otherwise avoid, and that connection can hang until the\ndeadline. Clients with their own connect timeout give up first, and\nbecause they never complete a call, the revision cache never warms and\nthe next session repeats it. A few seconds here lets session init fail\nfast, which partialFailureMode: best_effort turns into a usable session.", + "pattern": "^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$", + "type": "string" + }, "default": { "default": "30s", "description": "Default is the default timeout for backend requests.",