Skip to content

Releases: stacklok/toolhive

v0.40.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 17 Jul 15:42
505df83

🚀 Toolhive v0.40.0 is live!

This release hardens Virtual MCP authorization end-to-end — explicit HTTP 403 denials, a unified authz gate, and complete capability pagination — while laying the groundwork for agentic auth (RFC 8693 token exchange, the MCP 2026-07-28 revision) and moving MCP protocol handling onto the official modelcontextprotocol/go-sdk. It also fixes network isolation silently breaking --network host workloads and closes an SSRF gap in upstream Dynamic Client Registration.

🆕 New Features

  • The embedded authorization server gains an RFC 8693 OAuth 2.0 Token Exchange grant handler, so an agent can exchange a user's token for a delegated token carrying both the user (sub) and the acting agent (act.sub) — the foundation for agentic delegation (not yet wired into the server) (#5822).
  • ToolHive's request-parsing layer now understands the upcoming stateless MCP 2026-07-28 ("Modern") revision — a revision classifier, the Mcp-Method/Mcp-Name header and _meta vocabulary, and server/discover/subscriptions/listen authz registration — dormant until later slices wire it into proxy routing, with no change to existing traffic (#5834).

🐛 Bug Fixes

  • Virtual MCP now returns an explicit HTTP 403 (with a JSON-RPC error code 403 and a "denied by authorization policy" message) when a Cedar policy denies a tools/call, resources/read, or prompts/get, instead of a misleading -32602 "not found" at HTTP 200 — and records the denial as denied in the audit log (#5841).
  • thv run --network host no longer silently loses outbound connectivity: network isolation (on by default) is dropped for host/none networking with a warning, and explicitly combining --isolate-network=true with --network host now fails fast with an actionable error instead of starting a broken workload (#5794).
  • The Virtual MCP authz gate is hardened so the gate decision, the enforced decision, and the backend forward all derive from a single argument decode, and a backend tool named execute_tool_script now fails loudly instead of being silently shadowed by the code-mode virtual tool (#5850).
  • Virtual MCP capability discovery now follows list pagination cursors to exhaustion, so backends advertising more than one page (>1000 tools, resources, or prompts) no longer have their extra capabilities silently dropped from routing and clients (#5851).
  • Upstream Dynamic Client Registration (DCR) discovery and registration calls are now routed through a private-IP-guarded HTTP client, closing an SSRF vector (CWE-918) — safe by default and honoring the upstream's existing allow_private_ips setting (#5826).
  • Multi-upstream embedded authservers with two or more OAuth2 DCR upstreams requesting the same scopes now register a distinct client per upstream instead of silently reusing the first upstream's credentials, fixing failed or misattributed authorization (#5824).

🧹 Misc

  • Migrated MCP protocol handling from mark3labs/mcp-go to the go-sdk-backed toolhive-core/mcpcompat compatibility shim (a pure, atomic import swap with no call-site logic changes), moving ToolHive onto the official modelcontextprotocol/go-sdk. Note: the stdio bridge currently forwards only progress/message notifications, so tools/list_changed and similar notifications are dropped — dynamic-capability servers may show stale lists until clients re-list (#5729).
  • Resolved temp-dir symlinks in the plugin adapter tests so task test passes on macOS (/var/private/var); product code is unchanged (#5849).

📦 Dependencies

Module Version
github.com/stacklok/toolhive-core v0.0.29
github.com/stacklok/toolhive-catalog v0.20260716.0
github/codeql-action 7188fc3
golang.org/x/exp/jsonrpc2 9ea1abe
Full commit log

What's Changed

  • Add upstream identity to DCR credential cache key by @tgrunnagle in #5824
  • Update github/codeql-action digest to 7188fc3 by @renovate[bot] in #5778
  • Guard upstream-DCR HTTP calls against SSRF by @tgrunnagle in #5826
  • Update module github.com/stacklok/toolhive-core to v0.0.29 by @renovate[bot] in #5840
  • feat: migrate from mark3labs/mcp-go to toolhive-core/mcpcompat (go-sdk) by @JAORMX in #5729
  • Update module github.com/stacklok/toolhive-catalog to v0.20260716.0 by @renovate[bot] in #5843
  • Return HTTP 403 for authz-denied vMCP calls (#5827) by @JAORMX in #5841
  • Update golang.org/x/exp/jsonrpc2 digest to 9ea1abe by @renovate[bot] in #5780
  • Reconcile network isolation with network mode by @JAORMX in #5794
  • Resolve temp dirs in plugin adapter tests by @jhrozek in #5849
  • Add MCP 2026-07-28 revision classification and method vocabulary by @jhrozek in #5834
  • Harden vMCP authz gate: single parse source and reserved-name check by @JAORMX in #5850
  • Add RFC 8693 token exchange handler to the embedded AS by @jhrozek in #5822
  • Follow list pagination cursors in vMCP capability discovery by @JAORMX in #5851
  • Release v0.40.0 by @toolhive-release-app[bot] in #5855

Full Changelog: v0.39.0...v0.40.0

v0.39.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 16 Jul 15:44
4ebb610

What's Changed

  • Stop VirtualMCPServer hot-reconcile on cleared imagePullSecrets by @jhrozek in #5821
  • Update module github.com/stacklok/toolhive-core to v0.0.28 by @renovate[bot] in #5798
  • Add Bedrock compatibility flag to thv llm setup by @aponcedeleonch in #5832
  • Release v0.39.0 by @toolhive-release-app[bot] in #5833

Full Changelog: v0.38.0...v0.39.0

v0.38.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 15 Jul 17:26
1164212

What's Changed

  • Fix tool-filter terminal drain dropping error bodies by @aponcedeleonch in #5816
  • Add Codex App LLM setup support by @JAORMX in #5810
  • Release v0.38.0 by @toolhive-release-app[bot] in #5820

Full Changelog: v0.37.0...v0.38.0

v0.37.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 15 Jul 12:39
90539bb

What's Changed

  • Document operator phase conventions by @buyicoder in #5766
  • Add runtime-stage environment variables to protocol Dockerfiles by @danbarr in #5801
  • Add MCP conformance CI job for thv run proxy by @jhrozek in #5806
  • Prefer context7 for MCP spec lookups, drop hardcoded version by @jhrozek in #5805
  • Expose --allow-docker-gateway in workload API by @kantord in #5799
  • Added spec.podTemplateSpec support to MCPRemoteProxy by @Sanskarzz in #5531
  • Stop SSE filter from leaking tools/list on undecodable lines by @saivedant169 in #5304
  • Validate aud and resource claims in returned ID-JAG JWT by @jhrozek in #5716
  • Flush tool-filter buffer after handler returns by @aponcedeleonch in #5809
  • Release v0.37.0 by @toolhive-release-app[bot] in #5811

New Contributors

Full Changelog: v0.36.0...v0.37.0

v0.36.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 14 Jul 10:40
f58dbd5

What's Changed

  • Add Codex CLI direct-mode support to thv llm setup by @jerm-dro in #5789
  • Use llmgateway mode constants for direct/proxy modes by @JAORMX in #5790
  • Update anthropics/claude-code-action digest to f1bd27c by @renovate[bot] in #5777
  • Release v0.36.0 by @toolhive-release-app[bot] in #5795

Full Changelog: v0.35.0...v0.36.0

v0.35.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 13 Jul 20:04
d2f6812

What's Changed

  • Update module github.com/stacklok/toolhive-core to v0.0.27 by @renovate[bot] in #5736
  • Improve documentation discoverability and cross-linking by @JAORMX in #5739
  • Add ListBackends/LookupBackend to the vMCP core interface by @ChrisJBurns in #5763
  • Rate limiting observability (metrics and tracing) PR A by @Sanskarzz in #5701
  • Suppress GO-2026-5932 (x/crypto/openpgp deprecated-by-design, no fix available) by @JAORMX in #5781
  • Allow HTTP upstream OIDC issuers for in-cluster dev environments by @ChrisJBurns in #5787
  • Release v0.35.0 by @toolhive-release-app[bot] in #5788

Full Changelog: v0.34.0...v0.35.0

v0.34.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 07 Jul 10:40
b084be4

What's Changed

  • Unify token-endpoint URL validation, fix insecure-mode gap by @jhrozek in #5706
  • Allow custom HTTP headers on the OpenAI embedding client by @gabrielcosi in #5704
  • Sort aggregated tools by name for deterministic embedding order by @gabrielcosi in #5709
  • Fix documentation link rot across the repo by @JAORMX in #5711
  • Add plugin install/list/info/uninstall + MaterializationAdapter (Phase 3, THV-0077) by @JAORMX in #5685
  • Make --allow-docker-gateway grant host access, not just unblock it by @eleftherias in #5707
  • Support nested map claims in Cedar authorization for act claim by @jhrozek in #5713
  • Document that --allow-docker-gateway ignores allowed ports by @eleftherias in #5714
  • Replace opaque Step A/B labels in XAA CRD comments by @jhrozek in #5703
  • Unify subject provider defaulting, hard-error xaa by @jhrozek in #5708
  • Update auth and security libraries by @renovate[bot] in #5670
  • Update anthropics/claude-code-action action to v1.0.165 by @renovate[bot] in #5721
  • Update anthropics/claude-code-action digest to 558b1d6 by @renovate[bot] in #5718
  • Update aws-sdk-go-v2 monorepo by @renovate[bot] in #5722
  • Update module github.com/getsentry/sentry-go to v0.47.0 by @renovate[bot] in #5726
  • Update goreleaser/goreleaser-action digest to f06c13b by @renovate[bot] in #5720
  • Update github/codeql-action digest to 54f647b by @renovate[bot] in #5719
  • Update module github.com/stacklok/toolhive-catalog to v0.20260706.0 by @renovate[bot] in #5728
  • Filter upstream auth chain via callback hook by @tgrunnagle in #5725
  • Preserve external annotations on operator Services by @blkt in #5731
  • Drop unconditional ACL password guard from auth server Redis storage by @JAORMX in #5734
  • Remove Amp editor extension clients by @ecgang in #5717
  • Expose UpstreamFilter through authserver.New facade by @tgrunnagle in #5733
  • Add Claude Desktop as an LLM gateway client by @jerm-dro in #5712
  • Fix TOOLHIVE_DEV plain HTTP breaking real OCI registry pulls by @samuv in #5735
  • Release v0.34.0 by @toolhive-release-app[bot] in #5737

New Contributors

Full Changelog: v0.33.0...v0.34.0

v0.33.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 01 Jul 14:10
2aca563

What's Changed

  • Configure rate limits on VirtualMCPServer PR B 2 by @Sanskarzz in #5522
  • Fix stale pre-pulled image tag causing flaky E2E tests by @reyortiz3 in #5693
  • Add XAA auth strategy CRD support by @jhrozek in #5691
  • Update go.starlark.net digest to 529d8e8 by @renovate[bot] in #5520
  • Release v0.33.0 by @toolhive-release-app[bot] in #5698

Full Changelog: v0.32.0...v0.33.0

v0.32.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 30 Jun 16:43
ecb9a8d

🚀 Toolhive v0.32.0 is live!

This release advances vMCP cross-application authentication — adding the XAA (Cross-Application Access) outgoing-auth strategy, the OBO strategy seam, and upstream ID-token propagation — alongside meaningful security hardening (Origin/DNS-rebind protection and a credential-passthrough fix) and a batch of operator and proxy robustness fixes.

⚠️ Breaking Changes

  • Origin validation & SSE CORS hardening — ToolHive now validates the HTTP Origin header (MCP 2025-11-25 DNS-rebind protection) and removed the insecure Access-Control-Allow-Origin: * from the legacy SSE transport. Default local (loopback) usage is unaffected; only browser clients on a non-http://localhost origin need action via the new --allowed-origins flag (migration guide) (#4908).
  • vMCP Go embedders: server.New signature changedpkg/vmcp/server.New dropped its discovery.Manager parameter (7 → 6 args) and the pkg/vmcp/discovery package was removed. CLI, operator, and API behavior are unchanged; only out-of-tree code importing the vMCP library must update its call (migration guide) (#5627).
Migration guide: Origin validation & SSE CORS hardening

Who is affected: Only browser-based MCP clients that make cross-origin requests to ToolHive's SSE transport from an origin that is not http://localhost:<port> / http://127.0.0.1:<port> (for example, a web app served over HTTPS or from a custom hostname). Non-browser clients (IDEs, CLIs, MCP SDK clients) do not send an Origin header and are unaffected. Loopback binds (the default 127.0.0.1) auto-derive a matching local allowlist, so default local usage continues to work. Non-loopback binds without --allowed-origins are not enforced — a warning is logged instead.

Before

# Relied on the implicit Access-Control-Allow-Origin: * wildcard
thv run --transport sse some/mcp-server

After

# Explicitly allow the browser origin that needs cross-origin access
thv run --transport sse --allowed-origins https://my-web-app.example.com some/mcp-server

# The same flag is available on thv proxy:
thv proxy --allowed-origins https://my-web-app.example.com ...

Migration steps

  1. Determine whether any client reaches ToolHive's SSE endpoint cross-origin from a browser. If not, no action is needed.
  2. For each such origin, pass --allowed-origins=<scheme>://<host>:<port> on thv run / thv proxy. The flag is repeatable for multiple origins; matching is exact on scheme + host + port.
  3. Consider migrating browser clients off the legacy SSE transport to the streamable-HTTP transport.

PR: #4908

Migration guide: vMCP server.New signature change

Who is affected: Only out-of-tree Go code that imports github.com/stacklok/toolhive/pkg/vmcp/server and calls server.New directly (e.g. vMCP library embedders). All in-tree callers were updated in the same PR. There is no impact for CLI, operator, or API consumers.

Before

mgr := discovery.NewManager(agg)
srv, err := server.New(ctx, cfg, router, backendClient, mgr, backendRegistry, workflowDefs)

After

// discovery.Manager is removed; capability discovery is now the core's responsibility.
srv, err := server.New(ctx, cfg, router, backendClient, backendRegistry, workflowDefs)

Migration steps

  1. Remove the discovery.Manager argument from your server.New call (and delete the discovery.NewManager(...) construction).
  2. Ensure Config.Aggregator is set — the core now rejects a nil aggregator.
  3. If you set Config.AuthzMiddleware, also set Config.Authz; the combination without Authz now returns ErrInvalidConfig instead of silently allowing all requests.

PR: #5627

🆕 New Features

  • New XAA (Cross-Application Access) outgoing auth strategy implementing the ID-JAG two-step token exchange (RFC 8693 → RFC 7523) for lazy per-backend cross-application access tokens (#5684).
  • Surface upstream ID tokens through the auth middleware, consolidating upstream credential retrieval into a single bulk lookup that carries both access and ID tokens (#5682).
  • Added the vMCP OBO (on-behalf-of) strategy seam — a new optional OBO field on BackendAuthStrategy plus strategy registration and override hook (#5624).
  • The vMCP optimizer can now use an OpenAI-compatible embedding client via the optional embeddingProvider/embeddingModel config fields (defaults to TEI, so existing configs are unchanged) (#5633).
  • Added insecureAllowHTTP to EmbeddedAuthServerConfig so VirtualMCPServer deployers can explicitly allow an http:// issuer for in-cluster hosts, with admission-time validation instead of a proxyrunner crash (#5671).
  • The operator Helm chart now prints a post-install NOTES.txt with verification commands, a minimal MCPServer example, and documentation links (#5656).

🐛 Bug Fixes

  • vMCP now returns HTTP 401 + WWW-Authenticate (RFC 6750) when an upstream provider token is expired and cannot be refreshed, letting clients re-authenticate instead of receiving an opaque error (#5651).
  • Security: the upstreamswap custom header strategy no longer forwards the client's ToolHive JWT in Authorization to the backend; the upstream IdP token is still delivered in the configured custom header (#5661).
  • MCPRemoteProxy now mounts and validates the referenced OIDC CA bundle ConfigMap, fixing silent TLS failures and surfacing a CABundleRefValidated status condition (#5630).
  • Concurrent upstream-token refreshes are now deduplicated on a shared refresher, preventing spurious upstream logouts on IdPs with refresh-token rotation + reuse detection (#5635).
  • The operator no longer perpetually reconciles MCPServers using Redis session storage with a password ref — deploymentNeedsUpdate now mirrors the Redis password env var (#5639).
  • Container-internal target ports are no longer validated against host availability, so SSE/streamable-HTTP workloads keep their registry-defined target port (#5638).
  • Remote proxies now set X-Forwarded-Proto to the upstream scheme, fixing infinite redirect loops when MCPRemoteProxy runs behind a TLS-terminating load balancer (#5646).
  • Upstream-token refresh now fails closed when a rotated refresh token can't be persisted, deleting the stale row instead of stranding a poisoned token (#5636).
  • A typed-nil *Identity stored in the request context is now treated as absent, restoring vMCP fallback identity injection and preventing nil-deref panics (#5653).
  • VirtualMCPServer now always applies its PodTemplateSpec strategic merge patch, so fields like runtimeClassName, topologySpreadConstraints, and hostNetwork are no longer silently dropped (#5641).
  • RestoreSession no longer fabricates a partial identity, and session restore now threads the authenticated request context, fixing cross-pod Redis failover with upstream-auth strategies (#5650).
  • DetachedEnvVarValidator no longer rejects optional secret env vars left blank, fixing spurious "missing required secret" errors when installing registry servers via ToolHive Studio (#5689).

🧹 Misc

  • Landed Phase 2 of the plugin lifecycle epic — new pkg/plugins / pluginsvc packages, validation, and storage migration (no user-facing surface yet) (#5676).
  • Removed the now-unreachable legacy vMCP discovery seam and default router (#5627).
  • Removed redundant stale-ref scans from config controller watches, relying on controller-runtime's old+new object enqueue (−648 lines) (#5626).
  • Removed redundant annotation-based reconcile triggers in config controllers and added the missing MCPToolConfig watch (#5629).
  • Added unit + E2E test coverage for --allow-docker-gateway deny/allow behavior (#5644).
  • Added E2E test infrastructure for upstreamInject identity propagation after cross-pod Redis restore, plus several embedded-auth-server in-cluster fixes (#5660).
  • Expanded CONTRIBUTING guidelines with good-first-issue and good-tenth-issue descriptions (#5634).

📦 Dependencies

Module Version
github.com/stacklok/toolhive-catalog v0.20260629.0
`ant...
Read more

v0.31.0

Choose a tag to compare

@toolhive-release-app toolhive-release-app released this 24 Jun 19:47
493d030

What's Changed

  • Fix incorrect elicitation template paths in comment by @danbarr in #5610
  • Update module github.com/stacklok/toolhive-core to v0.0.26 by @renovate[bot] in #5604
  • Consolidate operator envtest suite bootstrap by @ChrisJBurns in #5602
  • Update core workflow actions to df4cb1c by @renovate[bot] in #5461
  • Index MCPOIDCConfig referencing-workload lookups by @ChrisJBurns in #5608
  • Document level-triggered operator reconciliation rules by @ChrisJBurns in #5609
  • Fix codespell failure: unparseable -> unparsable by @ChrisJBurns in #5612
  • Dedupe operator rules to single canonical homes by @ChrisJBurns in #5613
  • Fix vMCP Deployment update loop with embedded auth server by @danbarr in #5617
  • Migrate issue triage workflow to claude-code-action@v1 by @danbarr in #5620
  • Allow private IPs for in-cluster OIDC and OAuth2 upstream providers by @tgrunnagle in #5618
  • Remove dead legacy session-registration path by @tgrunnagle in #5622
  • Add opt-in code mode decorator for vMCP by @jerm-dro in #5606
  • Index referencing-workload lookups across config controllers by @ChrisJBurns in #5599
  • Fix multi-upstream authorization chain flows by @lorr1 in #5590
  • Remove dead session-factory aggregation and composite mirrors by @tgrunnagle in #5625
  • Release v0.31.0 by @toolhive-release-app[bot] in #5628

Full Changelog: v0.30.1...v0.31.0