Skip to content

Commit 82d8e92

Browse files
renovate[bot]github-actions[bot]claude
authored
Update stacklok/toolhive to v0.26.0 (#826)
* Update stacklok/toolhive to v0.26.0 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Refresh reference assets for toolhive v0.26.0 * Document v0.26.0 user-facing additions - Note that OAuth 2.0 upstream userInfo is now optional with synthesis mode for upstreams without a userinfo endpoint - Add an "Interactive dashboard" pointer to thv tui from the CLI manage guide - Document operator.defaultImagePullSecrets for chart-level pull secrets and its precedence with per-CR imagePullSecrets Co-authored-by: claude[bot] <noreply@anthropic.com> * Edit v0.26.0 doc additions for clarity - Tighten the thv tui tip and drop the trailing complement-to-CLI line - Move the tk- prefix next to the synthesized subject and replace "shape" with "configuration" in the userInfo synthesis-mode note - Lift the per-CR imagePullSecrets parenthetical into a list and remove redundant phrasing in the operator pull-secret section Co-authored-by: claude[bot] <noreply@anthropic.com> --------- Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <noreply@anthropic.com>
1 parent d73ca31 commit 82d8e92

10 files changed

Lines changed: 313 additions & 18 deletions

File tree

.github/upstream-projects.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ projects:
3535

3636
- id: toolhive
3737
repo: stacklok/toolhive
38-
version: v0.25.0
38+
version: v0.26.0
3939
# toolhive is a monorepo covering the CLI, the Kubernetes
4040
# operator, and the vMCP gateway. It also introduces cross-
4141
# cutting features that land in concepts/, integrations/,

docs/toolhive/guides-cli/manage-mcp-servers.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ description:
99
ToolHive provides visibility into the status of your MCP servers. You can check
1010
the status of running servers and view their logs using the ToolHive CLI.
1111

12+
:::tip[Interactive dashboard]
13+
14+
To monitor and operate servers from a single live view instead of chaining
15+
together `thv list`, `thv logs`, and other subcommands, run
16+
[`thv tui`](../reference/cli/thv_tui.md) to launch the experimental terminal
17+
dashboard. It shows a real-time server list, streaming logs, a tool inspector,
18+
and a registry browser. Press `?` for the full key map.
19+
20+
:::
21+
1222
### List running servers
1323

1424
To see all currently running MCP servers:

docs/toolhive/guides-k8s/auth-k8s.mdx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -735,11 +735,19 @@ spec:
735735

736736
:::note
737737

738-
OAuth 2.0 providers require explicit endpoint configuration and a `userInfo`
739-
section, unlike OIDC providers which auto-discover these from the issuer URL.
740-
The `fieldMapping` section maps provider-specific response fields to standard
741-
user identity fields. For example, GitHub returns `login` instead of the
742-
standard `name` field.
738+
OAuth 2.0 providers require explicit endpoint configuration, unlike OIDC
739+
providers which auto-discover these from the issuer URL. The `userInfo` section
740+
is optional: when present, the embedded auth server fetches user identity claims
741+
from the configured endpoint, and the `fieldMapping` section maps
742+
provider-specific response fields to standard user identity fields (for example,
743+
GitHub returns `login` instead of the standard `name` field).
744+
745+
When you omit `userInfo`, the embedded auth server runs in synthesis mode for
746+
this upstream: it derives a non-personally-identifying subject (with a `tk-`
747+
prefix) from the access token and leaves `name` and `email` empty. Use this
748+
configuration for OAuth 2.0 servers that don't expose a userinfo endpoint, such
749+
as MCP authorization servers that comply with the
750+
[MCP authorization specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization).
743751

744752
:::
745753

docs/toolhive/guides-k8s/deploy-operator.mdx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,40 @@ To see all available configuration options, run:
181181
helm show values oci://ghcr.io/stacklok/toolhive/toolhive-operator
182182
```
183183

184+
### Pull workload images from a private registry
185+
186+
If your MCP server, proxy runner, vMCP, registry API, or embedding server images
187+
live in a private container registry, use `operator.defaultImagePullSecrets` to
188+
apply pull credentials to every workload the operator spawns:
189+
190+
```yaml title="values.yaml"
191+
operator:
192+
defaultImagePullSecrets:
193+
- regcred
194+
- name: backup-regcred
195+
```
196+
197+
Each entry is the name of a Kubernetes Secret of type
198+
`kubernetes.io/dockerconfigjson` (or another image-pull-secret type) that must
199+
exist in the namespace where each workload is created. Plain string and object
200+
forms are equivalent.
201+
202+
The secrets propagate to the pod spec and the operator-managed ServiceAccount of
203+
every workload-spawning controller: `MCPServer`, `MCPRemoteProxy`,
204+
`MCPRegistry`, `VirtualMCPServer`, and `EmbeddingServer`. Chart-level entries
205+
are appended to any per-CR `imagePullSecrets` already configured on the
206+
resource. Common per-CR fields are:
207+
208+
- `spec.imagePullSecrets` on `MCPRegistry` and `VirtualMCPServer`
209+
- `spec.resourceOverrides.proxyDeployment.imagePullSecrets` on `MCPServer` and
210+
`MCPRemoteProxy`
211+
212+
Per-CR entries take precedence when a secret name appears in both places.
213+
214+
The chart also exposes `operator.imagePullSecrets`, which controls only the
215+
operator's own pod. Use it when the operator image itself is in a private
216+
registry; use `defaultImagePullSecrets` for the workloads the operator manages.
217+
184218
## Operator deployment modes
185219

186220
The ToolHive operator supports two distinct deployment modes to accommodate

docs/toolhive/reference/cli/thv.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ thv [flags]
5656
* [thv start](thv_start.md) - Start (resume) a tooling server
5757
* [thv status](thv_status.md) - Show detailed status of an MCP server
5858
* [thv stop](thv_stop.md) - Stop one or more MCP servers
59+
* [thv tui](thv_tui.md) - Open the interactive TUI dashboard (experimental)
5960
* [thv version](thv_version.md) - Show the version of ToolHive
6061
* [thv vmcp](thv_vmcp.md) - Run and manage a Virtual MCP Server locally
6162

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
title: thv tui
3+
hide_title: true
4+
description: Reference for ToolHive CLI command `thv tui`
5+
last_update:
6+
author: autogenerated
7+
slug: thv_tui
8+
mdx:
9+
format: md
10+
---
11+
12+
## thv tui
13+
14+
Open the interactive TUI dashboard (experimental)
15+
16+
### Synopsis
17+
18+
Launch the interactive terminal dashboard for managing MCP servers.
19+
20+
The dashboard shows a real-time list of servers with live log streaming,
21+
tool inspection, and registry browsing — all from a single terminal window.
22+
23+
Key bindings:
24+
↑/↓/j/k navigate servers or tools
25+
tab cycle panels: Logs → Info → Tools → Proxy Logs → Inspector
26+
s stop selected server
27+
r restart selected server
28+
d d delete selected server (press d twice)
29+
/ filter server list, or search logs (on Logs/Proxy Logs panel)
30+
n/N next/previous search match
31+
f toggle log follow mode
32+
←/→ horizontal scroll in log panels
33+
R open registry browser
34+
enter open tool in inspector (from Tools panel)
35+
space toggle JSON node collapse (in inspector response)
36+
c copy response JSON to clipboard
37+
y copy curl command to clipboard
38+
u copy server URL to clipboard
39+
i show tool description (in inspector)
40+
? show full help overlay
41+
q/ctrl+c quit
42+
43+
```
44+
thv tui [flags]
45+
```
46+
47+
### Options
48+
49+
```
50+
-h, --help help for tui
51+
```
52+
53+
### Options inherited from parent commands
54+
55+
```
56+
--debug Enable debug mode
57+
```
58+
59+
### SEE ALSO
60+
61+
* [thv](thv.md) - ToolHive (thv) is a lightweight, secure, and fast manager for MCP servers
62+

static/api-specs/crds/mcpexternalauthconfigs.schema.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@
8686
"default": "sub",
8787
"description": "SessionNameClaim is the JWT claim to use for role session name\nDefaults to \"sub\" to use the subject claim",
8888
"type": "string"
89+
},
90+
"subjectProviderName": {
91+
"description": "SubjectProviderName is the name of the upstream provider whose access token\nis used as the web identity token for STS AssumeRoleWithWebIdentity.\nThis field is used exclusively by VirtualMCPServer, where there is no\nupstream swap middleware to replace the bearer token before the strategy runs.\nWhen left empty and an embedded authorization server is configured on the\nVirtualMCPServer, the controller automatically populates this field with\nthe first configured upstream provider name. Set it explicitly to override\nthat default or to select a specific provider when multiple upstreams are\nconfigured.\nWhen no embedded auth server is present, the bearer token from the incoming\nrequest's Authorization header is used instead.",
92+
"type": "string"
8993
}
9094
},
9195
"required": [
@@ -490,7 +494,7 @@
490494
"type": "object"
491495
},
492496
"userInfo": {
493-
"description": "UserInfo contains configuration for fetching user information from the upstream provider.\nRequired for OAuth2 providers to resolve user identity.",
497+
"description": "UserInfo contains configuration for fetching user information from the upstream provider.\nWhen omitted, the embedded auth server runs in synthesis mode for this\nupstream: a non-PII subject derived from the access token, no Name/Email.\nUse this shape for upstreams with no userinfo surface (e.g., MCP\nauthorization servers per the MCP spec).",
494498
"properties": {
495499
"additionalHeaders": {
496500
"additionalProperties": {
@@ -552,8 +556,7 @@
552556
"required": [
553557
"authorizationEndpoint",
554558
"clientId",
555-
"tokenEndpoint",
556-
"userInfo"
559+
"tokenEndpoint"
557560
],
558561
"type": "object"
559562
},

static/api-specs/crds/mcpregistries.schema.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@
2424
"description": "DisplayName is a human-readable name for the registry.",
2525
"type": "string"
2626
},
27+
"imagePullSecrets": {
28+
"description": "ImagePullSecrets allows specifying image pull secrets for the registry API workload.\nThese are applied to both the registry-api Deployment's PodSpec.ImagePullSecrets\nand to the operator-managed ServiceAccount the registry API runs as, so private\nimages are pullable through either path.\n\nUse this field for new manifests.\n\nImportant: this is the ONLY way to attach image-pull credentials to the\noperator-managed ServiceAccount. The legacy\nspec.podTemplateSpec.spec.imagePullSecrets path populates the Deployment's pod\nspec ONLY — it does NOT touch the ServiceAccount. On managed Kubernetes\nplatforms that rely on ServiceAccount-level credential injection (for example\nGKE Workload Identity, OpenShift's per-SA dockercfg secrets, EKS IRSA), using\nonly the legacy PodTemplateSpec path can fail to pull private images even when\nthe secret exists in the namespace. Always set spec.imagePullSecrets when\nSA-level credentials matter.\n\nPrecedence with PodTemplateSpec:\n - This field is applied first as the controller-generated default.\n - Values set under spec.podTemplateSpec.spec.imagePullSecrets are user overrides\n and win on overlap. If the user supplies imagePullSecrets via PodTemplateSpec,\n those replace the default list on the Deployment (the list is treated atomically).\n - The ServiceAccount is always populated from this field — PodTemplateSpec does not\n affect the ServiceAccount.\n\nAn omitted field and an explicitly empty list are equivalent: both leave the\nServiceAccount's existing ImagePullSecrets unchanged. This preserves\nplatform-managed pull secrets (for example OpenShift's per-SA dockercfg\nentries) when overlays or patches emit an empty list. Truly clearing the\nServiceAccount's pull secrets requires recreating the resource.",
29+
"items": {
30+
"description": "LocalObjectReference contains enough information to let you locate the\nreferenced object inside the same namespace.",
31+
"properties": {
32+
"name": {
33+
"default": "",
34+
"description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
35+
"type": "string"
36+
}
37+
},
38+
"type": "object",
39+
"x-kubernetes-map-type": "atomic"
40+
},
41+
"type": "array",
42+
"x-kubernetes-list-type": "atomic"
43+
},
2744
"pgpassSecretRef": {
2845
"description": "PGPassSecretRef references a Secret containing a pre-created pgpass file.\n\nWhy this is a dedicated field instead of a regular volume/volumeMount:\nPostgreSQL's libpq rejects pgpass files that aren't mode 0600. Kubernetes\nsecret volumes mount files as root-owned, and the registry-api container\nruns as non-root (UID 65532). A root-owned 0600 file is unreadable by\nUID 65532, and using fsGroup changes permissions to 0640 which libpq also\nrejects. The only solution is an init container that copies the file to an\nemptyDir as the app user and runs chmod 0600. This cannot be expressed\nthrough volumes/volumeMounts alone -- it requires an init container, two\nextra volumes (secret + emptyDir), a subPath mount, and an environment\nvariable, all wired together correctly.\n\nWhen specified, the operator generates all of that plumbing invisibly.\nThe user creates the Secret with pgpass-formatted content; the operator\nhandles only the Kubernetes permission mechanics.\n\nExample Secret:\n\n\tapiVersion: v1\n\tkind: Secret\n\tmetadata:\n\t name: my-pgpass\n\tstringData:\n\t .pgpass: |\n\t postgres:5432:registry:db_app:mypassword\n\t postgres:5432:registry:db_migrator:otherpassword\n\nThen reference it:\n\n\tpgpassSecretRef:\n\t name: my-pgpass\n\t key: .pgpass",
2946
"properties": {

0 commit comments

Comments
 (0)