Skip to content

Update stacklok/toolhive to v0.41.0 - #1065

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

Update stacklok/toolhive to v0.41.0#1065
renovate[bot] wants to merge 4 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

After this PR opens, .github/workflows/upstream-release-docs.yml adds source-verified content edits for the new release. For stacklok/toolhive, the same workflow also syncs reference assets (CLI help, Swagger) and regenerates the CRD MDX pages.


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 America/New_York)

  • 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: Never, 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.


Docs update for toolhive v0.41.0

At a glance

Upstream stacklok/toolhive v0.40.1v0.41.0
Hand-written changes 2 commit(s)
Reference assets refreshed (separate commit)
Gaps 0
Release contributors 8 auto-assigned (see sidebar)
Action required Spot-check skill-authored prose for accuracy

Summary of changes

  • Updated JSON-RPC rate-limit error.code from -32029 to 429 in docs/toolhive/guides-k8s/rate-limiting.mdx and added an admonition explaining the change.
  • Added 2026-07-28 to the MCP revisions list in docs/toolhive/concepts/mcp-primer.mdx, briefly framing it as a stateless variant alongside 2025-11-25.
  • Added "Storage version migrator (namespace-mode opt-out)" and "Static image discovery for air-gapped installs" subsections to docs/toolhive/guides-k8s/deploy-operator.mdx.
  • Added a "Constrain build-time dependencies" section to docs/toolhive/guides-cli/build-containers.mdx covering the new --build-with flag on uvx:// builds.
  • Updated docs/toolhive/guides-cli/run-mcp-servers.mdx with the same --build-with guidance and a new "Reject unknown MCP protocol versions" section covering --strict-protocol-validation.
  • Added a "Choose an egress proxy backend" section to docs/toolhive/guides-cli/network-isolation.mdx documenting the opt-in TOOLHIVE_NETWORK_PROXY=envoy backend.
  • Added a full "Pin a project's skills for reproducible installs" section to docs/toolhive/guides-cli/skills-management.mdx covering thv skill sync, thv skill upgrade, the toolhive.lock.yaml file, the TOOLHIVE_SKILLS_LOCK_ENABLED gate, and typed exit codes; cross-linked from docs/toolhive/concepts/skills.mdx.
  • Added a "Delegated tokens via RFC 8693 token exchange" section (with delegation-chain audit sub-section) to docs/toolhive/concepts/embedded-auth-server.mdx.
  • Added a "Multi-valued claim normalization" subsection to docs/toolhive/reference/authz-policy-reference.mdx and a matching config bullet in docs/toolhive/concepts/cedar-policies.mdx.

Run cost

Session Turns Cost (USD)
Generation 150 $22.8513
Editorial review 64 $7.6310
Total 214 $30.4823
How this PR was built

Two Claude Opus sessions run per release: a generation pass
(upstream-release-docs skill, 6 phases) followed by a fresh-
context editorial pass (docs-review). Prettier/ESLint
auto-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.

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@renovate renovate Bot added the autogen-docs Pull requests generated by automated release workflows label Jul 28, 2026
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs-website Ready Ready Preview, Comment Jul 28, 2026 8:02pm

Request Review

@github-actions
github-actions Bot marked this pull request as draft July 28, 2026 19:28
@claude

claude Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @renovate[bot]'s task in 25m 11s —— View job


Upstream Release Docs: toolhive v0.41.0 — done

  • Phase 1: Discovery — categorized 100+ commits
  • Phase 2: Deep Dive — verified 13 feature areas against source at tag v0.41.0
  • Phase 3: Audit — impact map + displacement audit
  • Phase 4: Implementation — 11 files edited
  • Phase 5: Validation — docs-review pass applied, prettier + eslint clean
  • Committed and pushed to renovate/stacklok-toolhive-0.x

Summary of hand-written changes

File What
docs/toolhive/guides-k8s/rate-limiting.mdx JSON-RPC rate-limit error.code moved from -32029 to 429
docs/toolhive/concepts/mcp-primer.mdx Added 2026-07-28 revision to the dated-revisions list
docs/toolhive/guides-k8s/deploy-operator.mdx New sections for storage version migrator opt-out (namespace-scope) and opt-in imageDiscovery Deployment (air-gapped)
docs/toolhive/guides-cli/build-containers.mdx New "Constrain build-time dependencies" section for --build-with (uvx only)
docs/toolhive/guides-cli/run-mcp-servers.mdx --build-with guidance + new "Reject unknown MCP protocol versions" section for --strict-protocol-validation
docs/toolhive/guides-cli/network-isolation.mdx New "Choose an egress proxy backend" section for TOOLHIVE_NETWORK_PROXY=envoy
docs/toolhive/guides-cli/skills-management.mdx New reproducible-workflow section: thv skill sync, thv skill upgrade, toolhive.lock.yaml, TOOLHIVE_SKILLS_LOCK_ENABLED gate, typed exit codes
docs/toolhive/concepts/skills.mdx New "Reproducible project-scope installs" section + cross-link
docs/toolhive/concepts/embedded-auth-server.mdx New RFC 8693 token-exchange section with delegation-chain audit sub-section
docs/toolhive/reference/authz-policy-reference.mdx New "Multi-valued claim normalization" subsection
docs/toolhive/concepts/cedar-policies.mdx Config-fields bullet for multi_valued_claims

