v0.30.0
🚀 Toolhive v0.30.0 is live!
This release expands the Virtual MCP server with rate limiting, header passthrough, and high-availability building blocks, introduces a new backend-agnostic authorization CRD, and hardens every MCP proxy against request-body and slow-client denial-of-service vectors — alongside the continuing vMCP core-extraction refactor.
⚠️ Breaking Changes
AuthorizerFactoryGo interface gains a requiredConfigKey()method — out-of-tree Go code that implements its own authorizer backend must add the method to compile. Kubernetes, CRD, and CLI users are not affected. (migration guide)
🆕 New Features
- Rate limiting can now be configured on a
VirtualMCPServerviaspec.config.rateLimiting(shared and per-user token buckets, backed by Redis session storage). (#5276) - New backend-agnostic
MCPAuthzConfigCRD decouples authorization config from workloads and lets any registered authorizer backend (Cedar, HTTP PDP) be referenced viaauthzConfigRefonMCPServer,MCPRemoteProxy, andVirtualMCPServer. (#4777) VirtualMCPServergainsspec.passthroughHeaders, an allowlist of incoming header names that vMCP forwards unchanged to every backend it calls — enabling backends that authenticate per-user from a header (e.g.x-mcp-api-key) to be used through vMCP. (#5466)MCPRemoteProxygainsspec.replicasandspec.sessionStoragefor high availability, mirroringMCPServerandVirtualMCPServer: run multiple replicas behind a load balancer with Redis-backed shared session state. (#5237)- The
oboexternal-auth type onMCPExternalAuthConfignow exposes a real configuration schema (tenantId,authority,clientId,clientSecretRef,audience,scopes,subjectTokenProviderName,cacheSkew) for the Microsoft Entra On-Behalf-Of flow; the type remains inert in upstream builds (reportsValid=False/EnterpriseRequired). (#5494) - New
disableUpstreamTokenInjectionflag on the embedded auth server authenticates MCP clients via OAuth while forwarding an unauthenticated request to the backend — useful for proxying public MCP servers with client-side auth. (#4168) thv llm setup,thv llm token, andthv llm proxy startgain a--skip-browserflag that prints the OIDC authorization URL instead of opening a browser, for headless/SSH/CI environments. (#5533)
🐛 Bug Fixes
- Inbound request bodies on the MCP proxies (streamable, httpsse, transparent) and the vMCP server are now capped at 8MB and rejected with
413 Request Entity Too Largebefore buffering, closing an unbounded-buffering memory-exhaustion vector (embedded OAuth endpoints are capped at 64KB). Behavior change: clients sending a single message larger than 8MB — e.g. large inline base64 content — will now be rejected; the limit is not yet configurable. (#5492) - A 30-second request read timeout is now applied to the proxy servers, the management API server, and
thv mcp serve, preventing slow or stalled uploads from holding connections open indefinitely. Behavior change: request reads taking longer than 30s are terminated; long-lived SSE/streaming responses are unaffected, and the timeout is not yet configurable. (#5501) - The transparent proxy no longer forwards
X-Forwarded-Hostto remote upstreams, fixing cross-host redirect loops where upstreams echoed the proxy hostname;X-Forwarded-ForandX-Forwarded-Protoare still sent. (#4168)
🧹 Misc
- Carry
RateLimitMiddlewarethrough the vMCPbuildServeConfigpath so the field is not dropped during the Serve migration (fixes a brokenmain). (#5500) - Apply the compound
(kind, name)listMapKey toMCPOIDCConfigStatusandMCPExternalAuthConfigStatusreferencingWorkloadsso cross-kind name reuse stays distinct under merge-patch (data-safe schema change). (#5508) - Migrate the
MCPOIDCConfigandMCPExternalAuthConfigcontrollers toMutateAndPatchStatus/MutateAndPatchSpecto avoid clobbering foreign-owned status conditions. (#5509) - Route the vMCP
Servepath through the core for capability advertising and call routing, replacing the discovery-into-context middleware. (#5491) - Label the audit backend at the call site on the
Servepath to eliminate per-request capability re-aggregation. (#5512) - Add vMCP core/server config derivation helpers, consolidating transport defaulting to a single edge resolver. (#5513)
- Add a generic
RunConfigseam (AdditionalMiddlewareConfigs) for handler-supplied middleware configs. (#5495) - Add Serve-path test coverage for authz/annotation omission and for the AS runner, status reporter, optimizer, and health-monitor lifecycles. (#5482, #5506)
- Add an integration test for the
MCPOIDCConfig→oidcConfigRef→ runconfig path. (#5536) - Add reference docs and a kind-cluster upgrade-guide walkthrough for the storage-version migrator. (#5451)
- Add a
/retestcomment workflow (with trusted-user gating and app-owner support) to re-run failed GitHub Actions. (#5510, #5515) - Fix the Generate Release Notes workflow to trigger via
workflow_runinstead of the unsupportedreleaseevent. (#5490) - Pre-pull the time server image in the proxy E2E job to stop intermittent flakes. (#5534)
📦 Dependencies
| Module | Version |
|---|---|
container / docker libraries |
v0.21.6 |
aws-sdk-go-v2 monorepo |
v1.32.25 |
github.com/pressly/goose/v3 |
v3.27.1 |
github.com/lestrrat-go/httprc/v3 |
v3.0.6 |
golang.org/x/exp/jsonrpc2 |
c48552f (digest) |
anthropics/claude-code-action |
d5726de (digest) |
Full commit log
What's Changed
- Trigger release notes via workflow_run not release event by @reyortiz3 in #5490
- Cover Serve-path authz and annotation-enrichment omission by @tgrunnagle in #5482
- Add storage-version migration docs + upgrade-guide walkthrough by @ChrisJBurns in #5451
- Configure rate limits on VirtualMCPServer PR B 1 by @Sanskarzz in #5276
- Carry RateLimitMiddleware through vMCP buildServeConfig by @ChrisJBurns in #5500
- Add MCPAuthzConfig CRD for backend-agnostic authorization by @JAORMX in #4777
- Add request timeouts to MCP proxy servers by @ChrisJBurns in #5501
- Enforce request body size limits on proxies and vMCP by @ChrisJBurns in #5492
- Replace discovery-into-context with direct VMCP calls by @tgrunnagle in #5491
- Define OBOConfig CRD schema for Entra OBO flow by @tgrunnagle in #5494
- Allow MCPRemoteProxy to work without upstream or client auth by @aron-muon in #4168
- Use compound listMapKey on sibling config statuses by @ChrisJBurns in #5508
- Add retest workflow for GitHub Actions by @ChrisJBurns in #5510
- Cover Serve-path lifecycle for AS runner, status, optimizer, health by @tgrunnagle in #5506
- Add RunConfig seam for injected middleware configs by @tgrunnagle in #5495
- Update retest workflow to include app-owner by @ChrisJBurns in #5515
- Update container and docker libraries to v0.21.6 by @renovate[bot] in #5519
- Update aws-sdk-go-v2 monorepo to v1.32.25 by @renovate[bot] in #5518
- Update anthropics/claude-code-action digest to d5726de by @renovate[bot] in #5516
- Update golang.org/x/exp/jsonrpc2 digest to c48552f by @renovate[bot] in #5517
- Update module github.com/pressly/goose/v3 to v3.27.1 by @renovate[bot] in #5524
- Add passthroughHeaders to VirtualMCPServer for header forwarding by @juancarlosm in #5466
- Add replicas and sessionStorage to MCPRemoteProxy for HA by @aron-muon in #5237
- feat(llm): add --skip-browser to llm setup/token/proxy start by @jerm-dro in #5533
- Pre-pull time server image in proxy E2E job by @jerm-dro in #5534
- Migrate sibling config controllers to MutateAndPatchStatus/Spec by @ChrisJBurns in #5509
- Add integration test for MCPOIDCConfig → oidcConfigRef → runconfig path by @Sanskarzz in #5536
- Label audit backend in Serve handlers to avoid re-aggregation by @tgrunnagle in #5512
- Add vMCP core/server config derivation helpers by @tgrunnagle in #5513
- Update module github.com/lestrrat-go/httprc/v3 to v3.0.6 by @renovate[bot] in #5523
- Release v0.30.0 by @toolhive-release-app[bot] in #5539
Full Changelog: v0.29.3...v0.30.0
🔗 Full changelog: v0.29.3...v0.30.0