Skip to content

Release v0.30.0#5539

Merged
JAORMX merged 1 commit into
mainfrom
release/v0.30.0
Jun 16, 2026
Merged

Release v0.30.0#5539
JAORMX merged 1 commit into
mainfrom
release/v0.30.0

Conversation

@toolhive-release-app

Copy link
Copy Markdown
Contributor

Release v0.30.0

Version Bump

minor release

Files Updated

  • VERSION
  • deploy/charts/operator-crds/Chart.yaml (path: version)
  • deploy/charts/operator-crds/Chart.yaml (path: appVersion)
  • deploy/charts/operator/Chart.yaml (path: version)
  • deploy/charts/operator/Chart.yaml (path: appVersion)
  • deploy/charts/operator/values.yaml (path: operator.image)
  • deploy/charts/operator/values.yaml (path: operator.toolhiveRunnerImage)
  • deploy/charts/operator/values.yaml (path: operator.vmcpImage)
  • Helm chart docs (via helm-docs)

Next Steps

  1. Review this PR
  2. Merge to main
  3. Release automation will handle the rest

Checklist

  • Version bump is correct
  • All CI checks pass

Release-Triggered-By: jerm-dro
@github-actions github-actions Bot added the size/XS Extra small PR: < 100 lines changed label Jun 16, 2026
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.83%. Comparing base (5310d73) to head (9c8732b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5539      +/-   ##
==========================================
- Coverage   69.84%   69.83%   -0.02%     
==========================================
  Files         647      647              
  Lines       65796    65796              
==========================================
- Hits        45957    45949       -8     
- Misses      16494    16502       +8     
  Partials     3345     3345              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JAORMX JAORMX merged commit bc4bedd into main Jun 16, 2026
42 checks passed
@JAORMX JAORMX deleted the release/v0.30.0 branch June 16, 2026 18:55
@github-actions

Copy link
Copy Markdown
Contributor

📝 Generated release notes for v0.30.0

Auto-generated by the release-notes skill. Review and, if good, apply with:

gh release edit v0.30.0 --notes-file <paste-below>.md
Click to expand release notes

🚀 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

  • AuthorizerFactory Go interface gains a required ConfigKey() 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)
Migration guide: AuthorizerFactory.ConfigKey()

Who is affected: Only downstream Go developers who import ToolHive as a module and implement the pkg/authz/authorizers.AuthorizerFactory interface themselves (a private fork or closed-source authorizer backend). All in-tree backends (Cedar → "cedar", HTTP PDP → "pdp") and test mocks are migrated in this release. The JSON config envelope ({"version","type","<configKey>": ...}) is unchanged, so Kubernetes/operator, CRD, and thv CLI users are unaffected.

The interface gained a new required method ConfigKey() string, and Register() now panics at startup if a factory returns a reserved key ("", "version", or "type").

Before

type MyFactory struct{}

func (*MyFactory) ValidateConfig(rawConfig json.RawMessage) error { /* ... */ }
func (*MyFactory) CreateAuthorizer(rawConfig json.RawMessage, serverName string) (authorizers.Authorizer, error) { /* ... */ }

func init() {
    authorizers.Register("mybackend", &MyFactory{})
}

After

type MyFactory struct{}

// New: required by AuthorizerFactory in v0.30.0.
// Must be non-empty and not "version" or "type".
func (*MyFactory) ConfigKey() string { return "mybackend" }

func (*MyFactory) ValidateConfig(rawConfig json.RawMessage) error { /* unchanged */ }
func (*MyFactory) CreateAuthorizer(rawConfig json.RawMessage, serverName string) (authorizers.Authorizer, error) { /* unchanged */ }

func init() {
    authorizers.Register("mybackend", &MyFactory{}) // now panics if ConfigKey() is reserved
}

Migration steps

  1. Add a ConfigKey() string method to each out-of-tree AuthorizerFactory implementation, returning the non-empty JSON key under which your backend's config is nested.
  2. Ensure the returned key is not "", "version", or "type", and does not collide with in-tree keys ("cedar", "pdp").
  3. Recompile. No changes to ValidateConfig/CreateAuthorizer and no wire-format/JSON changes are required.

PR: #4777

🆕 New Features

  • Rate limiting can now be configured on a VirtualMCPServer via spec.config.rateLimiting (shared and per-user token buckets, backed by Redis session storage). (#5276)
  • New backend-agnostic MCPAuthzConfig CRD decouples authorization config from workloads and lets any registered authorizer backend (Cedar, HTTP PDP) be referenced via authzConfigRef on MCPServer, MCPRemoteProxy, and VirtualMCPServer. (#4777)
  • VirtualMCPServer gains spec.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)
  • MCPRemoteProxy gains spec.replicas and spec.sessionStorage for high availability, mirroring MCPServer and VirtualMCPServer: run multiple replicas behind a load balancer with Redis-backed shared session state. (#5237)
  • The obo external-auth type on MCPExternalAuthConfig now 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 (reports Valid=False / EnterpriseRequired). (#5494)
  • New disableUpstreamTokenInjection flag 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, and thv llm proxy start gain a --skip-browser flag 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 Large before 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-Host to remote upstreams, fixing cross-host redirect loops where upstreams echoed the proxy hostname; X-Forwarded-For and X-Forwarded-Proto are still sent. (#4168)

🧹 Misc

  • Carry RateLimitMiddleware through the vMCP buildServeConfig path so the field is not dropped during the Serve migration (fixes a broken main). (#5500)
  • Apply the compound (kind, name) listMapKey to MCPOIDCConfigStatus and MCPExternalAuthConfigStatus referencingWorkloads so cross-kind name reuse stays distinct under merge-patch (data-safe schema change). (#5508)
  • Migrate the MCPOIDCConfig and MCPExternalAuthConfig controllers to MutateAndPatchStatus/MutateAndPatchSpec to avoid clobbering foreign-owned status conditions. (#5509)
  • Route the vMCP Serve path 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 Serve path 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 RunConfig seam (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 MCPOIDCConfigoidcConfigRef → runconfig path. (#5536)
  • Add reference docs and a kind-cluster upgrade-guide walkthrough for the storage-version migrator. (#5451)
  • Add a /retest comment 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_run instead of the unsupported release event. (#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

Full Changelog: v0.29.3...v0.30.0

🔗 Full changelog: v0.29.3...v0.30.0

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

Labels

release size/XS Extra small PR: < 100 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant