ToolHive
v0.46.0 open-sourceToolHive is an enterprise-grade platform for running and managing Model Context Protocol (MCP) servers.
thv ai-plugin upgrade --allow-signer-change <plugin-name>
caBundleRef: my-internal-ca-secret
thv ai-plugin upgrade --allow-signer-change <plugin-name>
caBundleRef: my-internal-ca-secret
thv skill sync --check --clients claude-code
curl -X POST http://127.0.0.1:8080/api/v1beta/workloads \
-H 'Content-Type: application/json' \
-d '{"name":"fetch","image":"ghcr.io/example/fetch:latest"}'
curl -X POST http://127.0.0.1:8080/api/v1beta/skills/sync \
-H 'Content-Type: application/json' \
-d '{"clients": ["claude-code", "cursor"]}'
thv skill sync --check --clients claude-code
curl -X POST http://127.0.0.1:8080/api/v1beta/workloads \
-H 'Content-Type: application/json' \
-d '{"name":"fetch","image":"ghcr.io/example/fetch:latest"}'
curl -X POST http://127.0.0.1:8080/api/v1beta/skills/sync \
-H 'Content-Type: application/json' \
-d '{"clients": ["claude-code", "cursor"]}'
backends:
github:
type: token_exchange
tokenExchange:
tokenUrl: "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token"
clientId: "vmcp-github-exchange"
clientSecretEnv: "GITHUB_EXCHANGE_SECRET"
audience: "github-api"
scopes: ["repo", "read:org"]
backends:
github:
type: token_exchange
tokenExchange:
tokenUrl: "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token"
clientId: "vmcp-github-exchange"
clientSecretEnv: "GITHUB_EXCHANGE_SECRET"
audience: "github-api"
scopes: ["repo", "read:org"]
name: "engineering-vmcp"
groupRef: "engineering-team"
aggregation:
defaultToolVisibility: deny
tools:
- workload: github
- workload: jira
TOOLHIVE_API_TIMEOUT=30s thv skill list
apiVersion: toolhive.stacklok.dev/v1beta1
kind: MCPOIDCConfig
metadata:
name: keycloak-auth
spec:
type: inline
inline:
issuer: http://keycloak:8080/realms/toolhive
jwksUrl: http://keycloak:8080/realms/toolhive/protocol/openid-connect/certs
insecureAllowHTTP: true
name: "engineering-vmcp"
groupRef: "engineering-team"
aggregation:
defaultToolVisibility: deny
tools:
- workload: github
- workload: jira
TOOLHIVE_API_TIMEOUT=30s thv skill list
apiVersion: toolhive.stacklok.dev/v1beta1
kind: MCPOIDCConfig
metadata:
name: keycloak-auth
spec:
type: inline
inline:
issuer: http://keycloak:8080/realms/toolhive
jwksUrl: http://keycloak:8080/realms/toolhive/protocol/openid-connect/certs
insecureAllowHTTP: true
thv skill sync
thv skill upgrade
operator:
rbac:
scope: namespace
features:
storageVersionMigrator: false
thv skill sync
thv skill upgrade
operator:
rbac:
scope: namespace
features:
storageVersionMigrator: false Summary
ToolHive is an open-source platform, licensed under Apache 2.0, that runs Model Context Protocol (MCP) servers in isolated containers and enforces identity and access policy on each request. It is run as a command-line tool, with a Kubernetes operator for cluster deployments, and covers developers connecting clients like Claude Code or Cursor to MCP servers, platform engineers standardizing MCP on existing Kubernetes infrastructure, and enterprises with compliance needs that rule out SaaS. Its own documentation contrasts it with SaaS-based MCP offerings, positioning self-hosting as the reason to choose it. Recent work adds Cedar-based authorization, OAuth token exchange for agentic delegation, and OpenTelemetry tracing for rate limiting, and with 143 contributors and a release cut 16 days ago, it is under active development.
ToolHive is an enterprise-grade platform for running and managing Model Context Protocol (MCP) servers.
What ToolHive answers
Which MCP clients can I connect without custom setup?
ships with support for Claude Code, Cursor, GitHub Copilot, Claude Desktop, and Codex out of the box, alongside direct-mode and proxy-mode LLM connections
Can I enforce different access rules for different agents calling the same backend?
supports per-backend cross-application access tokens through a two-step token exchange, so an agent acting on a user's behalf gets a distinct, auditable token rather than reusing the user's own credentials
What happens to my existing browser-based MCP clients after an update?
a client served from any origin other than localhost now needs to be added to an explicit allow list, since the previous open cross-origin behavior was removed
Do I need to rewrite backend integration code across releases?
some internal interfaces have changed shape between versions, so code calling them directly needs small updates rather than continuing to work unmodified
Can I see why a request was denied?
denials on the proxy path are written to an audit log, giving operators a trail of rejected requests rather than a silent drop
How does it decide which LLM backend to use?
configuration supports several backends including AWS Bedrock and OpenAI-compatible embedding endpoints, selected through setup rather than hardcoded to one provider
Examples
Command line
No option matches that search.
| option | found in | since | description |
|---|
No option matches that search.
Values are placeholders taken from each option’s declared default. Nothing is executed here — the output shown is a recording of a run that already happened.
Release history
- v0.46.0
ToolHive v0.46.0 adds private-CA trust for embedded auth servers and signer-rotation blocking on plugin upgrades.
└──▷ GET THIS VERSION$ git clone --branch v0.46.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.46.0
└──▷ TRY ITUpgrade a plugin while explicitly approving a signer identity change — required when the new release is signed by a different identity than what the lock file recorded.$ thv ai-plugin upgrade --allow-signer-change <plugin-name>
Point an embedded auth server at an in-cluster IdP behind a private CA so ToolHive can reach its OIDC discovery and token endpoints.caBundleRef: my-internal-ca-secret
- ›Adds
--allow-signer-changeflag tothv ai-plugin upgradeso operators can explicitly confirm a signer rotation; without it, upgrades whose signature identity differs from the lock file — or that are unsigned — are blocked with exit code 4 andsigner-change-blocked. - ›Adds
caBundleReffield to OIDC and OAuth2 upstream specs, letting an embedded auth server trust a private CA for discovery, token, user-info, and dynamic client registration calls to that upstream only. - ›Enables the signer-blocking behaviour via the
TOOLHIVE_PLUGINS_LOCK_ENABLEDenvironment variable (experimental plugins lock file).
└──▷ BREAKING ON UPGRADE- !The
operator-crdschart must be upgraded to 0.46.0 before or together with the operator chart; a stale CRD silently prunes the newcaBundleReffield from applied resources instead of rejecting it.
- ›Adds
- v0.46.0
ToolHive v0.46.0 adds private-CA trust for embedded auth servers and signer-rotation blocking on plugin upgrades.
└──▷ GET THIS VERSION$ git clone --branch v0.46.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.46.0
└──▷ TRY ITUpgrade a plugin while explicitly approving a signer identity change — required when the new release is signed by a different identity than what the lock file recorded.$ thv ai-plugin upgrade --allow-signer-change <plugin-name>
Point an embedded auth server at an in-cluster IdP behind a private CA so ToolHive can reach its OIDC discovery and token endpoints.caBundleRef: my-internal-ca-secret
- ›Adds
--allow-signer-changeflag tothv ai-plugin upgradeso operators can explicitly confirm a signer rotation; without it, upgrades whose signature identity differs from the lock file — or that are unsigned — are blocked with exit code 4 andsigner-change-blocked. - ›Adds
caBundleReffield to OIDC and OAuth2 upstream specs, letting an embedded auth server trust a private CA for discovery, token, user-info, and dynamic client registration calls to that upstream only. - ›Enables the signer-blocking behaviour via the
TOOLHIVE_PLUGINS_LOCK_ENABLEDenvironment variable (experimental plugins lock file).
└──▷ BREAKING ON UPGRADE- !The
operator-crdschart must be upgraded to 0.46.0 before or together with the operator chart; a stale CRD silently prunes the newcaBundleReffield from applied resources instead of rejecting it.
- ›Adds
- v0.45.0
ToolHive v0.45.0 adds Sigstore plugin verification, RFC 7523RFC 7523An IETF standard that defines how a JSON Web Token (JWT) can be used as a credential to request an OAuth 2.0 access token, letting a cyber tool authenticate to an API without exchanging a username and password. auth flows, a diagnostics metrics port, and a new Qoder skill client.
└──▷ GET THIS VERSION$ git clone --branch v0.45.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.45.0
└──▷ TRY ITSync skills to only a specific client in CI so that the addition of the newqoderclient does not cause unexpected drift and a non-zero exit.$ thv skill sync --check --clients claude-code
Create a workload via the management API now thatContent-Type: application/jsonis required on state-changing TCP requests.$ curl -X POST http://127.0.0.1:8080/api/v1beta/workloads \ -H 'Content-Type: application/json' \ -d '{"name":"fetch","image":"ghcr.io/example/fetch:latest"}'
Scope a REST skill sync to specific clients so CI pipelines do not unexpectedly expand to all skill-supporting clients after upgrade.$ curl -X POST http://127.0.0.1:8080/api/v1beta/skills/sync \ -H 'Content-Type: application/json' \ -d '{"clients": ["claude-code", "cursor"]}'
- ›Adds
--clientsflag tothv skill syncand{"clients": [...]}body field toPOST /api/v1beta/skills/syncto explicitly scope which skill-supporting clients are targeted on each sync. - ›Adds
qoderas the 18th skill-supporting client, materializing skills into<project>/.qoder/skills/on sync. - ›Enforces
Content-Type: application/jsonon state-changingthv servemanagement API requests over TCP, and adds Origin validation with a loopback-only allowlist on those same listeners. - ›Prometheus metrics move to a dedicated diagnostics port, controlled by a migration switch.
- ›The embedded auth server gains two new RFC 7523 flows.
+4 moreshow less
- ›Plugin artifacts now have end-to-end Sigstore bundle verification; stored bundles and git commit payloads/signatures are rejected with HTTP 422 above 1 MiB.
- ›
thv skill pushnow signs keylessly by default; requires exactly one of--key,--identity-token, or--no-sign. - ›Virtual MCP now honours
operational.timeoutsconfigured values and propagates backend health changes to live sessions. - ›Package names in
npx://,uvx://, andgo://references are now validated against[A-Za-z0-9@/:._+=~[\]-]at build time, blocking shell metacharacter injection into generated Dockerfiles.
└──▷ BREAKING ON UPGRADE- !
thv servemanagement API over TCP now requiresContent-Type: application/jsonon state-changing requests with a body; callers omitting it receive415 Unsupported Media Type. - !Package names in
npx://,uvx://, andgo://references containing characters outside[A-Za-z0-9@/:._+=~[\]-]now fail at build time with an 'invalid package name' error instead of being interpolated into the Dockerfile. - !
thv skill syncwithout--clientsnow targets every skill-supporting client; any skill locked under v0.44.0 will report as drifted on first sync after upgrade, andthv skill sync --checkwill exit non-zero in CI. - !
runtime_config.build_withonnpx:///go://images is now a400 Bad Request;runtime_config.runtime_envis now actually applied (was silently discarded) viaPOST /api/v1beta/workloads. - !
thv skill pushnow returns400when both--keyand--no-signare supplied; exactly one of--key,--identity-token, or--no-signis required. - !Virtual MCP now honours
operational.timeouts; a configured value below 30 s will now actually cut backend calls that previously received the silent 30 s default. - !Exported Go interfaces
plugins.MaterializationAdapter,state.Storewriters,storage.UpstreamTokenStorage, and six function signatures gained required methods or changed signatures. - !The
thv llmlocal proxy now returns401 token_requiredinstead of502 server_errorwhen the stored credential has been rejected by the IdP.
- ›Adds
- v0.45.0
ToolHive v0.45.0 adds Sigstore plugin verification, RFC 7523RFC 7523An IETF standard that defines how a JSON Web Token (JWT) can be used as a credential to request an OAuth 2.0 access token, letting a cyber tool authenticate to an API without exchanging a username and password. auth flows, a diagnostics metrics port, and a new Qoder skill client.
└──▷ GET THIS VERSION$ git clone --branch v0.45.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.45.0
└──▷ TRY ITSync skills to only a specific client in CI so that the addition of the newqoderclient does not cause unexpected drift and a non-zero exit.$ thv skill sync --check --clients claude-code
Create a workload via the management API now thatContent-Type: application/jsonis required on state-changing TCP requests.$ curl -X POST http://127.0.0.1:8080/api/v1beta/workloads \ -H 'Content-Type: application/json' \ -d '{"name":"fetch","image":"ghcr.io/example/fetch:latest"}'
Scope a REST skill sync to specific clients so CI pipelines do not unexpectedly expand to all skill-supporting clients after upgrade.$ curl -X POST http://127.0.0.1:8080/api/v1beta/skills/sync \ -H 'Content-Type: application/json' \ -d '{"clients": ["claude-code", "cursor"]}'
- ›Adds
--clientsflag tothv skill syncand{"clients": [...]}body field toPOST /api/v1beta/skills/syncto explicitly scope which skill-supporting clients are targeted on each sync. - ›Adds
qoderas the 18th skill-supporting client, materializing skills into<project>/.qoder/skills/on sync. - ›Enforces
Content-Type: application/jsonon state-changingthv servemanagement API requests over TCP, and adds Origin validation with a loopback-only allowlist on those same listeners. - ›Prometheus metrics move to a dedicated diagnostics port, controlled by a migration switch.
- ›The embedded auth server gains two new RFC 7523 flows.
+4 moreshow less
- ›Plugin artifacts now have end-to-end Sigstore bundle verification; stored bundles and git commit payloads/signatures are rejected with HTTP 422 above 1 MiB.
- ›
thv skill pushnow signs keylessly by default; requires exactly one of--key,--identity-token, or--no-sign. - ›Virtual MCP now honours
operational.timeoutsconfigured values and propagates backend health changes to live sessions. - ›Package names in
npx://,uvx://, andgo://references are now validated against[A-Za-z0-9@/:._+=~[\]-]at build time, blocking shell metacharacter injection into generated Dockerfiles.
└──▷ BREAKING ON UPGRADE- !
thv servemanagement API over TCP now requiresContent-Type: application/jsonon state-changing requests with a body; callers omitting it receive415 Unsupported Media Type. - !Package names in
npx://,uvx://, andgo://references containing characters outside[A-Za-z0-9@/:._+=~[\]-]now fail at build time with an 'invalid package name' error instead of being interpolated into the Dockerfile. - !
thv skill syncwithout--clientsnow targets every skill-supporting client; any skill locked under v0.44.0 will report as drifted on first sync after upgrade, andthv skill sync --checkwill exit non-zero in CI. - !
runtime_config.build_withonnpx:///go://images is now a400 Bad Request;runtime_config.runtime_envis now actually applied (was silently discarded) viaPOST /api/v1beta/workloads. - !
thv skill pushnow returns400when both--keyand--no-signare supplied; exactly one of--key,--identity-token, or--no-signis required. - !Virtual MCP now honours
operational.timeouts; a configured value below 30 s will now actually cut backend calls that previously received the silent 30 s default. - !Exported Go interfaces
plugins.MaterializationAdapter,state.Storewriters,storage.UpstreamTokenStorage, and six function signatures gained required methods or changed signatures. - !The
thv llmlocal proxy now returns401 token_requiredinstead of502 server_errorwhen the stored credential has been rejected by the IdP.
- ›Adds
- v0.44.0
ToolHive v0.44.0 adds RFC 8693 actor_token support in token exchange and hardens OAuth/DCR endpoints against SSRF.
└──▷ GET THIS VERSION$ git clone --branch v0.44.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.44.0
- ›Supports
actor_tokenin RFC 8693 token exchange flows, enabling delegated identity scenarios where an acting party is distinct from the subject. - ›Guards OAuth token and Dynamic Client Registration (DCR) endpoints against Server-Side Request Forgery (SSRF) attacks.
- ›Supports
- v0.44.0
ToolHive v0.44.0 adds RFC 8693 actor_token support in token exchange and hardens OAuth/DCR endpoints against SSRF.
└──▷ GET THIS VERSION$ git clone --branch v0.44.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.44.0
- ›Supports
actor_tokenin RFC 8693 token exchange flows, enabling delegated identity scenarios where an acting party is distinct from the subject. - ›Guards OAuth token and Dynamic Client Registration (DCR) endpoints against Server-Side Request Forgery (SSRF) attacks.
- ›Supports
- v0.43.0
ToolHive v0.43.0 adds confidential OAuth clients, RFC 8693 delegate clients, multi-line SSE parsing, macOS binary signing, and lock-file plugin tracking.
└──▷ GET THIS VERSION$ git clone --branch v0.43.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.43.0
└──▷ USE ITConfigure an OAuth token-exchange backend in vmcp so that downstream calls use RFC 8693 delegate tokens — now fully reachable after this release.backends: github: type: token_exchange tokenExchange: tokenUrl: "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" clientId: "vmcp-github-exchange" clientSecretEnv: "GITHUB_EXCHANGE_SECRET" audience: "github-api" scopes: ["repo", "read:org"]- ›Adds
pluginskey to the lock file schema, enabling plugin entries to be tracked in lock provenance. - ›Adds
PluginLockServiceand a managed install flag to support plugin lifecycle management through the lock file. - ›Records certificate ref and runner in lock provenance, strengthening supply-chain traceability for installed servers.
- ›Enforces recorded ref and runner fields during skill verification, so provenance is validated at use time.
- ›Enables signing of pushes by default and removes the lock feature gate, making image signing the standard behavior.
+10 moreshow less
- ›Supports confidential clients in dynamic client registration, expanding OAuth client types available to the auth layer.
- ›Makes RFC 8693 delegate (token-exchange) clients reachable and usable, enabling downstream token exchange workflows in
vmcp-config.yaml. - ›Supports parsing of multi-line Modern SSE events, improving compatibility with SSE-based MCP transports.
- ›Signs the macOS
thvbinary with a Developer ID certificate, removing Gatekeeper warnings for macOS users. - ›Adds rate-limiting observability via metrics and tracing (OpenTelemetry), covering the proxy rate-limit path.
- ›Drops the build fingerprint from the proxy
/healthresponse, reducing information exposure on that endpoint. - ›Displays recorded trust state to the user in the CLI, surfacing container image trust information at runtime.
- ›Resets the LLM config when the last tool is torn down, preventing stale LLM configuration from persisting after all tools exit.
- ›Uses a bare
thvcommand as the LLM token helper, simplifying the token-helper integration for LLM clients. - ›Ignores unsupported grant types in CIMD documents, improving interoperability with authorization servers that advertise non-standard grant types.
- ›Adds
- v0.43.0
ToolHive v0.43.0 adds confidential OAuth clients, RFC 8693 delegate clients, multi-line SSE parsing, macOS binary signing, and lock-file plugin tracking.
└──▷ GET THIS VERSION$ git clone --branch v0.43.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.43.0
└──▷ USE ITConfigure an OAuth token-exchange backend in vmcp so that downstream calls use RFC 8693 delegate tokens — now fully reachable after this release.backends: github: type: token_exchange tokenExchange: tokenUrl: "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" clientId: "vmcp-github-exchange" clientSecretEnv: "GITHUB_EXCHANGE_SECRET" audience: "github-api" scopes: ["repo", "read:org"]- ›Adds
pluginskey to the lock file schema, enabling plugin entries to be tracked in lock provenance. - ›Adds
PluginLockServiceand a managed install flag to support plugin lifecycle management through the lock file. - ›Records certificate ref and runner in lock provenance, strengthening supply-chain traceability for installed servers.
- ›Enforces recorded ref and runner fields during skill verification, so provenance is validated at use time.
- ›Enables signing of pushes by default and removes the lock feature gate, making image signing the standard behavior.
+10 moreshow less
- ›Supports confidential clients in dynamic client registration, expanding OAuth client types available to the auth layer.
- ›Makes RFC 8693 delegate (token-exchange) clients reachable and usable, enabling downstream token exchange workflows in
vmcp-config.yaml. - ›Supports parsing of multi-line Modern SSE events, improving compatibility with SSE-based MCP transports.
- ›Signs the macOS
thvbinary with a Developer ID certificate, removing Gatekeeper warnings for macOS users. - ›Adds rate-limiting observability via metrics and tracing (OpenTelemetry), covering the proxy rate-limit path.
- ›Drops the build fingerprint from the proxy
/healthresponse, reducing information exposure on that endpoint. - ›Displays recorded trust state to the user in the CLI, surfacing container image trust information at runtime.
- ›Resets the LLM config when the last tool is torn down, preventing stale LLM configuration from persisting after all tools exit.
- ›Uses a bare
thvcommand as the LLM token helper, simplifying the token-helper integration for LLM clients. - ›Ignores unsupported grant types in CIMD documents, improving interoperability with authorization servers that advertise non-standard grant types.
- ›Adds
- v0.42.1
ToolHive v0.42.1 adds deny-by-default vMCP visibility, external OIDC trusted issuers, composite tool annotations, and a
TOOLHIVE_API_TIMEOUToverride.└──▷ GET THIS VERSION$ git clone --branch v0.42.1 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.42.1
└──▷ USE ITLock down a vMCP group so new workloads are hidden by default and only explicitly listed ones expose tools.name: "engineering-vmcp" groupRef: "engineering-team" aggregation: defaultToolVisibility: deny tools: - workload: github - workload: jiraFail CI faster whenthv skillcalls time out in a slow environment by shortening the API client timeout.$ TOOLHIVE_API_TIMEOUT=30s thv skill listAllow a dev/test inline OIDC config pointing at an in-cluster Keycloak over HTTP to pass URL validation after upgrading.apiVersion: toolhive.stacklok.dev/v1beta1 kind: MCPOIDCConfig metadata: name: keycloak-auth spec: type: inline inline: issuer: http://keycloak:8080/realms/toolhive jwksUrl: http://keycloak:8080/realms/toolhive/protocol/openid-connect/certs insecureAllowHTTP: true- ›Adds
aggregation.defaultToolVisibility: denyto vMCP config so only workloads explicitly listed inaggregation.toolshave their tools advertised, closing the fail-open gap in tool aggregation. - ›Adds
trusted_issuersto the embedded auth server config, enabling agents to exchange subject tokens from external OIDC providers (Entra, Okta, Keycloak) for ToolHive-scoped delegated tokens under a fail-closed RFC 8693 consent policy. - ›Adds
TOOLHIVE_API_TIMEOUTenvironment variable to override the CLI API client timeout forthv skillandthv ai-plugincommands (default is 10 minutes). - ›Adds
insecureAllowHTTP: truefield underspec.inlinein MCPOIDCConfig to explicitly opt in to plain-HTTP issuer and JWKS URLs for dev/test environments; production configs must use HTTPS. - ›Composite tools now support MCP tool annotations (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint), with a conservative fail-closed safety floor derived from the workflow's step tools when none are set explicitly.
└──▷ BREAKING ON UPGRADE- !With Cedar authorization enabled (
--authz-config),POSTrequests withoutContent-Type: application/json(including a missing header) now return400instead of being forwarded unauthorized; all MCP POST clients must sendContent-Type: application/json. - !vMCP tools excluded via
filter,excludeAll, orexcludeAllToolsare no longer directly callable on the Modern (2026-07-28) path —tools/callnow returns-32602at HTTP 400 instead of executing; un-filter the tool or wrap it in a composite tool. - !MCPOIDCConfig resources of
spec.type: inlinewith a plain-HTTP, malformed, or scheme-lessissuerorjwksUrlflip toValid=Falseon next reconcile and block reconciliation of every MCPServer,MCPRemoteProxy, andVirtualMCPServerreferencing them; addinsecureAllowHTTP: trueor switch to HTTPS.
- ›Adds
- v0.42.1
ToolHive v0.42.1 adds deny-by-default vMCP visibility, external OIDC trusted issuers, composite tool annotations, and a
TOOLHIVE_API_TIMEOUToverride.└──▷ GET THIS VERSION$ git clone --branch v0.42.1 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.42.1
└──▷ USE ITLock down a vMCP group so new workloads are hidden by default and only explicitly listed ones expose tools.name: "engineering-vmcp" groupRef: "engineering-team" aggregation: defaultToolVisibility: deny tools: - workload: github - workload: jiraFail CI faster whenthv skillcalls time out in a slow environment by shortening the API client timeout.$ TOOLHIVE_API_TIMEOUT=30s thv skill listAllow a dev/test inline OIDC config pointing at an in-cluster Keycloak over HTTP to pass URL validation after upgrading.apiVersion: toolhive.stacklok.dev/v1beta1 kind: MCPOIDCConfig metadata: name: keycloak-auth spec: type: inline inline: issuer: http://keycloak:8080/realms/toolhive jwksUrl: http://keycloak:8080/realms/toolhive/protocol/openid-connect/certs insecureAllowHTTP: true- ›Adds
aggregation.defaultToolVisibility: denyto vMCP config so only workloads explicitly listed inaggregation.toolshave their tools advertised, closing the fail-open gap in tool aggregation. - ›Adds
trusted_issuersto the embedded auth server config, enabling agents to exchange subject tokens from external OIDC providers (Entra, Okta, Keycloak) for ToolHive-scoped delegated tokens under a fail-closed RFC 8693 consent policy. - ›Adds
TOOLHIVE_API_TIMEOUTenvironment variable to override the CLI API client timeout forthv skillandthv ai-plugincommands (default is 10 minutes). - ›Adds
insecureAllowHTTP: truefield underspec.inlinein MCPOIDCConfig to explicitly opt in to plain-HTTP issuer and JWKS URLs for dev/test environments; production configs must use HTTPS. - ›Composite tools now support MCP tool annotations (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint), with a conservative fail-closed safety floor derived from the workflow's step tools when none are set explicitly.
└──▷ BREAKING ON UPGRADE- !With Cedar authorization enabled (
--authz-config),POSTrequests withoutContent-Type: application/json(including a missing header) now return400instead of being forwarded unauthorized; all MCP POST clients must sendContent-Type: application/json. - !vMCP tools excluded via
filter,excludeAll, orexcludeAllToolsare no longer directly callable on the Modern (2026-07-28) path —tools/callnow returns-32602at HTTP 400 instead of executing; un-filter the tool or wrap it in a composite tool. - !MCPOIDCConfig resources of
spec.type: inlinewith a plain-HTTP, malformed, or scheme-lessissuerorjwksUrlflip toValid=Falseon next reconcile and block reconciliation of every MCPServer,MCPRemoteProxy, andVirtualMCPServerreferencing them; addinsecureAllowHTTP: trueor switch to HTTPS.
- ›Adds
- v0.42.0
ToolHive v0.42.0 adds a full
thv ai-pluginCLI and REST API, a registry catalog, and Sigstore signature verification for skills installs.└──▷ GET THIS VERSION$ git clone --branch v0.42.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.42.0
- ›Adds
thv ai-pluginsubcommand with a full CLI and REST API for end-to-end AI-tool plugin management. - ›Introduces a registry catalog for discovering and managing AI-tool plugins.
- ›Adds Sigstore signature verification for skills at install, sync, and upgrade time.
- ›Enables multiple MCP clients to share a single stdio server simultaneously.
- ›Stabilizes vMCP protocol negotiation, stopping flapping between Modern and Legacy MCP revisions.
+1 moreshow less
- ›Cedar authorization policy is now evaluated against the post-mutation MCP request, closing a bypass window for length-preserving mutating webhook rewrites.
└──▷ BREAKING ON UPGRADE- !
status.referencingWorkloads,status.referenceCount, and the References printer column are removed from all six config CRDs (MCPOIDCConfig,MCPAuthzConfig,MCPExternalAuthConfig,MCPToolConfig,MCPWebhookConfig,MCPTelemetryConfig); replace any automation reading them with workload field queries via-o json | jq. - !Cedar policy and audit records now evaluate against the post-mutation MCP request body; re-audit Cedar policies and update SIEM rules keyed on
typeortarget.namebefore upgrading workloads that combine amutating:entry in--webhook-config(orMCPWebhookConfig.spec.mutating) with Cedar authorization. - !Recovered HTTP panics no longer produce a
slog.Errorlog line or stack trace; log-based alerts on recovered panics will silently stop firing unless Sentry is configured. - !
pkg/telemetry/providersis deleted and twooptimizerdecconstants are removed from the Go API; out-of-tree Go importers must drop references to these before upgrading.
- ›Adds
- v0.42.0
ToolHive v0.42.0 adds a full
thv ai-pluginCLI and REST API, a registry catalog, and Sigstore signature verification for skills installs.└──▷ GET THIS VERSION$ git clone --branch v0.42.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.42.0
- ›Adds
thv ai-pluginsubcommand with a full CLI and REST API for end-to-end AI-tool plugin management. - ›Introduces a registry catalog for discovering and managing AI-tool plugins.
- ›Adds Sigstore signature verification for skills at install, sync, and upgrade time.
- ›Enables multiple MCP clients to share a single stdio server simultaneously.
- ›Stabilizes vMCP protocol negotiation, stopping flapping between Modern and Legacy MCP revisions.
+1 moreshow less
- ›Cedar authorization policy is now evaluated against the post-mutation MCP request, closing a bypass window for length-preserving mutating webhook rewrites.
└──▷ BREAKING ON UPGRADE- !
status.referencingWorkloads,status.referenceCount, and the References printer column are removed from all six config CRDs (MCPOIDCConfig,MCPAuthzConfig,MCPExternalAuthConfig,MCPToolConfig,MCPWebhookConfig,MCPTelemetryConfig); replace any automation reading them with workload field queries via-o json | jq. - !Cedar policy and audit records now evaluate against the post-mutation MCP request body; re-audit Cedar policies and update SIEM rules keyed on
typeortarget.namebefore upgrading workloads that combine amutating:entry in--webhook-config(orMCPWebhookConfig.spec.mutating) with Cedar authorization. - !Recovered HTTP panics no longer produce a
slog.Errorlog line or stack trace; log-based alerts on recovered panics will silently stop firing unless Sentry is configured. - !
pkg/telemetry/providersis deleted and twooptimizerdecconstants are removed from the Go API; out-of-tree Go importers must drop references to these before upgrading.
- ›Adds
- v0.41.0
ToolHive v0.41.0 adds MCP 2026-07-28 spec support,
thv skill sync/upgradewith lock file, RFC 8693 token exchange, and Envoy network isolation.└──▷ GET THIS VERSION$ git clone --branch v0.41.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.41.0
└──▷ TRY ITRestore and verify a project's pinned MCP skill set in CI to ensure every machine uses exactly the locked versions.$ thv skill syncRe-resolve all pinned skills to newer content and updatetoolhive.lock.yamlwithout silent drift.$ thv skill upgradeOpt out of the StorageVersionMigrator on a namespace-scoped Helm install to avoid a brokenhelm upgrade.operator: rbac: scope: namespace features: storageVersionMigrator: false- ›Adds
thv skill syncto restore a project's pinned skill set on any machine and verify on-disk content in CI. - ›Adds
thv skill upgradeto re-resolve pinned skills to newer content without silent lock drift. - ›Pins project-scoped skill installs in a
toolhive.lock.yamllock file, including Sigstore provenance fields. - ›Adds typed exit codes and a pre-install confirmation gate to
thv skill syncandthv skill upgradefor scriptable CI use. - ›Adds opt-in strict MCP-Protocol-Version header validation for the streamable proxy.
+14 moreshow less
- ›Supports the MCP 2026-07-28 stateless ('Modern') spec revision end to end across transport proxies, transparent proxy, and Virtual MCP — bridging era-mismatched client×backend combinations.
- ›Modern client-facing dispatch is gated per capability instead of a global kill-switch, with listen-stream support and pagination.
- ›W3C trace context propagates through outbound MCP
_meta(SEP-414), joining backend spans to the client→proxy→server trace. - ›Wires RFC 8693 token exchange into the embedded authorization server's token endpoint, with delegated token audience bounded by the subject token.
- ›Subject tokens from trusted external OIDC issuers (Keycloak, Entra, Okta) can now be validated for RFC 8693 token exchange.
- ›Audit logs capture the RFC 8693
actclaim and full delegation chain, making 'agent X acting for Alice' distinguishable from Alice. - ›Dynamically registered OAuth clients now renew expiring client secrets automatically (RFC 7591/7592).
- ›Multi-valued JWT claims can be normalized to canonical space-delimited form for Cedar policies.
- ›Backend
list_changednotifications are now consumed and propagated to clients for tools, resources, and prompts. - ›Virtual MCP is now MCP-conformant: completions, resource templates, subscriptions, and mid-call server-to-client forwarding all work.
- ›Guarantees
tools/listpagination completeness for aggregated sets exceeding 1,000 tools. - ›Tool definitions carrying invalid
x-mcp-headerannotations (SEP-2243) are now rejected as the spec requires. - ›Readiness probe now sends the current MCP protocol version instead of a hardcoded 2024-11-05.
- ›Adds an opt-in Envoy network-isolation backend.
└──▷ BREAKING ON UPGRADE- !Namespace-scoped Helm installs (
operator.rbac.scope=namespace) now failhelm upgradeat render time unlessoperator.features.storageVersionMigrator: falseis set, because the StorageVersionMigrator controller is now enabled by default (operator.features.storageVersionMigrator: true). - !JSON-RPC batch requests (top-level arrays) are now rejected with HTTP 400 / error code
-32600instead of being executed; send individual requests. - !Rate-limit JSON-RPC error code changed from
-32029to429; clients branching onerror.code == -32029must match429instead.
- ›Adds
- v0.41.0
ToolHive v0.41.0 adds MCP 2026-07-28 spec support,
thv skill sync/upgradewith lock file, RFC 8693 token exchange, and Envoy network isolation.└──▷ GET THIS VERSION$ git clone --branch v0.41.0 https://github.com/stacklok/toolhive.git # already have the repo? check out this version: $ git checkout v0.41.0
└──▷ TRY ITRestore and verify a project's pinned MCP skill set in CI to ensure every machine uses exactly the locked versions.$ thv skill syncRe-resolve all pinned skills to newer content and updatetoolhive.lock.yamlwithout silent drift.$ thv skill upgradeOpt out of the StorageVersionMigrator on a namespace-scoped Helm install to avoid a brokenhelm upgrade.operator: rbac: scope: namespace features: storageVersionMigrator: false- ›Adds
thv skill syncto restore a project's pinned skill set on any machine and verify on-disk content in CI. - ›Adds
thv skill upgradeto re-resolve pinned skills to newer content without silent lock drift. - ›Pins project-scoped skill installs in a
toolhive.lock.yamllock file, including Sigstore provenance fields. - ›Adds typed exit codes and a pre-install confirmation gate to
thv skill syncandthv skill upgradefor scriptable CI use. - ›Adds opt-in strict MCP-Protocol-Version header validation for the streamable proxy.
+14 moreshow less
- ›Supports the MCP 2026-07-28 stateless ('Modern') spec revision end to end across transport proxies, transparent proxy, and Virtual MCP — bridging era-mismatched client×backend combinations.
- ›Modern client-facing dispatch is gated per capability instead of a global kill-switch, with listen-stream support and pagination.
- ›W3C trace context propagates through outbound MCP
_meta(SEP-414), joining backend spans to the client→proxy→server trace. - ›Wires RFC 8693 token exchange into the embedded authorization server's token endpoint, with delegated token audience bounded by the subject token.
- ›Subject tokens from trusted external OIDC issuers (Keycloak, Entra, Okta) can now be validated for RFC 8693 token exchange.
- ›Audit logs capture the RFC 8693
actclaim and full delegation chain, making 'agent X acting for Alice' distinguishable from Alice. - ›Dynamically registered OAuth clients now renew expiring client secrets automatically (RFC 7591/7592).
- ›Multi-valued JWT claims can be normalized to canonical space-delimited form for Cedar policies.
- ›Backend
list_changednotifications are now consumed and propagated to clients for tools, resources, and prompts. - ›Virtual MCP is now MCP-conformant: completions, resource templates, subscriptions, and mid-call server-to-client forwarding all work.
- ›Guarantees
tools/listpagination completeness for aggregated sets exceeding 1,000 tools. - ›Tool definitions carrying invalid
x-mcp-headerannotations (SEP-2243) are now rejected as the spec requires. - ›Readiness probe now sends the current MCP protocol version instead of a hardcoded 2024-11-05.
- ›Adds an opt-in Envoy network-isolation backend.
└──▷ BREAKING ON UPGRADE- !Namespace-scoped Helm installs (
operator.rbac.scope=namespace) now failhelm upgradeat render time unlessoperator.features.storageVersionMigrator: falseis set, because the StorageVersionMigrator controller is now enabled by default (operator.features.storageVersionMigrator: true). - !JSON-RPC batch requests (top-level arrays) are now rejected with HTTP 400 / error code
-32600instead of being executed; send individual requests. - !Rate-limit JSON-RPC error code changed from
-32029to429; clients branching onerror.code == -32029must match429instead.
- ›Adds