diff --git a/.github/upstream-projects.yaml b/.github/upstream-projects.yaml index 86d25ae4..83da434e 100644 --- a/.github/upstream-projects.yaml +++ b/.github/upstream-projects.yaml @@ -64,7 +64,7 @@ projects: - id: toolhive repo: stacklok/toolhive - version: v0.57.0 + version: v0.58.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/concepts/embedded-auth-server.mdx b/docs/toolhive/concepts/embedded-auth-server.mdx index 16245ef4..3a14f280 100644 --- a/docs/toolhive/concepts/embedded-auth-server.mdx +++ b/docs/toolhive/concepts/embedded-auth-server.mdx @@ -216,6 +216,17 @@ If the refresh token is also expired or has been revoked by the upstream provider, ToolHive returns a `401` response, prompting re-authentication through the OAuth flow. +ToolHive also checks the upstream credential when an MCP client redeems its own +ToolHive refresh token. Before issuing new tokens, the embedded authorization +server reads the session's stored upstream tokens and refreshes any that have +expired. If the upstream credential is no longer usable (for example, the +provider rejects the refresh with `invalid_grant`, or no upstream refresh token +is stored), the token endpoint responds with HTTP `400` and `invalid_grant`. +This sends the client through a full authorization instead of looping on +refreshed tokens that still fail with `401`. When the outcome is uncertain, such +as a network error, a `5xx` or `429` response from the provider, or a check that +takes longer than 10 seconds, ToolHive issues the new tokens. + ## Key characteristics - **In-process execution:** The authorization server runs within the ToolHive diff --git a/docs/toolhive/guides-vmcp/delegate-agent-identity.mdx b/docs/toolhive/guides-vmcp/delegate-agent-identity.mdx index 373a9112..d522798d 100644 --- a/docs/toolhive/guides-vmcp/delegate-agent-identity.mdx +++ b/docs/toolhive/guides-vmcp/delegate-agent-identity.mdx @@ -248,7 +248,7 @@ curl -s -X POST https://vmcp.example.com/oauth/register \ The response carries a `client_id` and **no `client_secret`**. The keypair itself is the credential. To authenticate at the token endpoint, the agent signs a `client_assertion` JWT with its private key (`iss` and `sub` set to its own -`client_id`, `aud` set to ToolHive's token endpoint, with a unique `jti`), then +`client_id`, `aud` set to the auth server's `issuer`, with a unique `jti`), then presents it alongside the subject token: ```bash title="POST /oauth/token" @@ -265,11 +265,13 @@ curl -s -X POST https://vmcp.example.com/oauth/token \ No `client_secret` parameter appears anywhere in this request. ToolHive validates the `client_assertion`'s signature against the JWKS declared at registration and rejects a replayed `client_assertion` (the same `jti` presented -twice) on the second attempt. Everything else about the exchange, subject-token -validation against `trustedIssuers`, actor resolution, and the resulting `act` -claim, works exactly as in the pre-provisioned case above; the issued token's -`act.sub` is the DCR-assigned `client_id` instead of a statically configured -one. +twice) on the second attempt. ToolHive also accepts the token endpoint URL as +the `aud` value, or an `aud` array that contains either value. These forms are +deprecated, and a future release will require the issuer as the only audience. +Everything else about the exchange, subject-token validation against +`trustedIssuers`, actor resolution, and the resulting `act` claim, works exactly +as in the pre-provisioned case above; the issued token's `act.sub` is the +DCR-assigned `client_id` instead of a statically configured one. ToolHive rejects registrations whose keys fall outside these limits: diff --git a/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx b/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx index a2420741..2e1f469d 100644 --- a/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx +++ b/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx @@ -477,6 +477,16 @@ client. For local development, a plain-HTTP loopback issuer also works when you set `insecureAllowConfidentialOverLoopbackHTTP: true`; ToolHive rejects a plain-HTTP non-loopback issuer. +To revoke a delegate client, remove its entry from `delegateClients`. Each vMCP +replica serves only the delegate clients its own configuration declares, and +answers requests from any other delegate client in storage with +`invalid_client`, as if the client were unknown. Access tokens already issued to +the removed client stay valid until they expire. With Redis storage, the +client's record stays in Redis; to delete it, remove the +`client:` key. During a rolling update, replicas still +running the previous configuration answer a newly added delegate client with +`invalid_client` until they're replaced. + To accept subject tokens minted by an external OIDC issuer, pair this with an `inboundGrants.tokenExchange.issuerPolicies` entry. For why delegation exists, the consent policy options, and a worked exchange, see diff --git a/docs/toolhive/reference/helm/operator-crds.mdx b/docs/toolhive/reference/helm/operator-crds.mdx index 9eb65183..3de8b21c 100644 --- a/docs/toolhive/reference/helm/operator-crds.mdx +++ b/docs/toolhive/reference/helm/operator-crds.mdx @@ -11,9 +11,9 @@ Control CRD installation and preservation with these Helm values. This reference lists values declared in the chart's default `values.yaml`. Templates can also accept optional settings and inherited `global` values. -Chart: `toolhive-operator-crds`. Chart version: `0.57.0`. Source: -[`values.yaml`](https://github.com/stacklok/toolhive/blob/v0.57.0/deploy/charts/operator-crds/values.yaml) -at `v0.57.0`. +Chart: `toolhive-operator-crds`. Chart version: `0.58.0`. Source: +[`values.yaml`](https://github.com/stacklok/toolhive/blob/v0.58.0/deploy/charts/operator-crds/values.yaml) +at `v0.58.0`. ## Values diff --git a/docs/toolhive/reference/helm/operator.mdx b/docs/toolhive/reference/helm/operator.mdx index 79dd53ed..447802e3 100644 --- a/docs/toolhive/reference/helm/operator.mdx +++ b/docs/toolhive/reference/helm/operator.mdx @@ -10,9 +10,9 @@ Configure the ToolHive operator with these Helm values. This reference lists values declared in the chart's default `values.yaml`. Templates can also accept optional settings and inherited `global` values. -Chart: `toolhive-operator`. Chart version: `0.57.0`. Source: -[`values.yaml`](https://github.com/stacklok/toolhive/blob/v0.57.0/deploy/charts/operator/values.yaml) -at `v0.57.0`. +Chart: `toolhive-operator`. Chart version: `0.58.0`. Source: +[`values.yaml`](https://github.com/stacklok/toolhive/blob/v0.58.0/deploy/charts/operator/values.yaml) +at `v0.58.0`. ## Values @@ -68,7 +68,7 @@ features: gc: gogc: 75 gomemlimit: 110MiB -image: ghcr.io/stacklok/toolhive/operator:v0.57.0 +image: ghcr.io/stacklok/toolhive/operator:v0.58.0 imageDiscovery: enabled: false resources: {} @@ -153,8 +153,8 @@ serviceAccount: labels: {} name: toolhive-operator tolerations: [] -toolhiveRunnerImage: ghcr.io/stacklok/toolhive/proxyrunner:v0.57.0 -vmcpImage: ghcr.io/stacklok/toolhive/vmcp:v0.57.0 +toolhiveRunnerImage: ghcr.io/stacklok/toolhive/proxyrunner:v0.58.0 +vmcpImage: ghcr.io/stacklok/toolhive/vmcp:v0.58.0 volumeMounts: [] volumes: [] ``` @@ -255,7 +255,7 @@ Key containing the password in `existingSecret`. When empty, uses **Type:** `string` -**Default:** `"ghcr.io/stacklok/toolhive/operator:v0.57.0"` +**Default:** `"ghcr.io/stacklok/toolhive/operator:v0.58.0"` Container image for the operator. @@ -271,7 +271,7 @@ Image pull policy for the operator container and image-discovery containers. **Type:** `string` -**Default:** `"ghcr.io/stacklok/toolhive/proxyrunner:v0.57.0"` +**Default:** `"ghcr.io/stacklok/toolhive/proxyrunner:v0.58.0"` Container image for ToolHive proxy runners created by the operator. @@ -279,7 +279,7 @@ Container image for ToolHive proxy runners created by the operator. **Type:** `string` -**Default:** `"ghcr.io/stacklok/toolhive/vmcp:v0.57.0"` +**Default:** `"ghcr.io/stacklok/toolhive/vmcp:v0.58.0"` Container image for Virtual MCP Server (vMCP) deployments created by the operator.