Build note: npm run build on this runner fails at plugin load because the mcp-metadata-plugin requires the thv binary on PATH, which isn't installed on the CI runner used for this job. This is an environmental issue unrelated to the doc changes. npm run eslint and npm run prettier both pass on the changed files, and CI on the PR will run the full build against a full environment.

Cover the v0.41.0 changes that need prose: rate-limit JSON-RPC code
change from -32029 to 429, MCP 2026-07-28 revision, operator storage
version migrator default and namespace opt-out, opt-in image-discovery
Deployment, --build-with on uvx builds, --strict-protocol-validation,
Envoy egress backend, reproducible project skills workflow, embedded
authorization server RFC 8693 token exchange with delegation audit,
and Cedar multi-valued claim normalization.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@claude

claude Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @renovate[bot]'s task in 6m 41s —— View job


Editorial review: toolhive v0.41.0 docs — done

  • Identify hand-written files (skipped auto-generated CLI/API/CRD content)
  • Run /docs-review across all in-scope files
  • Apply actionable fixes
  • npm run prettier:fix and npm run eslint:fix — both clean
  • Commit and push

Editorial changes applied

File Fix
docs/toolhive/guides-k8s/deploy-operator.mdx Structural. Moved the new "Static image discovery for air-gapped installs" H3 out of "Operator deployment modes" (which is scoped to cluster vs. namespace mode) into the "Customize the operator" section next to the other image/Helm-values H3s. Storage version migrator stays under deployment modes since it's namespace-mode-specific.
docs/toolhive/concepts/embedded-auth-server.mdx Rephrased the delegated-token intro to address the reader directly ("Use this pattern when an agent framework needs to ...") instead of the impersonal "An agent framework uses ...".
docs/toolhive/guides-k8s/rate-limiting.mdx Named the reserved JSON-RPC code range (-32020 to -32099) in the change note instead of the vague "a range reserved by the MCP 2026-07-28 spec".
docs/toolhive/concepts/cedar-policies.mdx Reworded the multi_valued_claims bullet to drop the jargon ("OAuth scope-shaped values") and lead with concrete example claim names.
docs/toolhive/guides-cli/build-containers.mdx Promoted the "uvx only" admonition from :::info to :::warning; using --build-with on npx:// or go:// is a hard error, so a warning matches the severity.

Verified against upstream at v0.41.0

  • TOOLHIVE_SKILLS_LOCK_ENABLED env var name and gate behavior (pkg/skills/feature_gate.go)
  • TOOLHIVE_NETWORK_PROXY accepts empty/squid/envoy and errors otherwise (pkg/container/docker/networkproxy.go)
  • Envoy backend translates both AllowHost and AllowPort into Envoy RBAC (pkg/container/docker/envoy.go)
  • --strict-protocol-validation flag and help text match (cmd/thv/app/run_flags.go)
  • Modern revision is 2026-07-28 and is stateless, no initialize, per-request metadata in _meta (pkg/mcp/revision.go)
  • maxDelegationDepth = 10 at token exchange with refusal on exceed (pkg/authserver/server/tokenexchange/handler.go)
  • Cedar multi_valued_claims config field name (pkg/authz/authorizers/cedar/core.go)

Files not modified

Passed on all other v0.41.0 hand-written pages after review — the prose was already accurate, appropriately scoped, and consistent with the rest of the section it lives in.
· Latest commit

- Move air-gapped image discovery out of deployment-modes section, into
  the operator customization section where the other image and Helm
  values live. The parent section is scoped to cluster vs. namespace
  mode; static image discovery is orthogonal.
- Rephrase the delegated-token intro to address the reader directly
  rather than starting with "An agent framework uses ..."
- Name the reserved JSON-RPC code range in the rate-limit change note.
- Reword the cedar multi_valued_claims bullet to drop the jargon
  ("scope-shaped values") and lead with an example.
- Promote the --build-with "uvx only" admonition to a warning; passing
  it to npx/go fails.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autogen-docs Pull requests generated by automated release workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants