Update stacklok/toolhive to v0.45.0 - #1120
Conversation
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @renovate[bot]'s task in 11m 15s —— View job Upstream release docs sync: toolhive v0.44.0 → v0.45.0
Summary of hand-written doc edits (13 files)
Deferred by readiness gatePlugin lock file, sync, upgrade, and Sigstore verification ( Auto-generated CLI/Swagger/CRD reference ( Commit: |
Covers the metrics diagnostics-port migration, Qoder IDE support, thv skill sync/push behavior changes, thv serve TCP request safeguards, MCPServerEntry and MCPRemoteProxy allowPrivateEndpoint, resourceOverrides.proxyDeployment scheduling fields, honored vMCP backend timeouts, and the new toolhive_rate_limit_fail_open metric. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @renovate[bot]'s task in 3m 58s —— View job Editorial review completeRan
Fixes applied
Considered but left as-is
|
- Use "vMCP" (already expanded on the page) in place of "Virtual MCP Server" in the MCPServerEntry allow-private-endpoint section. - Add the missing Oxford comma in the SSRF-blocked ranges bullet. - Drop "actually" filler and replace the Go-jargon "goroutine" with reader-facing language in the vMCP timeouts change note. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
@claude : adding Qoder to the "common clients" list and giving it a specific configuration section in the compatibility guide was overkill. Just add it to the table, it doesn't need the others. |
|
Claude finished @danbarr's task in 1m 7s —— View job Trimmed the Qoder additions
Qoder is now covered only by the table row in
The Note: I couldn't run Commit: |
Co-authored-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
jhrozek
left a comment
There was a problem hiding this comment.
Approved. Edited docs/toolhive/guides-cli/api-server.mdx to retain the actionable Content-Type: application/json requirement, the 415 Unsupported Media Type outcome, and the curl -d example. Removed the Origin-validation, loopback, socket, reverse-proxy, and media-type parsing implementation details from this API-user guide.
This PR contains the following updates:
v0.44.0→v0.45.0After this PR opens,
.github/workflows/upstream-release-docs.ymladds source-verified content edits for the new release. Forstacklok/toolhive, the same workflow also syncs reference assets (CLI help, Swagger) and regenerates the CRD MDX pages.Release Notes
stacklok/toolhive (stacklok/toolhive)
v0.45.0Compare Source
🚀 Toolhive v0.45.0 is live!
A security-and-supply-chain release: two coordinated fixes harden the
thv servemanagement API and the container build path, plugin artifacts gain end-to-end Sigstore verification, and skill pushes are now signed keylessly by default. Alongside that, Prometheus metrics move to a dedicated diagnostics port behind a migration switch, the embedded auth server gains two new RFC 7523 flows, and Virtual MCP finally honours configured backend timeouts and propagates backend health changes to live sessions.🔐 Security
thv servemanagement API are now rejected — the management API creates workloads with caller-named host bind mounts, registers MCP servers into on-disk agent configs, and installs skill artifacts, all as unauthenticated state-changing routes in the default configuration, and a cross-origin web page could drive it with a CORS "simple" POST that never triggers a preflight. This is GHSA-xv9h-79wp-q9w6. Two independent barriers are added for TCP listeners only (migration guide below).npx://,uvx://andgo://references were interpolated intoRUNinstructions unvalidated; they are now constrained to a character class that excludes shell metacharacters, and the two remaining bare interpolations in the templates are quoted (migration guide below).tools/list/prompts/list/resources/listresponse failed every decode and sniff and passed through unfiltered, leaking entries the Cedar policy or tool filter was supposed to remove (#6304).Flush()committed an implicitWriteHeader(200), so a backend 500 reached the client as a 200 carrying the full unfiltered list (#6335).thv servenow requiresContent-Type: application/jsonon state-changing requests that carry a body, and validatesOriginon loopback TCP binds — non-JSON callers get415 Unsupported Media Type(migration guide below)[A-Za-z0-9@/:._+=~[]-]— anpx:///uvx:///go://reference containing anything else now fails at build time instead of being interpolated into the Dockerfile (migration guide below)thv skill syncwithout--clientsnow targets every skill-supporting client — combined with the newqoderclient, every locked skill reports as drifted on the first sync after upgrading, andthv skill sync --checkexits non-zero in CI (migration guide below)runtime_config.build_withonnpx:///go://images is now a 400, andruntime_config.runtime_envis now actually applied to the built image — both were silently discarded by the workload REST API (migration guide below)thv skill pushrequires exactly one of--key,--identity-token, or--no-sign—key+no_signwas previously accepted and pushed an unsigned artifact; it is now a 400 (migration guide below)operational.timeouts— a configured value below 30 s will now actually cut backend calls that previously got the silent 30 s default (migration guide below)plugins.MaterializationAdapter,state.Storewriters,storage.UpstreamTokenStorage, and six function signatures. No effect on the CLI, the operator, the wire protocol, or persisted state (migration guide below)thv llmlocal proxy returns401 token_requiredinstead of502 server_errorwhen the stored credential has been rejected by the IdP (#6389)Migration guide: `thv serve` now requires application/json on state-changing requests
Who is affected: anything calling the
thv servemanagement API over TCP with aPOST/PUT/PATCH/DELETEthat carries a body but does not setContent-Type: application/json. Studio is not affected — it runsthv serve --socket=<path>, and the UNIX-socket path skips both barriers entirely. Empty-body mutating routes (stop,restart) are unaffected, as are allGET/HEADrequests.Two barriers were added to the middleware chain, for TCP listeners only:
thv proxypath. A non-loopback bind (or--port 0) yields no allowlist and passes through, matching that path's behaviour; aWARNis logged so the disabled state is visible.application/jsonenforcement on state-changing requests with a body.text/plain, the form encodings, and an absentContent-Typeare all CORS "simple" types exempt from preflight, and the handlers decoded them as JSON regardless. Requiringapplication/jsonforces a preflight the browser cannot clear. Chunked bodies (Content-Length: -1) take the strict path.Before
After
Migration steps
Content-Type: application/jsonto every request your client sends tothv servethat carries a body. Most HTTP clients already do;curl -dand barefetch()do not.application/json; charset=UTF-8also matches — the parameter is stripped before comparison.thv serveon a non-loopback address, note that Origin validation is a pass-through there. Put it behind a reverse proxy that enforcesOrigin, and check for the startupWARNnaming the bind address.thv serve --socket=<path>, nothing changes.Fixed in commit
7f15a63— GHSA-xv9h-79wp-q9w6Migration guide: package names are now constrained to a safe character class
Who is affected: anyone running
thv run npx://…,uvx://…orgo://…with a package reference containing characters outsideA-Za-z0-9and@ / : . _ + = ~ [ ] -. In practice this is nobody using a legitimate npm scope, PyPI pin/extra, or Go module path — the allowed set was chosen to cover all three ecosystems.The package name is interpolated into
RUNinstructions innpx.tmpl,uvx.tmplandgo.tmpl. Before this change nothing validated it, so a name carrying shell metacharacters could break out of the instruction and execute arbitrary commands during the image build. The two remaining bare interpolations innpx.tmplandgo.tmplare now single-quoted as well.Before
After
Migration steps
invalid package name, check the reference for spaces, quotes,;,$, backticks, or parentheses.npx://@scope/pkg@1.2.3,uvx://pkg[extra]==1.0,go://github.com/org/mod/cmd/tool@v1.2.3,go://./local/path.Fixed in commit
68dc1baMigration guide: `thv skill sync` client expansion
Who is affected: every user of
thv skill syncandPOST /api/v1beta/skills/sync, and most acutely CI pipelines runningthv skill sync --check.Two changes combine.
entryMatchesInstallednow treats a lock entry as current only if the installed skill covers every skill-supporting client, not just the clients it was recorded against; andreinstallPinnedno longer falls back to the previously recorded client list. Independently, #5870 added Qoder as the 18th skill-supporting client.The result: any skill locked under v0.44.0 has a recorded client list that cannot contain
qoder, so it is reported as drifted on the first sync after upgrade — and a barethv skill syncwill materialize it into<project>/.qoder/skills/as well.thv skill sync --checkexits with the check-failure code, so a previously green CI gate turns red purely from the upgrade.Before
After
Migration steps
thv skill sync --checkonce after upgrading and expect drift on every locked skill. This is expected, not corruption.thv skill synconce to materialize skills into all skill-supporting clients, including the new.qoder/skills/. Subsequent--checkruns go green.--clientsexplicitly on every sync (and{"clients": [...]}on the REST endpoint) so the expected set is exactly what you specify.thv, so the gate does not fail on the upgrade commit..qoder/skills/in a project tree is unwanted, add it to.gitignoreor constrain--clients.thv skill upgradeis unchanged — it still preserves the existing client list.PRs: #6352, #5870
Migration guide: workload API honours all `runtime_config` fields
Who is affected: REST callers of
POST /api/v1beta/workloadsand the workload update endpoint that sendruntime_config.The request type is
*templates.RuntimeConfigand Swagger published all four of its fields, but the service layer only ever copiedbuilder_imageandadditional_packages. A caller postingruntime_config.build_withgot201 Createdand a workload built with unconstrained dependencies — silently, which is exactly the failurebuild_withexists to prevent.runtime_envwas dropped the same way.Before
After
Migration steps
runtime_config.build_withfrom requests usingnpx://orgo://images — it was never applied. Onlyuvx://supports it.runtime_config.runtime_envyou were sending: it now actually lands in the built image. Keys must match^[A-Z][A-Z0-9_]*$, must not be reserved (PATH,HOME,USER,SHELL,PWD,HOSTNAME,TERM,LANG,LC_ALL,LD_PRELOAD,LD_LIBRARY_PATH), and values must not contain shell metacharacters..or_, and names over 128 characters, now return an actionable 400 instead of a scrubbed500 Internal Server Error. The workload was never created in either case.GET → edit → PUTof a protocol-built workload now succeeds instead of returning 400 and erasing the build configuration — no action needed, but re-test any round-trip tooling.--build-withshould matchbuild_withinstead; the message is now shared by the CLI, the API, the TUI and the config file.PR: #6214 — Fixes #6210
Migration guide: skill push signing inputs are now mutually exclusive
Who is affected: callers of
POST /api/v1beta/skills/push,skillsvc.Push, andthv skill pushthat supplied more than one signing input.Pushpreviously only checked "key or no_sign". Supplying both meantno_signsilently won and the artifact was published unsigned. It is now a 400.Before
{"reference": "ghcr.io/org/s:v1", "key": "/keys/cosign.key", "no_sign": true} → 200 OK (artifact pushed UNSIGNED — no_sign silently won)After
{"reference": "ghcr.io/org/s:v1", "key": "/keys/cosign.key", "no_sign": true} → 400 "no_sign (--no-sign) cannot be combined with key (--key) or identity_token (--identity-token)" // Choose exactly one: {"reference": "ghcr.io/org/s:v1", "key": "/keys/cosign.key"} // key-pair signed {"reference": "ghcr.io/org/s:v1", "identity_token": "<raw JWT>"} // keyless {"reference": "ghcr.io/org/s:v1", "no_sign": true} // explicitly unsignedMigration steps
key/identity_token/no_signper push."signing key required"— it is now"signing credential required".thv skill pushwith no flags no longer fails. In GitHub Actions withid-token: writeit signs keylessly from the ambient OIDC token; on an interactive terminal it prompts for a browser sign-in; anywhere else it fails client-side with an actionable error before anything is published. In CI and automation, pass one of the three flags explicitly rather than relying on the default.PRs: #6385, #6390 — Closes #6307
Migration guide: vMCP backend timeouts are now honoured
Who is affected: Virtual MCP operators who set
operational.timeouts.defaultoroperational.timeouts.perWorkload. Deployments that omitoperational.timeoutsare unaffected — three independent 30 s fallbacks keep the default behaviour identical.vMCP accepted the documented timeout settings but never used them for backend MCP calls; backend clients kept a hardcoded 30 s, and a separate 30 s server
WriteTimeoutcould close a POST before a slow backend returned anything. Both are now driven by configuration.Before
After
Migration steps
grep -A3 'timeouts:' <vmcp-config>orkubectl get virtualmcpserver -o yaml | grep -A5 timeouts.30sto preserve v0.44.0 behaviour, or keep them deliberately and verify your slowesttools/callcompletes inside the window.initOneBackendusesmax(30s, requestTimeout), so a short configured value never shortens init.failed to <op> for backend <id> (timeout)in logs after upgrade to spot a value set too low.operational.failureHandling.healthCheckTimeoutis separate and unaffected, and the cross-pod session-restore path is still a fixed 15 s.PR: #6411 — Fixes #6410
Migration guide: Go API changes
Who is affected: Go consumers importing ToolHive packages. None of these affect the CLI, the operator, the wire protocol, or persisted state.
pkg/pluginsMaterializationAdaptergains requiredEnsureRegistered(ctx, DematerializeRequest) errorandHealth(ctx, DematerializeRequest) errorpkg/groupsRemovePluginFromAllGroupsremoved (useRemovePluginFromGroupper group);AddPluginToGroupandAddSkillToGroupnow return(added bool, err error)pkg/stateAborter;Close()now publishes and can failpkg/skillsInstallOptions.Visitedremoved, replaced byExpectedCanonicalName stringpkg/authserver/storageUpstreamTokenStorage(and transitivelyStorage) gains requiredResolveUpstreamTokenRowIDpkg/authserver/server/registrationLoopbackClient,NewLoopbackClient,MatchRedirectURI,GetMatchingRedirectURIremoved; use the free functionRegisteredLoopbackRedirectURIpkg/authserver/server/registrationValidateDCRRequestgains anallowPrivateKeyJWT boolparameterpkg/authserver/server/tokenexchangeValidateTrustedIssuersandNewMultiIssuerTokenValidatorgain anallowedAudiences []stringparameterpkg/api/v1WorkloadService.BuildFullRunConfiggains a fourth parametercmd/thv-operator/pkg/validationValidateRemoteURL(rawURL string)→ValidateRemoteURL(rawURL string, opts ValidateRemoteURLOptions)Two of these deserve concrete code:
pkg/state— writers must abort, andClose()publishesLocalStorewriters now write to a temp file and publish atomically onClose(os.RenameforGetWriter,os.LinkforCreateExclusive). Three consequences: the target name does not exist untilClose;Closereturns real errors that must be handled; andCreateExclusiveconflicts surface fromCloserather than from the call itself.Aborteris documented as required but enforced only at runtime — aStorewhose writer lacksAbort()still compiles, and every abandon path then returns"state writer does not support abort"and leaks the file handle. Add a compile-time assertion.pkg/plugins— two new adapter methodsMigration steps
task genafter updating any implementation.UpstreamTokenStorage, return a deterministic, non-empty, side-effect-free ID derived from your key scheme, and do no I/O — resolution happens before the singleflight joins, so a round-trip defeats the dedup. Never alias rows that are not physically the same row.RegisteredLoopbackRedirectURI, note the changed return semantics: the old method returned the requested URI (dynamic port preserved); the new function returns the registered URI. Keep your own requested value if you need the port.httperr.Code(err) == http.StatusConflictcheck from theCreateExclusivecall site to theClose()call site.🔄 Deprecations
/metricson the transport port is deprecated in favour of the dedicated diagnostics listener (default port9464) — the transport-port copy still serves by default in v0.45.0 viametricsOnTransportPort, but that default will flip in a future release (#6296, #6370, #6371, #6368)Deprecation detail: moving Prometheus metrics to the diagnostics port
Existing scrape configurations keep working in v0.45.0.
DefaultMetricsOnTransportPortistrueand the field is a*boolwith no CRD default, so an unset value inherits the release default and is not pinned into stored config. Metrics are simply served in two places during the migration window.Why the move:
/metricsshared the port that serves MCP traffic, which the operator binds to0.0.0.0and the Service maps. KubernetesNetworkPolicymatches on pods, ports and protocols and cannot filter on HTTP path, so while the endpoint shares the transport port there is no way to express "allow MCP traffic, deny metrics scraping". Note the move adds no authentication — the diagnostics listener carries no middleware by design, and restricting who can reach the port is what protects it.Cutting over
# CLI thv run --otel-metrics-on-transport-port=false …9464unless overridden) and confirm metrics arrive.metricsOnTransportPort: falseand confirm nothing else was still scraping the transport port.NetworkPolicy— seedocs/observability.md. It binds0.0.0.0under the operator, so any pod in the cluster can reach it by pod IP until you do. Do not add it to a Service or Ingress.containerPortor Service port is declared,ServiceMonitor/named-portPodMonitordiscovery will not find it — scrape withkubernetes_sd_configsrole: podand an explicit__address__relabel to:9464.404on the transport port once you opt out (the body explains itself and names the log line to grep for).One genuinely breaking side effect, still present: when ToolHive metrics are not served on the transport port,
/metricsnow returns 404 on the application listener instead of falling through to the backend. Under the transparent proxy — remote servers viathv run <url>/MCPRemoteProxy, and containersse/streamable-httpworkloads — a backend that exposed its own/metricsthrough the ToolHive proxy is no longer reachable there. Scrape such backends directly instead.📋 Upgrade Notes
kubectl applyof the rawvirtualmcpserversCRD exceeds the 262144-byte annotation limit. This is pre-existing (it was already over at v0.44.0) rather than introduced here, but #6183 grew themcpserversandmcpremoteproxiesCRDs ~2.5× by expanding thecorev1.Affinityschema, so it is worth stating plainly.helm install/upgradeand Flux are unaffected; Argo CD with the default client-side apply is not. Usekubectl apply --server-side --force-conflicts -f <crd-dir>, or addServerSideApply=trueto the Argo CDApplication'ssyncOptions.MCPServerreadiness honest. A server whose workload StatefulSet was deleted out-of-band previously reportedReady=Truewhile clients hit a dead backend; it now reportsPending/Ready=Falseand is auto-healed by bouncing the proxy (2-minute cooldown). Only already-broken servers are affected, butkubectl wait --for=condition=Readyand Argo/Flux health checks will now correctly show them as not ready. The operator also adopts a controller owner-ref on that StatefulSet — adoption is metadata-only and causes no pod churn, but deleting anMCPServernow garbage-collects its StatefulSet even if the finalizer does not run.allowPrivateKeyJwtRegistration— a v0.44.0 replica silently drops the newjwksfield when reading a row a v0.45.0 replica wrote.🆕 New Features
private_key_jwt(RFC 7523 §2.2) instead of a shared secret, generating their own keypair and registering only the public half (#6427)nodeSelector,tolerationsandaffinityunderresourceOverrides.proxyDeployment, so the proxy lands on the same pre-warmed pool as its server (#6183)MCPServerEntryandMCPRemoteProxygainspec.allowPrivateEndpoint, letting a Virtual MCP reach a co-located in-cluster backend in-mesh so the backend's workload-identity authorization still applies — loopback, link-local, cloud-metadata andkubernetes.default*stay blocked regardless (#6195)9464) for both the proxy and Virtual MCP, so access can be governed by port with aNetworkPolicy(#6296, #6368), reachable from the CLI via--otel-metrics-on-transport-portand from the operator viaprometheus.metricsOnTransportPort(#6371)toolhive_rate_limit_fail_open_totalcounter and arate_limit.fail_openspan attribute record when a check failed open after a Redis error (#6282)thv skill pushsigns keylessly by default: the CLI acquires an OIDC identity token (GitHub Actions ambient token in CI, browser sign-in on a terminal) and the server exchanges it with Fulcio and records a Rekor entry (#6385, #6390); release pushes in CI are signed rather than carrying the old--no-signstopgap, and a new staging job verifies the result with stockcosign(#6402)provenance, that becomes the expected signer identity (#6420)TOOLHIVE_PLUGINS_LOCK_ENABLED=trueand inert by default: project installs pin intotoolhive.lock.yaml(#6314),thv ai-plugin syncrestores and drift-checks them (#6316),thv ai-plugin upgradeadvances a pin under review (#6317), bundles and git signatures are persisted (#6396), signatures are verified at install (#6397), and stored signatures are re-verified offline on every sync (#6399)thv client register qoderconfigures Qoder IDE for MCP server integration and skill installation (#5870)kubectl get mcpgroupshows a Proxies column fromstatus.remoteProxyCount, so a group made entirely ofMCPRemoteProxymembers no longer looks empty (#6376)🐛 Bug Fixes
notifications/tools/list_changedand an updatedtools/listwhen a backend recovers or fails health checks, instead of serving the registration-time snapshot until reconnect — note that tools can now also disappear mid-session, since resync uses replace semantics (#6196)operational.timeoutsfor backend calls, and no longer tears down a slow POST at the 30 s server write deadline (#6411)http://localhost/callbackregistration listening on an ephemeral port was rejected as aredirect_urimismatch, and OAuth errors now reach the client's real listener (#6215)thv llm setup, instead of an opaqueinvalid_grantthat every consumer read as a transient provider fault and retried forever (#6389)insecureAllowConfidentialOverLoopbackHTTPis explicitly enabled, unblocking local development; non-loopback HTTP issuers remain rejected (#6426)CreateExclusive's exists-check and creation are no longer racy (#6350)kubectl rollout restarton ToolHive proxy Deployments and MCPServer workload StatefulSets is honoured instead of being reverted on the next reconcile (#6378)Readyis no longer claimed on a proxy-only stack serving a dead backend (#6379)unix://socket URLs round-trip correctly on Windows — POSIX paths no longer gain a fourth slash, and drive-letter paths parse instead of being rejected as not absolute (#6416)thv skill syncandthv skill upgradere-read each skill under its lock before classifying or mutating, so a concurrent uninstall is not resurrected and a newer install is not overwritten (#6352)runtime_configfields instead of silently droppingbuild_withandruntime_env(#6214)/metricsendpoint move is diagnosable: the dead endpoint returns an explanatory 404 body and the startup line is aWARNnaming the resolved diagnostics address (#6369)metricsOnTransportPort, defaulting to on, so no existing scrape configuration breaks on upgrade (#6370)🧹 Misc
toolhive-core'scontainer/signer, deleting the local duplicate that only ever supported key-pair signing (#6383)close of closed channelpanic in the vMCP backend session tests that aborted the whole test binary and surfaced as unrelated failures (#6363)task test-e2eruns sweep workloads leaked by a Ginkgo timeout-kill, which had been exhausting the Docker network address pool (#6367)Accept: application/json, text/event-streamheader (#6123)golangci-lintto v2.12.2 to avoid an upstreamnilnessanalyzer panic that was failing CI onmain(#6393)GO-2026-5932openpgp suppression now names a checkable removal trigger and records why the dependency cannot be fixed locally (#6286)📦 Dependencies
github.com/moby/go-archivegithub.com/stacklok/toolhive-cataloganthropics/claude-code-actionAlso bumped as part of feature work:
github.com/stacklok/toolhive-coreto v0.0.41 (#6383) and v0.0.42 (#6420) — the latter migratedcelto the renamedcel.dev/cel-gomodule.👋 Welcome to our newest contributors: @TANTIOPE, @haaaashimi, @RaviTharuma, @premctl, @melbinjp, @christensenjairus, @talshechanovitz 🎉
Full commit log
What's Changed
New Contributors
Full Changelog: stacklok/toolhive@v0.44.0...v0.45.0
🔗 Full changelog: stacklok/toolhive@v0.44.0...v0.45.0
Configuration
📅 Schedule: (in timezone America/New_York)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Never, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.
Docs update for
toolhivev0.45.0At a glance
stacklok/toolhivev0.44.0→v0.45.0Who does what
@reyortiz3 cut this release and owns this PR: review your own changes, chase the remaining approvals, and merge once they're in. You don't need to wait on a review from anyone listed as having no docs impact below.
Everyone with a review request: the target is a review and approval within 2 business days.
Summary of changes
guides-cli/telemetry-and-metrics.mdx,guides-k8s/telemetry-and-metrics.mdx,guides-vmcp/telemetry-and-metrics.mdx, andconcepts/observability.mdxfor the new diagnostics listener (default9464), the--otel-metrics-on-transport-portCLI flag /metricsOnTransportPortfield, and the upcoming default flip.reference/client-compatibility.mdx(table row + configuration file section) and to the common client-name list inguides-cli/client-configuration.mdx.guides-cli/skills-management.mdx: documented the new default thatthv skill synctargets every skill-supporting client (with the CI recommendation to pin--clients), and rewrote thethv skill pushsigning section for the mutually exclusive--key/--identity-token/--no-signflags and the keyless-by-default ladder.guides-cli/api-server.mdxcovering the newContent-Type: application/jsonandOriginsafeguards, and their exemptions (UNIX socket, empty body, GET/HEAD).spec.allowPrivateEndpointsections toguides-k8s/mcp-server-entry.mdxandguides-k8s/remote-mcp-proxy.mdx, including which address families remain blocked.resourceOverrides.proxyDeploymentscheduling fields (nodeSelector,tolerations,affinity) with merge-order guidance toguides-k8s/run-mcp-k8s.mdxandguides-k8s/remote-mcp-proxy.mdx.Changed in v0.45.0admonition toguides-vmcp/configuration.mdxTimeouts section noting thatoperational.timeoutsvalues are now honored, and added thetoolhive_rate_limit_fail_opencounter row toguides-k8s/rate-limiting.mdxandguides-vmcp/telemetry-and-metrics.mdx.TOOLHIVE_PLUGINS_LOCK_ENABLED=trueand is inert by default. Deferred per the readiness gate.No docs impact identified
@RaviTharuma @TANTIOPE @Yanhaoxi @aponcedeleonch @kocaemre @melbinjp @stantheman0128 - your changes in this release didn't appear to affect the docs, so no review is requested and you're not blocking this PR. Please skim the diff anyway and comment if something of yours was missed or misjudged.
Run cost
How this PR was built
Two Claude Opus sessions run per release: a generation pass
(
upstream-release-docsskill, 6 phases) followed by a fresh-context editorial pass (
docs-review). Prettier/ESLintauto-fixes are applied after.
Auto-synced paths — do not hand-edit these in review:
static/api-specs/docs/toolhive/reference/cli/(toolhive only)docs/toolhive/reference/crds/If a "Gaps needing human context" section is present above,
each entry includes a paste-ready Helper prompt for local
Claude a reviewer can use to resolve the gap.