chore(deps): update dependency stacklok/toolhive to v0.42.0 - #2573
Merged
Conversation
samuv
approved these changes
Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
v0.41.0→v0.42.0Release Notes
stacklok/toolhive (stacklok/toolhive)
v0.42.0Compare Source
🚀 Toolhive v0.42.0 is live!
AI-tool plugin management goes end to end —
thv ai-plugingains a full CLI, REST API, and registry catalog — and the skills supply chain gets Sigstore signature verification at install, sync, and upgrade time. Alongside that, a large batch of MCP dual-era correctness fixes lands: multiple clients can finally share a stdio server, and vMCP stops flapping between the Modern and Legacy revisions.status.referencingWorkloadsandstatus.referenceCount(and theReferencesprinter column) are gone from all six config CRDs; replace any automation reading them with a workload field query (migration guide)pkg/telemetry/providerswas deleted and two long-publishedoptimizerdecconstants were removed (migration guide)Migration guide: Config CRD status fields removed
Who is affected: anyone reading
status.referencingWorkloadsorstatus.referenceCountfromMCPOIDCConfig,MCPAuthzConfig,MCPExternalAuthConfig,MCPToolConfig,MCPWebhookConfig, orMCPTelemetryConfig—kubectlusers relying on theREFERENCEScolumn, scripts and GitOps assertions usingjsonpath/jqon those paths, Chainsaw/kuttl tests, kube-state-metrics custom-resource-state configs and the dashboards built on them, and Go code reading.Status.ReferencingWorkloads/.Status.ReferenceCount.MCPWebhookConfigandMCPTelemetryConfigonly ever hadreferencingWorkloads.MCPTelemetryConfignever had aReferencesprinter column, so itskubectl getoutput is unchanged.Upgrade safety: these were derived values computed from workload specs — the source of truth (
spec.*ConfigRefon workloads) is untouched, so nothing unrecoverable is lost. Applying the new schema does not rewrite or reject existing stored objects; residual values stay inert in etcd until each object's status is next written. No storage-version bump, no CRD delete/recreate, no migration job. Deletion protection is unchanged — every config controller still recomputes referrers live at deletion time and setsDeletionBlocked=Truewith reasonReferencedByWorkloads.Before
After
To list referrers, query the workloads by their config-ref:
The reference paths per config kind, exactly as the operator's own indexers define them:
MCPOIDCConfigspec.oidcConfigRef.name;spec.incomingAuth.oidcConfigRef.name(vMCP)MCPAuthzConfigspec.authzConfigRef.name;spec.incomingAuth.authzConfigRef.name(vMCP)MCPTelemetryConfigspec.telemetryConfigRef.nameMCPExternalAuthConfigspec.externalAuthConfigRef.name, orspec.authServerRef.namewhenspec.authServerRef.kind == "MCPExternalAuthConfig"MCPToolConfigspec.toolConfigRef.nameMCPWebhookConfigspec.webhookConfigRef.nameNote
kubectl --field-selectorwill not work for these paths — the operator's indexes are controller-runtime cache indexes, not API-server field selectors. Use-o json | jqor-o custom-columns.Migration steps
kubectl get mcpoidcconfigs,mcpauthzconfigs,mcpexternalauthconfigs,mcptoolconfigs,mcpwebhookconfigs,mcptelemetryconfigs -A -o json > /tmp/thv-config-refs-pre-0.42.jsonreferenceCount,referencingWorkloads, and theReferences/REFERENCEScolumn — shell scripts,kubectl wait --for=jsonpath=, Chainsaw/kuttl assertions, Argo CD/Flux health checks, kube-state-metrics configs, Grafana panels, Kyverno/Gatekeeper rules.kubectl -n NS get mcpoidcconfig my-oidc -o jsonpath='{.status.conditions[?(@.type=="DeletionBlocked")].message}'helm upgradetheoperator-crdschart, then theoperatorchart. No pre/post hooks needed.kubectl -n toolhive-system get mcpoidcconfigshowsNAME SOURCE VALID AGE, and deletion of a referenced config still leaves it withDeletionBlocked=True..Status.ReferencingWorkloads/.Status.ReferenceCountreads. TheWorkloadReferencetype (Kind,Name) is still exported if you want to keep your own list shape.PR: #5631 — completes the cleanup tracked in #5607
Migration guide: Cedar policy now sees the post-mutation request
Who is affected: only workloads configured with at least one mutating webhook and either Cedar authorization or any consumer of audit / telemetry / usage metrics. Both are shipped, supported, non-mutually-exclusive configurations —
thv run --webhook-config <file with a mutating: entry> --authz-config <file>, orMCPWebhookConfig.spec.mutatingin the operator. Workloads with no mutating webhook see zero change; the republish is gated on the body actually having changed.What was wrong:
ParsingMiddlewareparses the request body once and refuses to parse again. The mutating webhook replacedr.Bodybut passed the request through unchanged, so Cedar evaluated policy against the tool name and arguments that arrived while the backend executed the ones that ran. The audit half was reachable in the default configuration: the event type andtarget.nameresolve through the parsed-request holder regardless ofincludeRequestData(which defaults tofalse), so the audit trail named a request that never executed. Telemetry and usage metrics drifted the same way.Security framing, stated precisely: before v0.42.0, a client could reach a tool or argument set Cedar would have denied by sending a permitted request shape that the webhook rewrote into a forbidden one. A second bug narrowed this in practice:
r.ContentLengthwas not refreshed alongsider.Body, so a mutation that shrank the body failed at the reverse proxy and one that grew it was truncated into invalid JSON. The bypass was live for length-preserving rewrites — which is exactly case/format normalization, and a webhook can pad JSON whitespace to hold length constant. That staleContent-Lengthis also fixed here.Before
After
Migration steps
--webhook-configwith amutating:entry (orMCPWebhookConfig.spec.mutating). If not, stop — no action needed.method,params.name, and/orparams.arguments.MCP::Tool::"<name>") and everywhen { context.arg_* }clause. Policies that were passing only because they never saw the rewrite will now deny, and vice versa.typeortarget.name— for mutated requests those values change on upgrade.Gaps this deliberately does not close, all documented rather than fixed:
includeRequestData: true, the recorded request payload is still the pre-mutation body (audit readsr.Bodybefore the webhook), so event type/target name are post-mutation while the payload is not.Mcp-Method/Mcp-Nameheaders forwarded to the backend still name the original tool. A conformant Modern backend rejects the mismatch, so it fails closed — but a mutating webhook should not rename tools on the Modern path.ParsingMiddlewareand still decide against the request as received, so--toolsfiltering remains bypassable by a webhook rename. Tracked in #6134.PR: #6136 — Fixes #6133
Migration guide: Recovered panics are no longer logged
This is an unintended regression, not a design decision. It is called out here because it costs you diagnostics silently, and a one-line fix is expected in a patch release.
Who is affected: any operator who relies on ToolHive's logs to diagnose a recovered HTTP panic — including log-based alerts, log-derived metrics, and support bundles. Everyone running without Sentry configured (the default) is affected most.
What changed:
pkg/recoverybecame a thin shim overtoolhive-core/recovery. Core'sMiddlewarerecovers panics silently unless a logger is injected viaWithLogger, and ToolHive's shim passes onlyWithPanicHandler. The OTel span error recording and Sentry issue reporting are genuinely preserved — same span status (codes.Error,"panic recovered"), same sanitization, same raw value to Sentry, same ordering — but theslog.Errorline and its stack trace are gone, and no other middleware picks them up.Before (v0.41.0)
After (v0.42.0)
Migration steps
Panic recovered, they will stop firing. Do not interpret the silence as "no panics" — re-point them at the 500-response rate or at Sentry until the log line returns.ReportPanicstill sends the raw panic value, so panics remain visible as Sentry Issues with full context.RecordErrorplus an error status, so OTel-based panic detection keeps working.msg="panic recovered"withpanic,method,path, andstackattributes) rather than the old single formatted string, so write any new log parser against that shape.PR: #6145
Migration guide: Go API changes
Who is affected: only out-of-tree Go code importing ToolHive packages. No CLI, REST API, or CRD surface changes here, and no in-tree caller is affected.
pkg/telemetry/providerswas deleted (#6146)The package and its
/otlpand/prometheussubpackages were removed and consumed fromtoolhive-coreinstead. The graduation is verbatim — every non-test file is byte-identical apart from two self-referential import paths — so all 12 options (WithServiceName,WithServiceVersion,WithOTLPEndpoint,WithHeaders,WithInsecure,WithCACertPath,WithTracingEnabled,WithMetricsEnabled,WithSamplingRate,WithEnablePrometheusMetricsPath,WithCustomAttributes,WithExtraSpanProcessors) plusNewCompositeProvider,ProviderOption, andCompositeProviderkeep identical names and signatures. Nothing about emitted telemetry changes — resource attributes, service-name defaulting, OTLP exporter/TLS config, and Prometheus exporter registration all behave as before.Before
After
Two
optimizerdecconstants were removed (#6175)pkg/vmcp/session/optimizerdecno longer exportsCallToolArgToolNameorCallToolArgParameters. Both have been part of the published API since v0.15.0. They existed to read thecall_tooltarget out of a raw arguments map, a pattern that is now known-unsafe:encoding/jsonfalls back to case-insensitive field matching, so a map index and a struct decode resolve different key sets.Before
After
registry.Providergained three methods (#6135)ListAvailablePlugins(),GetPlugin(namespace, name), andSearchPlugins(query)were added to the interface. Implementations that embedregistry.BaseProviderpick up no-op defaults and need no change; anything satisfying the old method set directly will no longer compile.Migration: embed
registry.BaseProviderin your provider struct, or implement the three methods.🔄 Deprecations
pkg/audit's MCP event constants,LevelAudit, andNewAuditLoggerare now transitional aliases forgithub.com/stacklok/toolhive-core/auditand will be removed once the migration's cleanup wave rewrites imports per subtree — prefer thetoolhive-core/auditsymbols in new code (#6148)🆕 New Features
thv ai-plugincommand group —build,validate,push,install,list,info,uninstall, plus local build management viabuildsandbuilds remove— targeting Claude Code and Codex (#5782)/api/v1beta/plugins(10 endpoints) with a matching Go HTTP client inpkg/plugins/client, so the CLI, API, and external tooling share one contract (#5782)thv ai-plugin install <name>now resolves a plain name against the configured registry instead of failing with a 404 hint, and new catalog routes let you browse and search plugins in a registry (#6135)provenance:on first use and rejecting unsigned artifacts unless you pass--allow-unsigned(#6129)thv skill syncre-verifies each managed skill's stored Sigstore bundle offline against the lock file's recorded identity, treating a failed re-verification as drift so a CI gate catches signature changes exactly like content changes (#6131)thv skill upgraderefuses to move a skill to an artifact signed by a different identity — or to an unsigned one — reportingsigner-change-blockedunless you explicitly rotate trust with--allow-signer-change(#6132)The skills signing features above are all behind the experimental
TOOLHIVE_SKILLS_LOCK_ENABLEDgate and apply only to project-scoped installs. With the gate unset,thv skill installbehaves exactly as in v0.41.0. Note that git (gitsign) provenance is recorded asprovisional: truebecause the embedded Rekor transparency-log proof is not yet validated — signing time is checked only against the Fulcio certificate's own ~10-minute validity window. OCI provenance is not provisional.🐛 Bug Fixes
duplicate "initialize" received, which also unblocks vMCP aggregating stdio backends (#6153)initializeon a live connection behind the transparent proxy now receives a fresh session instead of a hard failure, because the proxy no longer forwards a session ID oninitialize(#6152)github-mcp-serverv1.6.0 no longer oscillate between the Modern and Legacy revisions and fail roughly half their health checks — a Modern promotion must now win a confirmingserver/discoverprobe rather than trusting the negotiated version alone (#6158)io.modelcontextprotocol/logLevel_metakey that replaced the removedlogging/setLevelRPC (#6140)_meta(trace ids, custom fields) onresources/readresults, matching what the Modern path already delivered (#6180)find_tool'stool_keywordsinput now actually affects results instead of being decoded and dropped, and it drives the lexical BM25 arm whiletool_descriptiondrives semantic matching (#6124)call_toolnow accepts the common LLM malformation wheretool_nameis nested insideparameters, and a genuinely missingtool_nameproduces an error that states the expected shape and lists the parameter names received (#6150)server.jsonunder%LOCALAPPDATA%are now protected with an explicit DACL granting only the ToolHive user and SYSTEM, and are ownership-validated before being trusted — POSIX mode bits are advisory on NTFS, so any local account with Modify could previously rewrite thenpipe://discovery URL and redirect the next MCP client (#5951)call_tooltarget through the same decoder dispatch uses, closing three case-sensitivity divergences that could skip a policy check or drop arguments (#6175)🧹 Misc
pkg/telemetry/providers(~2,900 LOC) is deleted in favour of the verbatim graduation intoolhive-core, with no change to emitted telemetry (#6146)pkg/recoverybecomes a thin shim overtoolhive-core/recovery, keeping ToolHive's OTel and Sentry wiring through a panic-handler hook (#6145)toolhive-core's semconv preset instead of a local literal; the boundaries are unchanged (#6144)LevelAudit, andNewAuditLoggerbecome aliases overtoolhive-core/auditwith byte-identical values, so the audit wire format is untouched (#6148)ida-pro-mcpe2e image by digest after an upstream rebuild pulled in the breaking mcp Python SDK 2.0.0, and addedtest/e2e/images/**to the lifecycle suite's trigger filter so an image change can no longer skip the tests that consume it (#6159)mcp-server-timee2e image by digest for the same upstream breakage, unblocking the proxy suites (#6160)timeout waiting for process kube-apiserver to stopflake — 32 of the job's last 51 failures — by awaiting manager shutdown before tearing down envtest (#6179)📦 Dependencies
github.com/stacklok/toolhive-coregithub.com/stacklok/toolhive-cataloggithub.com/tailscale/hujsonb80ff77coverallsapp/github-action8d6379egithub/codeql-actionf205ea1anthropics/claude-code-actiontoolhive-corewas bumped across #6144, #6146, and #6180 rather than by a dependency PR; v0.0.38 also carries transitive bumps to aws-sdk-go-v2, go-containerregistry, moby/client, prometheus, and otel.👋 Welcome to our newest contributor: @Tanguille 🎉
Full commit log
What's Changed
New Contributors
Full Changelog: stacklok/toolhive@v0.41.0...v0.42.0
🔗 Full changelog: stacklok/toolhive@v0.41.0...v0.42.0
Configuration
📅 Schedule: (in timezone Europe/London)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, 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.