Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/upstream-projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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/,
Expand Down
26 changes: 21 additions & 5 deletions docs/toolhive/guides-cli/ai-plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 <cosign.pub>` 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)
Expand Down
26 changes: 21 additions & 5 deletions docs/toolhive/guides-cli/skills-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 <cosign.pub>` 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)
Expand Down
41 changes: 41 additions & 0 deletions docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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: '<YOUR_CLIENT_ID>'
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
Expand Down
46 changes: 46 additions & 0 deletions docs/toolhive/guides-vmcp/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/toolhive/reference/cli/thv_ai-plugin_sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
```

Expand Down
6 changes: 4 additions & 2 deletions docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
```

Expand Down
1 change: 1 addition & 0 deletions docs/toolhive/reference/cli/thv_skill_sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
```

Expand Down
12 changes: 7 additions & 5 deletions docs/toolhive/reference/cli/thv_skill_upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
Expand All @@ -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)
```

Expand Down
Loading