Skip to content

chore(deps): update dependency stacklok/toolhive to v0.41.0 - #2537

Open
renovate[bot] wants to merge 2 commits into
mainfrom
renovate/stacklok-toolhive-0.x
Open

chore(deps): update dependency stacklok/toolhive to v0.41.0#2537
renovate[bot] wants to merge 2 commits into
mainfrom
renovate/stacklok-toolhive-0.x

Conversation

@renovate

@renovate renovate Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Update Change
stacklok/toolhive minor v0.40.1v0.41.0

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


Release Notes

stacklok/toolhive (stacklok/toolhive)

v0.41.0

Compare Source

🚀 Toolhive v0.41.0 is live!

This release delivers first-class support for the new MCP 2026-07-28 ("Modern") specification revision across every ToolHive surface — the transport proxies, the transparent proxy, and Virtual MCP now recognize, serve, and bridge both the session-based 2025-11-25 revision and the new stateless revision, including mixed client×backend combinations. It also ships a reproducible project-skills workflow (thv skill sync/upgrade with a lock file and Sigstore groundwork), an opt-in Envoy network-isolation backend, and RFC 8693 token exchange with full delegation-chain auditing.

⚠️ Breaking Changes

  • Storage version migrator is now enabled by default in the operator Helm chart — namespace-scoped installs (operator.rbac.scope=namespace) fail helm upgrade at render time unless they set operator.features.storageVersionMigrator: false; cluster-scoped installs need no action (#​5603)
  • JSON-RPC batch requests are now rejected — top-level arrays get HTTP 400 / -32600 instead of being executed; batches previously bypassed authorization, tool filtering, and audit, and MCP removed batching in 2025-06-18, so send individual requests (#​5931)
  • Rate-limit JSON-RPC error code moved from -32029 to 429 — the MCP 2026-07-28 spec reserves -32020..-32099; clients branching on error.code == -32029 must match 429 (the HTTP 429 status, Retry-After header, and data.retryAfterSeconds are unchanged) (#​6120)
Migration guide: storage version migrator default

The chart now enables the StorageVersionMigrator controller by default (operator.features.storageVersionMigrator: true), and a new chart validation rejects that combination with operator.rbac.scope=namespace — the controller cannot sync its cluster-scoped CRD informer under namespace RBAC. Affected users see helm install/helm upgrade fail with:

operator.features.storageVersionMigrator requires operator.rbac.scope=cluster

Cluster-scoped installs (the chart default) need no action: the operator pod restarts once with the migrator enabled and begins automatically trimming status.storedVersions on ToolHive CRDs — the precondition for a future release to drop deprecated API versions. No new pods or RBAC objects are created. To opt out anyway, set operator.features.storageVersionMigrator: false.

Namespace-scoped installs must opt out explicitly:

Before
operator:
  rbac:
    scope: namespace
After
operator:
  rbac:
    scope: namespace
  features:
    storageVersionMigrator: false
Migration steps
  1. Check whether you are affected: helm get values <release> -n <ns> — you are affected if operator.rbac.scope is namespace and operator.features.storageVersionMigrator is unset or true.
  2. Add operator.features.storageVersionMigrator: false to your values (or pass --set operator.features.storageVersionMigrator=false).
  3. Run helm upgrade as usual.
  4. Since namespace-scoped installs cannot run the migrator, plan to clean CRD status.storedVersions by other means (e.g. a one-off run of kube-storage-version-migrator) before any future release drops a deprecated CRD version. See docs/operator/storage-version-migration.md.

PR: #​5603

Migration guide: JSON-RPC batch rejection and rate-limit error code

Batch requests (#​5931) — affects only clients sending JSON-RPC batches (removed from MCP in 2025-06-18); no conformant 2025-11-25 or 2026-07-28 client emits them.

Before
[{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{...}},
 {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{...}}]
After

Each request must be its own POST; a batch now returns:

{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"Invalid Request: batch requests are not supported"}}

Rate-limit error code (#​6120) — affects only clients branching on the JSON-RPC error.code for backoff.

Before
{"jsonrpc":"2.0","error":{"code":-32029,"message":"rate limited","data":{"retryAfterSeconds":30}}}
After
{"jsonrpc":"2.0","error":{"code":429,"message":"rate limited","data":{"retryAfterSeconds":30}}}
Migration steps
  1. Replace any JSON-RPC batch sends with sequential or concurrent single requests.
  2. Update rate-limit handling to match error.code == 429 — or, better, key off the HTTP 429 status or data.retryAfterSeconds, which are stable across versions.
Upgrade notes (not breaking, worth knowing)
  • HMAC secrets are now used byte-for-byte (#​6067): if your HMACSecretRefs secret file carried leading/trailing whitespace bytes, previously-minted authorization codes and refresh tokens fail validation once after upgrade and clients re-authenticate; ensure the mounted secret is exactly the raw random bytes (no trailing newline).
  • Denial/error responses are now spec-conformant JSON-RPC (#​5944, #​6055, #​6066, #​6068): correct envelope, standard error codes instead of HTTP statuses (500→-32603), id omitted rather than null, generic denial messages, and filtered tool calls answered with -32602 over HTTP 200 instead of a bodyless 400 — monitoring or scripts keyed to the old malformed shapes need updating.

🆕 New Features

MCP 2026-07-28 ("Modern") spec support
  • ToolHive now speaks the MCP 2026-07-28 stateless revision end to end, negotiating both revisions per backend via go-sdk v1.7 (#​5993)
  • The streamable and transparent proxies classify and serve Modern stateless requests alongside Legacy session traffic (#​5839, #​5884)
  • Virtual MCP serves Modern clients directly (#​5953), classifies request revisions at the client edge (#​5913), and resolves each backend's revision independently (885e8b1)
  • Era-mismatched client×backend combinations are bridged in vMCP, so a Modern client can use Legacy backends and vice versa (#​6006)
  • Modern client-facing dispatch is complete with listen-stream support and pagination (#​6050), gated per capability instead of a global kill-switch (#​6033)
  • vMCP falls back to Legacy when a backend's revision probe is inconclusive, keeping health checks and aggregation resilient (#​6001)
  • Mid-call elicitation/sampling refusals to Modern clients are classified per spec with the new error codes (#​6061), and the typed input_required seam lands as groundwork for MRTR (SEP-2322) (#​6074)
  • Reserved io.modelcontextprotocol/* keys are stripped from backend response _meta so backends cannot spoof protocol metadata (#​6024)
  • W3C trace context now propagates through outbound MCP _meta (SEP-414), joining backend spans to the client→proxy→server trace (#​5964)
  • Tool definitions carrying invalid x-mcp-header annotations (SEP-2243) are rejected as the spec requires (#​6013)
  • The readiness probe sends the current MCP protocol version instead of a hardcoded 2024-11-05 (#​5940)
  • Opt-in strict MCP-Protocol-Version header validation for the streamable proxy (#​5957)
Virtual MCP conformance and aggregation
  • vMCP is now MCP-conformant: completions, resource templates, subscriptions, and mid-call server→client forwarding all work (#​5875)
  • The streamable HTTP proxy supports GET listen streams and routes server-to-client messages per session, so progress, sampling, and elicitation reach clients (#​5934)
  • Backend list_changed notifications are consumed and propagated to clients for tools (#​5965) and for resources and prompts (#​5971)
  • The aggregator resolves cross-backend name conflicts for resources, resource templates, and prompts, not just tools (#​6075), and drops ambiguous prompt names instead of failing aggregation (#​6099)
  • tools/list pagination completeness is guaranteed for >1000-tool aggregated sets (#​6021)
Reproducible project skills
  • Project-scoped skill installs are pinned in a toolhive.lock.yaml lock file (#​5892, #​5893, #​5894)
  • thv skill sync restores a project's pinned skill set on any machine and verifies on-disk content in CI (#​5895)
  • thv skill upgrade re-resolves pinned skills to newer content without silent lock drift (#​5896)
  • Sync and upgrade gain typed exit codes and a pre-install confirmation gate for scriptable CI use (#​5897)
  • Sigstore signing groundwork for skill OCI artifacts: provenance fields in the lock schema (#​6015), a signer package (#​6023), and commit-signature plumbing with bundle storage (#​6084)
Authentication and token exchange
  • RFC 8693 token exchange is wired into the embedded authorization server's token endpoint (#​5881), with delegated token audience bounded by the subject token (#​5882)
  • Subject tokens from trusted external OIDC issuers (Keycloak, Entra, Okta) can be validated for token exchange (#​5995)
  • Audit logs capture the RFC 8693 act claim and full delegation chain, so "agent X acting for Alice" is distinguishable from Alice (#​6046, refined in #​6096 and adopted as the toolhive-core canonical schema in #​6107)
  • Malformed prior act claims are rejected at token exchange per RFC 8693 §4.1 (#​6114)
  • Dynamically registered OAuth clients renew expiring client secrets automatically (RFC 7591/7592) (#​5377)
  • Multi-valued JWT claims can be normalized to canonical space-delimited form for Cedar policies, unifying Entra/Keycloak/Okta scope shapes (#​5880)
  • Authentication failures, webhook denials, and rate-limit rejections now produce audit events (#​5874, #​6005)
Network isolation
  • An opt-in Envoy network-proxy backend (TOOLHIVE_NETWORK_PROXY=envoy) consolidates egress and ingress into one container (#​5907, seam extracted in #​5906)
  • AllowPort permissions translate into Envoy egress RBAC policy, matching Squid's port ACLs (#​5927)
  • The Envoy backend is hardened with a digest-pinned image and disabled admin interface (#​5949), fixed for Linux Docker Engine readiness (#​5926), and covered by e2e tests (#​5918)
Other
  • thv run and thv build gain a repeatable --build-with flag to constrain build-time dependencies (e.g. --build-with 'mcp<2' for uvx:// packages) (#​6111, #​6116)
  • The operator Helm chart gains an opt-in image-discovery Deployment so air-gapped installs can statically discover runtime images (#​6047)

🐛 Bug Fixes

  • The authz response filter can no longer be bypassed via media-type or status-code tricks by a malicious backend (#​6092)
  • SSE responses are parsed per event rather than per line, closing a tool-list smuggling vector (#​6088); filter failures are framed as proper SSE events instead of being silently ignored (#​6087); and raw SSE buffers are no longer spliced into error text (#​6079)
  • Cedar authorization no longer denies everything when an upstream IdP issues JWT access tokens without referenced identity claims like email (#​6022)
  • VirtualMCPServer now honors MCPOIDCConfig.caBundleRef, fixing OIDC discovery against self-signed issuers (#​4923)
  • Denial and error paths emit conformant JSON-RPC 2.0 with standard error codes, scrubbed error text, and omitted (not null) ids (#​6055, #​6066, #​6068, #​6086)
  • Filtered tool calls return a JSON-RPC error over HTTP 200 instead of a bodyless HTTP 400 (#​5944), and session-not-found 404s echo the request id (#​6031)
  • Streamable-http SSE frames carry event: message, unbreaking spec-lenient clients such as @ai-sdk/mcp (#​5954)
  • Binary HMAC secrets are used as-is instead of being whitespace-trimmed (#​6067)
  • Digest-pinned image pulls (tag@digest) no longer fail at container create (#​5978)
  • thv list no longer poisons workload status when transient Docker errors occur (#​6076), the ingress proxy port is no longer derived from a fixed upstream port (#​6069), and concurrent isolated-workload startups no longer race on network creation and ingress DNS (#​6071, #​6083)
  • Ingress Squid warms upstream connections at startup, removing cold-start latency skew (#​5887)
  • TUF outages no longer hard-fail thv run in warn mode (#​6063)
  • Backend tool schemas keep top-level oneOf/anyOf/enum keywords through vMCP ingestion (#​5990)

🧹 Misc

  • New architecture documentation for vMCP backend revision classification and the negotiate-down rationale (#​6016, #​6017, #​6025)
  • Extensive regression pins guarding the mcp-go → go-sdk migration: per-session security, TTL/DNS-rebind/bridge/schema behaviors, and Redis-backed mixed-era coverage (#​5974, #​5977, #​5981, #​6056)
  • Large e2e reliability and speed investment: parallel Ginkgo procs, reliable readiness waits, and deflaked forwarding/group/dual-era suites (#​6070, #​6012, #​6063, and others)
  • Deterministic swagger docgen and regenerated OpenAPI docs (9ef27fa, #​5970)
  • Shared source-dispatch skeleton for skill sources and preserved inner error codes in the skills API (#​5967, #​5966)
  • WorkflowAuditor event prologue extracted to remove eight-way duplication (#​6122)

📦 Dependencies

Module Version
google.golang.org/grpc v1.82.1 (security)
github.com/klauspost/compress v1.18.7 (security, #​6041)
github.com/stacklok/toolhive-catalog v0.20260727.0
actions/checkout digest d23441a
github/codeql-action digest e4fba86
golang/govulncheck-action digest 032d455
anthropics/claude-code-action digest be7b93b

👋 Welcome to our newest contributors: @​amir-rezaei and @​stantheman0128 🎉

Full commit log

What's Changed

New Contributors

Full Changelog: stacklok/toolhive@v0.40.1...v0.41.0

🔗 Full changelog: stacklok/toolhive@v0.40.1...v0.41.0


Configuration

📅 Schedule: (in timezone Europe/London)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 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.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate

renovate Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Edited/Blocked Notification

Renovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR.

You can manually request rebase by checking the rebase/retry box above.

⚠️ Warning: custom changes will be lost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants