{ "components": { "schemas": { "auth.TokenValidatorConfig": { "description": "DEPRECATED: Middleware configuration.\nOIDCConfig contains OIDC configuration", "properties": { "allowPrivateIP": { "description": "AllowPrivateIP allows JWKS/OIDC endpoints on private IP addresses", "type": "boolean" }, "audience": { "description": "Audience is the expected audience for the token", "type": "string" }, "authTokenFile": { "description": "AuthTokenFile is the path to file containing bearer token for authentication", "type": "string" }, "cacertPath": { "description": "CACertPath is the path to the CA certificate bundle for HTTPS requests", "type": "string" }, "clientID": { "description": "ClientID is the OIDC client ID", "type": "string" }, "clientSecret": { "description": "ClientSecret is the optional OIDC client secret for introspection", "type": "string" }, "insecureAllowHTTP": { "description": "InsecureAllowHTTP allows HTTP (non-HTTPS) OIDC issuers for development/testing\nWARNING: This is insecure and should NEVER be used in production", "type": "boolean" }, "introspectionURL": { "description": "IntrospectionURL is the optional introspection endpoint for validating tokens", "type": "string" }, "issuer": { "description": "Issuer is the OIDC issuer URL (e.g., https://accounts.google.com)", "type": "string" }, "jwksurl": { "description": "JWKSURL is the URL to fetch the JWKS from", "type": "string" }, "resourceURL": { "description": "ResourceURL is the explicit resource URL for OAuth discovery (RFC 9728)", "type": "string" }, "scopes": { "description": "Scopes is the list of OAuth scopes to advertise in the well-known endpoint (RFC 9728)\nIf empty, defaults to [\"openid\"]", "items": { "type": "string" }, "type": "array" } }, "type": "object" }, "core.Workload": { "properties": { "created_at": { "description": "CreatedAt is the timestamp when the workload was created.", "type": "string" }, "group": { "description": "Group is the name of the group this workload belongs to, if any.", "type": "string" }, "labels": { "additionalProperties": { "type": "string" }, "description": "Labels are the container labels (excluding standard ToolHive labels)", "type": "object" }, "name": { "description": "Name is the name of the workload.\nIt is used as a unique identifier.", "type": "string" }, "package": { "description": "Package specifies the Workload Package used to create this Workload.", "type": "string" }, "port": { "description": "Port is the port on which the workload is exposed.\nThis is embedded in the URL.", "type": "integer" }, "proxy_mode": { "description": "ProxyMode is the proxy mode that clients should use to connect.\nFor stdio transports, this will be the proxy mode (sse or streamable-http).\nFor direct transports (sse/streamable-http), this will be the same as TransportType.", "type": "string" }, "remote": { "description": "Remote indicates whether this is a remote workload (true) or a container workload (false).", "type": "boolean" }, "started_at": { "description": "StartedAt is when the container was last started (changes on restart)", "type": "string" }, "status": { "description": "Status is the current status of the workload.", "enum": [ "running", "stopped", "error", "starting", "stopping", "unhealthy", "removing", "unknown", "unauthenticated", "auth_retrying", "policy_stopped" ], "type": "string" }, "status_context": { "description": "StatusContext provides additional context about the workload's status.\nThe exact meaning is determined by the status and the underlying runtime.", "type": "string" }, "tools": { "description": "ToolsFilter is the filter on tools applied to the workload.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "transport_type": { "description": "TransportType is the type of transport used for this workload.", "enum": ["stdio", "sse", "streamable-http", "inspector"], "type": "string" }, "url": { "description": "URL is the URL of the workload exposed by the ToolHive proxy.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_cmd_thv-operator_api_v1beta1.RateLimitConfig": { "description": "RateLimitConfig contains the CRD rate limiting configuration.\nWhen set, rate limiting middleware is added to the proxy middleware chain.", "properties": { "perUser": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket" }, "shared": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket" }, "tools": { "description": "Tools defines per-tool rate limit overrides.\nEach entry applies additional rate limits to calls targeting a specific tool name.\nA request must pass both the server-level limit and the per-tool limit.\n+listType=map\n+listMapKey=name\n+optional", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.ToolRateLimitConfig" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_audit.Config": { "description": "DEPRECATED: Middleware configuration.\nAuditConfig contains the audit logging configuration", "properties": { "component": { "description": "Component is the component name to use in audit events.\n+optional", "type": "string" }, "detectApplicationErrors": { "description": "DetectApplicationErrors controls whether the audit middleware inspects\nJSON-RPC response bodies for application-level errors when the HTTP\nstatus code indicates success (2xx). When enabled, a small prefix of\nthe response body is buffered to detect JSON-RPC error fields,\nindependent of the IncludeResponseData setting.\n+kubebuilder:default=true\n+optional", "type": "boolean" }, "enabled": { "description": "Enabled controls whether audit logging is enabled.\nWhen true, enables audit logging with the configured options.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "eventTypes": { "description": "EventTypes specifies which event types to audit. If empty, all events are audited.\n+optional", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "excludeEventTypes": { "description": "ExcludeEventTypes specifies which event types to exclude from auditing.\nThis takes precedence over EventTypes.\n+optional", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "includeRequestData": { "description": "IncludeRequestData determines whether to include request data in audit logs.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "includeResponseData": { "description": "IncludeResponseData determines whether to include response data in audit logs.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "logFile": { "description": "LogFile specifies the file path for audit logs. If empty, logs to stdout.\n+optional", "type": "string" }, "maxDataSize": { "description": "MaxDataSize limits the size of request/response data included in audit logs (in bytes).\n+kubebuilder:default=1024\n+optional", "type": "integer" }, "maxDelegationDepth": { "description": "MaxDelegationDepth caps how many nested RFC 8693 \"act\" entries are\nrecorded in an audit event's delegation chain. Deeper chains are\ntruncated (marked with truncated=true). Defaults to 10 when unset.\n+kubebuilder:validation:Minimum=1\n+kubebuilder:default=10\n+optional", "type": "integer" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_auth_awssts.Config": { "description": "AWSStsConfig contains AWS STS token exchange configuration for accessing AWS services", "properties": { "fallback_role_arn": { "description": "FallbackRoleArn is the IAM role ARN to assume when no role mapping matches.", "type": "string" }, "region": { "description": "Region is the AWS region for STS and SigV4 signing.", "type": "string" }, "role_claim": { "description": "RoleClaim is the JWT claim to use for role mapping (default: \"groups\").", "type": "string" }, "role_mappings": { "description": "RoleMappings maps JWT claim values to IAM roles with priority.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_auth_awssts.RoleMapping" }, "type": "array", "uniqueItems": false }, "service": { "description": "Service is the AWS service name for SigV4 signing (default: \"aws-mcp\").", "type": "string" }, "session_duration": { "description": "SessionDuration is the duration in seconds for assumed role credentials (default: 3600).", "type": "integer" }, "session_name_claim": { "description": "SessionNameClaim is the JWT claim to use for role session name (default: \"sub\").", "type": "string" }, "subject_provider_name": { "description": "SubjectProviderName identifies which upstream provider's access token to use\nfor STS AssumeRoleWithWebIdentity. Used by vMCP only. When empty, the bearer\ntoken from the incoming HTTP request is used.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_auth_awssts.RoleMapping": { "properties": { "claim": { "description": "Claim is the simple claim value to match (e.g., group name).\nInternally compiles to a CEL expression: \"\u003cclaim_value\u003e\" in claims[\"\u003crole_claim\u003e\"]\nMutually exclusive with Matcher.", "type": "string" }, "matcher": { "description": "Matcher is a CEL expression for complex matching against JWT claims.\nThe expression has access to a \"claims\" variable containing all JWT claims.\nExamples:\n - \"admins\" in claims[\"groups\"]\n - claims[\"sub\"] == \"user123\" \u0026\u0026 !(\"act\" in claims)\nMutually exclusive with Claim.", "type": "string" }, "priority": { "description": "Priority determines selection order (lower number = higher priority).\nWhen multiple mappings match, the one with the lowest priority is selected.\nWhen nil (omitted), the mapping has the lowest possible priority, and\nconfiguration order acts as tie-breaker via stable sort.", "type": "integer" }, "role_arn": { "description": "RoleArn is the IAM role ARN to assume when this mapping matches.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_auth_upstreamswap.Config": { "description": "UpstreamSwapConfig contains configuration for upstream token swap middleware.\nWhen set along with EmbeddedAuthServerConfig, this middleware exchanges ToolHive JWTs\nfor upstream IdP tokens before forwarding requests to the MCP server.", "properties": { "custom_header_name": { "description": "CustomHeaderName is the header name when HeaderStrategy is \"custom\".", "type": "string" }, "header_strategy": { "description": "HeaderStrategy determines how to inject the token: \"replace\" (default) or \"custom\".", "type": "string" }, "provider_name": { "description": "ProviderName identifies which upstream provider's tokens to retrieve for injection.\nThis is required and must match a configured upstream provider name.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.CIMDRunConfig": { "description": "CIMD controls client_id metadata document support. When enabled, the\nembedded authorization server accepts HTTPS URLs as client_id values\nand resolves them via the CIMD protocol instead of requiring DCR.", "properties": { "cache_fallback_ttl": { "description": "CacheFallbackTTL is the fixed TTL applied to every cached CIMD document.\nCache-Control header parsing is not yet implemented; all entries use this value.\nFormat: Go duration string (e.g. \"5m\", \"10m\", \"1h\").\nDefaults to 5 minutes when Enabled is true and this field is omitted.", "example": "5m", "type": "string" }, "cache_max_size": { "description": "CacheMaxSize is the maximum number of CIMD documents held in the LRU cache.\nDefaults to 256 when Enabled is true and this field is zero.", "type": "integer" }, "enabled": { "description": "Enabled activates CIMD client lookup when true.", "type": "boolean" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.DCRUpstreamConfig": { "description": "DCRConfig enables RFC 7591 Dynamic Client Registration against the\nupstream authorization server. When set, the client credentials are\nobtained at runtime rather than being pre-provisioned via ClientID /\nClientSecretFile / ClientSecretEnvVar, and ClientID must be left empty.\nMutually exclusive with ClientID.", "properties": { "discovery_url": { "description": "DiscoveryURL is the exact RFC 8414 / OIDC Discovery document URL to\nfetch at runtime. The resolver issues a single GET against this URL\n(no well-known-path fallback) and reads registration_endpoint,\nauthorization_endpoint, token_endpoint,\ntoken_endpoint_auth_methods_supported, and scopes_supported from the\nresponse. Per RFC 8414 §3.3, the document's \"issuer\" field must\nexactly match the upstream issuer configured on the parent\nrun-config.\n\nUse this field when the upstream publishes discovery metadata at a\npath that differs from the issuer-derived well-known paths — for\nexample a multi-tenant IdP whose metadata lives at\nhttps://idp.example.com/tenants/acme/.well-known/openid-configuration.\n\nMutually exclusive with RegistrationEndpoint.", "type": "string" }, "initial_access_token_env_var": { "description": "InitialAccessTokenEnvVar is the name of an environment variable\ncontaining the RFC 7591 initial access token. Mutually exclusive with\nInitialAccessTokenFile.", "type": "string" }, "initial_access_token_file": { "description": "InitialAccessTokenFile is the path to a file containing the RFC 7591\ninitial access token presented to the registration endpoint. Mutually\nexclusive with InitialAccessTokenEnvVar. Both may be omitted for open\nregistration endpoints.", "type": "string" }, "registration_endpoint": { "description": "RegistrationEndpoint is the RFC 7591 registration endpoint URL used\ndirectly, bypassing discovery. Because no discovery is performed,\nserver-capability fields (token_endpoint_auth_methods_supported,\nscopes_supported) are unavailable on this code path; the caller is\nexpected to also supply AuthorizationEndpoint, TokenEndpoint, and an\nexplicit Scopes list on the parent OAuth2UpstreamRunConfig. Auth\nmethod falls back to the resolver's default (client_secret_basic).\n\nMutually exclusive with DiscoveryURL.", "type": "string" }, "software_id": { "description": "SoftwareID is the RFC 7591 \"software_id\" registration metadata value,\nidentifying the client software independent of any particular\nregistration instance.", "type": "string" }, "software_statement": { "description": "SoftwareStatement is the RFC 7591 \"software_statement\" JWT asserting\nmetadata about the client software, signed by a party the authorization\nserver trusts.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.IdentityFromTokenRunConfig": { "description": "IdentityFromToken extracts user identity (subject, name, email) directly from the\nOAuth2 token-endpoint response body using gjson dot-notation paths. When set, the\nembedded auth server skips the userinfo HTTP call entirely. Mirrors the CRD type\n(cmd/thv-operator/api/v1beta1.IdentityFromTokenConfig) — the authoritative\ntrust-model and uniqueness documentation lives there.", "properties": { "email_path": { "description": "EmailPath is the dot-notation path to the email address field.", "type": "string" }, "name_path": { "description": "NamePath is the dot-notation path to the display name field.", "type": "string" }, "subject_path": { "description": "SubjectPath is the dot-notation path to the subject (user ID) field.\nRequired when IdentityFromToken is set.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.OAuth2UpstreamRunConfig": { "description": "OAuth2Config contains OAuth 2.0-specific configuration.\nRequired when Type is \"oauth2\", must be nil when Type is \"oidc\".", "properties": { "additional_authorization_params": { "additionalProperties": { "type": "string" }, "description": "AdditionalAuthorizationParams are extra query parameters to include in\nauthorization requests. Useful for provider-specific parameters like\nGoogle's access_type=offline.", "type": "object" }, "allow_private_ips": { "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). When DCRConfig is set, this\nalso gates the DCR discovery and registration calls made on this\nupstream's behalf (see pkg/authserver/runner/dcr_adapter.go), so a\nsingle flag covers the whole upstream rather than needing a separate\nDCR-specific setting. Use only when the upstream is hosted inside the\nsame cluster and has no public endpoint. HTTP-scheme restrictions are\nunchanged — HTTPS is still required for non-localhost hosts. Defaults\nto false.", "type": "boolean" }, "authorization_endpoint": { "description": "AuthorizationEndpoint is the URL for the OAuth authorization endpoint.", "type": "string" }, "client_id": { "description": "ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.\nMutually exclusive with DCRConfig: when DCRConfig is set, ClientID is obtained\nat runtime via RFC 7591 Dynamic Client Registration and must be left empty.", "type": "string" }, "client_secret_env_var": { "description": "ClientSecretEnvVar is the name of an environment variable containing the client secret.\nMutually exclusive with ClientSecretFile. Optional for public clients using PKCE.", "type": "string" }, "client_secret_file": { "description": "ClientSecretFile is the path to a file containing the OAuth 2.0 client secret.\nMutually exclusive with ClientSecretEnvVar. Optional for public clients using PKCE.", "type": "string" }, "dcr_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.DCRUpstreamConfig" }, "identity_from_token": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.IdentityFromTokenRunConfig" }, "insecure_allow_http": { "description": "InsecureAllowHTTP permits plain-HTTP authorization and token endpoint URLs\nfor this upstream. Only for in-cluster development environments (e.g. an\nOAuth2 provider served over HTTP in a kind cluster) where TLS is not\navailable. Never set this in production.", "type": "boolean" }, "redirect_uri": { "description": "RedirectURI is the callback URL where the upstream IDP will redirect after authentication.\nWhen not specified, defaults to `{issuer}/oauth/callback`.", "type": "string" }, "scopes": { "description": "Scopes are the OAuth scopes to request from the upstream IDP.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "token_endpoint": { "description": "TokenEndpoint is the URL for the OAuth token endpoint.", "type": "string" }, "token_response_mapping": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.TokenResponseMappingRunConfig" }, "userinfo": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UserInfoRunConfig" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.OIDCUpstreamRunConfig": { "description": "OIDCConfig contains OIDC-specific configuration.\nRequired when Type is \"oidc\", must be nil when Type is \"oauth2\".", "properties": { "additional_authorization_params": { "additionalProperties": { "type": "string" }, "description": "AdditionalAuthorizationParams are extra query parameters to include in\nauthorization requests. Useful for provider-specific parameters like\nGoogle's access_type=offline.", "type": "object" }, "allow_private_ips": { "description": "AllowPrivateIPs permits the OIDC discovery and token HTTP clients to\nconnect to private IP ranges (RFC-1918, link-local). Use only when the\nupstream is hosted inside the same cluster and has no public endpoint.\nHTTP-scheme restrictions are unchanged — HTTPS is still required for\nnon-localhost hosts. Defaults to false.", "type": "boolean" }, "client_id": { "description": "ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.", "type": "string" }, "client_secret_env_var": { "description": "ClientSecretEnvVar is the name of an environment variable containing the client secret.\nMutually exclusive with ClientSecretFile. Optional for public clients using PKCE.", "type": "string" }, "client_secret_file": { "description": "ClientSecretFile is the path to a file containing the OAuth 2.0 client secret.\nMutually exclusive with ClientSecretEnvVar. Optional for public clients using PKCE.", "type": "string" }, "insecure_allow_http": { "description": "InsecureAllowHTTP permits a plain-HTTP issuer URL and HTTP discovery\nendpoints for this upstream. Only for in-cluster development environments\n(e.g. Dex served over HTTP in a kind cluster) where TLS is not available.\nNever set this in production.", "type": "boolean" }, "issuer_url": { "description": "IssuerURL is the OIDC issuer URL for automatic endpoint discovery.\nMust be a valid HTTPS URL.", "type": "string" }, "redirect_uri": { "description": "RedirectURI is the callback URL where the upstream IDP will redirect after authentication.\nWhen not specified, defaults to `{issuer}/oauth/callback`.", "type": "string" }, "scopes": { "description": "Scopes are the OAuth scopes to request from the upstream IDP.\nIf not specified, defaults to [\"openid\", \"offline_access\"].\nWhen using AdditionalAuthorizationParams with provider-specific refresh\ntoken mechanisms (e.g., Google's access_type=offline), set explicit scopes\nto avoid sending both offline_access and the provider-specific parameter.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "subject_claim": { "description": "SubjectClaim names the validated ID-token claim to use as the upstream\nsubject. Defaults to \"sub\" when empty. Set for IdPs where \"sub\" isn't\nstable per user (e.g. Entra/Azure AD's \"oid\"). See upstream.OIDCConfig.", "type": "string" }, "userinfo_override": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UserInfoRunConfig" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.RunConfig": { "description": "EmbeddedAuthServerConfig contains configuration for the embedded OAuth2/OIDC authorization server.\nWhen set, the proxy runner will start an embedded auth server that delegates to upstream IDPs.\nThis is the serializable RunConfig; secrets are referenced by file paths or env var names.", "properties": { "allowed_audiences": { "description": "AllowedAudiences is the list of valid resource URIs that tokens can be issued for.\nPer RFC 8707, the \"resource\" parameter in authorization and token requests is\nvalidated against this list. Required for MCP compliance.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "authorization_endpoint_base_url": { "description": "AuthorizationEndpointBaseURL overrides the base URL used for the authorization_endpoint\nin the OAuth discovery document. When set, the discovery document will advertise\n`{authorization_endpoint_base_url}/oauth/authorize` instead of `{issuer}/oauth/authorize`.\nAll other endpoints remain derived from the issuer.", "type": "string" }, "baseline_client_scopes": { "description": "BaselineClientScopes is a baseline set of OAuth 2.0 scopes unioned into every\nDCR registration. All values must appear in ScopesSupported; the auth server\nrejects this RunConfig at startup otherwise. Empty means current behavior is\npreserved (registered scope = client-requested, or DefaultScopes if empty).\nWhen ScopesSupported is empty, the subset check uses registration.DefaultScopes\n(the same set applyDefaults would substitute at startup) — so\nBaselineClientScopes containing standard OIDC scopes works without enumerating\nScopesSupported explicitly.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "cimd": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.CIMDRunConfig" }, "delegation_token_lifespan": { "description": "DelegationTokenLifespan is the maximum lifetime for delegated tokens issued\nvia RFC 8693 token exchange. Specified as a Go duration string (e.g., \"15m\").\nIf empty, defaults to 15 minutes.", "type": "string" }, "disable_upstream_token_injection": { "description": "DisableUpstreamTokenInjection prevents the upstream swap middleware from being added.\nWhen true, the embedded auth server handles OAuth flows for clients, but instead of\ninjecting upstream IdP tokens the proxy strips the client's credential headers\n(Authorization, Cookie, Proxy-Authorization) after the JWT is validated — the\nbackend receives an unauthenticated request. Incompatible with token exchange\nand AWS STS, which would re-add credentials after the strip.", "type": "boolean" }, "hmac_secret_files": { "description": "HMACSecretFiles contains file paths to HMAC secrets for signing authorization codes\nand refresh tokens (opaque tokens).\nFirst file is the current secret (must be at least 32 bytes), subsequent files\nare for rotation/verification of existing tokens.\nIf empty, an ephemeral secret will be auto-generated (development only).", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "insecure_allow_http": { "description": "InsecureAllowHTTP permits an http:// issuer URL for non-localhost hosts.\nOnly set this for in-cluster Kubernetes deployments on a trusted network.\nProduction deployments reachable outside the cluster MUST use https://.", "type": "boolean" }, "issuer": { "description": "Issuer is the issuer identifier for this authorization server.\nThis will be included in the \"iss\" claim of issued tokens.\nMust be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.", "type": "string" }, "schema_version": { "description": "SchemaVersion is the version of the RunConfig schema.", "type": "string" }, "scopes_supported": { "description": "ScopesSupported lists the OAuth 2.0 scope values advertised in discovery documents.\nIf empty, defaults to registration.DefaultScopes ([\"openid\", \"profile\", \"email\", \"offline_access\"]).", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "signing_key_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.SigningKeyRunConfig" }, "storage": { "$ref": "#/components/schemas/storage.RunConfig" }, "token_lifespans": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.TokenLifespanRunConfig" }, "upstreams": { "description": "Upstreams configures connections to upstream Identity Providers.\nAt least one upstream is required - the server delegates authentication to these providers.\nMultiple upstreams are supported for sequential authorization chains.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UpstreamRunConfig" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.SigningKeyRunConfig": { "description": "SigningKeyConfig configures the signing key provider for JWT operations.\nIf nil or empty, an ephemeral signing key will be auto-generated (development only).", "properties": { "fallback_key_files": { "description": "FallbackKeyFiles are filenames of additional keys for verification (relative to KeyDir).\nThese keys are included in the JWKS endpoint for token verification but are NOT\nused for signing new tokens. Useful for key rotation.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "key_dir": { "description": "KeyDir is the directory containing PEM-encoded private key files.\nAll key filenames are relative to this directory.\nIn Kubernetes, this is typically a mounted Secret volume.", "type": "string" }, "signing_key_file": { "description": "SigningKeyFile is the filename of the primary signing key (relative to KeyDir).\nThis key is used for signing new tokens.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.TokenLifespanRunConfig": { "description": "TokenLifespans configures the duration that various tokens are valid.\nIf nil, defaults are applied (access: 1h, refresh: 7d, authCode: 10m).", "properties": { "access_token_lifespan": { "description": "AccessTokenLifespan is the duration that access tokens are valid.\nIf empty, defaults to 1 hour.", "type": "string" }, "auth_code_lifespan": { "description": "AuthCodeLifespan is the duration that authorization codes are valid.\nIf empty, defaults to 10 minutes.", "type": "string" }, "refresh_token_lifespan": { "description": "RefreshTokenLifespan is the duration that refresh tokens are valid.\nIf empty, defaults to 7 days (168h).", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.TokenResponseMappingRunConfig": { "description": "TokenResponseMapping configures custom field extraction from non-standard token responses.\nWhen set, the token exchange bypasses golang.org/x/oauth2 and extracts fields using\nthe configured dot-notation paths.", "properties": { "access_token_path": { "description": "AccessTokenPath is the dot-notation path to the access token (required).", "type": "string" }, "expires_in_path": { "description": "ExpiresInPath is the dot-notation path to the expires_in value. Defaults to \"expires_in\".", "type": "string" }, "refresh_token_path": { "description": "RefreshTokenPath is the dot-notation path to the refresh token. Defaults to \"refresh_token\".", "type": "string" }, "scope_path": { "description": "ScopePath is the dot-notation path to the scope. Defaults to \"scope\".", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.UpstreamProviderType": { "description": "Type specifies the provider type: \"oidc\" or \"oauth2\".", "enum": ["oidc", "oauth2"], "type": "string", "x-enum-varnames": [ "UpstreamProviderTypeOIDC", "UpstreamProviderTypeOAuth2" ] }, "github_com_stacklok_toolhive_pkg_authserver.UpstreamRunConfig": { "properties": { "name": { "description": "Name uniquely identifies this upstream.\nUsed for routing decisions and session binding in multi-upstream scenarios.\nIf empty when only one upstream is configured, defaults to \"default\".", "type": "string" }, "oauth2_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.OAuth2UpstreamRunConfig" }, "oidc_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.OIDCUpstreamRunConfig" }, "type": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UpstreamProviderType" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.UserInfoFieldMappingRunConfig": { "description": "FieldMapping contains custom field mapping configuration for non-standard providers.\nIf nil, standard OIDC field names are used (\"sub\", \"name\", \"email\").", "properties": { "email_fields": { "description": "EmailFields is an ordered list of field names to try for the email address.\nThe first non-empty value found will be used.\nDefault: [\"email\"]", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "name_fields": { "description": "NameFields is an ordered list of field names to try for the display name.\nThe first non-empty value found will be used.\nDefault: [\"name\"]", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "subject_fields": { "description": "SubjectFields is an ordered list of field names to try for the user ID.\nThe first non-empty value found will be used.\nDefault: [\"sub\"]", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authserver.UserInfoRunConfig": { "description": "UserInfo contains configuration for fetching user information.\nOptional: when nil, the upstream OAuth2 provider derives a deterministic\nsubject by SHA-256-hashing the access token (with a \"tk-\" prefix) instead\nof calling a userinfo endpoint. OIDC providers always derive Subject from\nthe ID token and are unaffected.", "properties": { "additional_headers": { "additionalProperties": { "type": "string" }, "description": "AdditionalHeaders contains extra headers to include in the userinfo request.\nUseful for providers that require specific headers (e.g., GitHub's Accept header).", "type": "object" }, "endpoint_url": { "description": "EndpointURL is the URL of the userinfo endpoint.", "type": "string" }, "field_mapping": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UserInfoFieldMappingRunConfig" }, "http_method": { "description": "HTTPMethod is the HTTP method to use for the userinfo request.\nIf not specified, defaults to GET.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_authz.Config": { "description": "DEPRECATED: Middleware configuration.\nAuthzConfig contains the authorization configuration", "properties": { "type": { "description": "Type is the type of authorization configuration (e.g., \"cedarv1\").", "type": "string" }, "version": { "description": "Version is the version of the configuration format.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_client.ClientApp": { "description": "ClientType is the type of MCP client", "enum": [ "roo-code", "cline", "cursor", "vscode-insider", "vscode", "claude-code", "windsurf", "windsurf-jetbrains", "amp-cli", "lm-studio", "goose", "trae", "continue", "opencode", "kiro", "antigravity", "zed", "gemini-cli", "vscode-server", "mistral-vibe", "codex", "kimi-cli", "factory", "copilot-cli" ], "type": "string", "x-enum-varnames": [ "RooCode", "Cline", "Cursor", "VSCodeInsider", "VSCode", "ClaudeCode", "Windsurf", "WindsurfJetBrains", "AmpCli", "LMStudio", "Goose", "Trae", "Continue", "OpenCode", "Kiro", "Antigravity", "Zed", "GeminiCli", "VSCodeServer", "MistralVibe", "Codex", "KimiCli", "Factory", "CopilotCli" ] }, "github_com_stacklok_toolhive_pkg_client.ClientAppStatus": { "properties": { "client_type": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.ClientApp" }, "installed": { "description": "Installed indicates whether the client is installed on the system", "type": "boolean" }, "registered": { "description": "Registered indicates whether the client is registered in the ToolHive configuration", "type": "boolean" }, "supports_plugins": { "description": "SupportsPlugins indicates whether ToolHive can install plugins for this client", "type": "boolean" }, "supports_skills": { "description": "SupportsSkills indicates whether ToolHive can install skills for this client", "type": "boolean" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_client.RegisteredClient": { "properties": { "groups": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "name": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.ClientApp" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_groups.Group": { "properties": { "name": { "type": "string" }, "plugins": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "registered_clients": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "skills": { "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket": { "description": "PerUser token bucket configuration for this tool.\n+optional", "properties": { "maxTokens": { "description": "MaxTokens is the maximum number of tokens (bucket capacity).\nThis is also the burst size: the maximum number of requests that can be served\ninstantaneously before the bucket is depleted.\n+kubebuilder:validation:Required\n+kubebuilder:validation:Minimum=1", "type": "integer" }, "refillPeriod": { "$ref": "#/components/schemas/v1.Duration" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_ratelimit_types.ToolRateLimitConfig": { "properties": { "name": { "description": "Name is the MCP tool name this limit applies to.\n+kubebuilder:validation:Required\n+kubebuilder:validation:MinLength=1", "type": "string" }, "perUser": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket" }, "shared": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_registry.OAuthPublicConfig": { "description": "AuthConfig contains the non-secret OAuth configuration when auth is configured.\nNil when auth_status is \"none\".", "properties": { "audience": { "type": "string" }, "client_id": { "type": "string" }, "issuer": { "type": "string" }, "scopes": { "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_runner.HeaderForwardConfig": { "description": "HeaderForward contains configuration for injecting headers into requests to remote servers.", "properties": { "add_headers_from_secret": { "additionalProperties": { "type": "string" }, "description": "AddHeadersFromSecret is a map of header names to secret names.\nThe key is the header name, the value is the secret name in ToolHive's secrets manager.\nResolved at runtime via WithSecrets() into resolvedHeaders.\nThe actual secret value is only held in memory, never persisted.", "type": "object" }, "add_plaintext_headers": { "additionalProperties": { "type": "string" }, "description": "AddPlaintextHeaders is a map of header names to literal values to inject into requests.\nWARNING: These values are stored in plaintext in the configuration.\nFor sensitive values (API keys, tokens), use AddHeadersFromSecret instead.", "type": "object" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_runner.RunConfig": { "properties": { "additional_middleware_configs": { "description": "AdditionalMiddlewareConfigs carries pre-built middleware configs injected by\nexternal-auth handlers (reached via *[]RunConfigBuilderOption) rather than\nderived from typed RunConfig fields. PopulateMiddlewareConfigs splices these\ninto the chain in the backend-egress group — after auth and before recovery —\ninstead of discarding them. Upstream carries these configs verbatim and never\ninspects their parameters; the middleware type identity (e.g. an enterprise\nauth type) is supplied by the caller via types.MiddlewareConfig.Type.\n\nEach entry's Type is expected to be a NEW egress middleware type (e.g. OBO),\nnot one already produced from a typed RunConfig field (auth, authz, audit,\ntokenExchange, awssts, …). Dispatch in the proxyrunner is purely by Type\nstring, so an injected Type that shadows a typed-field type would add a\nsecond instance of that middleware to the chain; the seam does not validate\nagainst this.", "items": { "$ref": "#/components/schemas/types.MiddlewareConfig" }, "type": "array", "uniqueItems": false }, "allow_docker_gateway": { "description": "AllowDockerGateway permits outbound connections to Docker gateway addresses\n(host.docker.internal, gateway.docker.internal, 172.17.0.1). These are\nblocked by default in the egress proxy even when InsecureAllowAll is set.\nOnly applicable to Docker deployments with network isolation enabled.\nGateway access is port-independent: it ignores the permission profile's\nallowed ports, so once enabled the gateway is reachable on any port.", "type": "boolean" }, "allowed_origins": { "description": "AllowedOrigins is the allowlist of values accepted on the HTTP Origin header,\nused for DNS-rebinding protection per MCP 2025-11-25 §\"Security Warning\".\nWhen empty and Host is loopback (127.0.0.1 / localhost / [::1]), a default\nloopback-only allowlist is derived at middleware-wiring time.\nWhen empty and Host is non-loopback, the middleware is disabled — operators\nexposing the proxy publicly must configure an explicit allowlist.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "audit_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_audit.Config" }, "audit_config_path": { "description": "DEPRECATED: Middleware configuration.\nAuditConfigPath is the path to the audit configuration file", "type": "string" }, "authz_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authz.Config" }, "authz_config_path": { "description": "DEPRECATED: Middleware configuration.\nAuthzConfigPath is the path to the authorization configuration file", "type": "string" }, "aws_sts_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_auth_awssts.Config" }, "base_name": { "description": "BaseName is the base name used for the container (without prefixes)", "type": "string" }, "cmd_args": { "description": "CmdArgs are the arguments to pass to the container", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "container_labels": { "additionalProperties": { "type": "string" }, "description": "ContainerLabels are the labels to apply to the container", "type": "object" }, "container_name": { "description": "ContainerName is the name of the container", "type": "string" }, "debug": { "description": "Debug indicates whether debug mode is enabled", "type": "boolean" }, "embedded_auth_server_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.RunConfig" }, "endpoint_prefix": { "description": "EndpointPrefix is an explicit prefix to prepend to SSE endpoint URLs.\nThis is used to handle path-based ingress routing scenarios.", "type": "string" }, "env_file_dir": { "description": "DEPRECATED: No longer appears to be used.\nEnvFileDir is the directory path to load environment files from", "type": "string" }, "env_vars": { "additionalProperties": { "type": "string" }, "description": "EnvVars are the parsed environment variables as key-value pairs", "type": "object" }, "group": { "description": "Group is the name of the group this workload belongs to, if any", "type": "string" }, "header_forward": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_runner.HeaderForwardConfig" }, "host": { "description": "Host is the host for the HTTP proxy", "type": "string" }, "ignore_config": { "$ref": "#/components/schemas/ignore.Config" }, "image": { "description": "Image is the Docker image to run", "type": "string" }, "isolate_network": { "description": "IsolateNetwork indicates whether to isolate the network for the container", "type": "boolean" }, "jwks_auth_token_file": { "description": "DEPRECATED: No longer appears to be used.\nJWKSAuthTokenFile is the path to file containing auth token for JWKS/OIDC requests", "type": "string" }, "k8s_pod_template_patch": { "description": "K8sPodTemplatePatch is a JSON string to patch the Kubernetes pod template\nOnly applicable when using Kubernetes runtime", "type": "string" }, "mcpserver_generation": { "description": "MCPServerGeneration is the K8s .metadata.generation of the MCPServer CR that rendered\nthis RunConfig. The Kubernetes runtime uses it as a monotonic version to prevent stale\nrolling-update pods from overwriting a newer RunConfig's StatefulSet apply. Zero value\nmeans unversioned (backward-compat with older operators, or non-operator callers).", "type": "integer" }, "middleware_configs": { "description": "MiddlewareConfigs contains the list of middleware to apply to the transport\nand the configuration for each middleware.", "items": { "$ref": "#/components/schemas/types.MiddlewareConfig" }, "type": "array", "uniqueItems": false }, "mutating_webhooks": { "description": "MutatingWebhooks contains the configuration for mutating webhook middleware.\nMutating webhooks run before validating webhooks, per RFC THV-0017 ordering.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_webhook.Config" }, "type": "array", "uniqueItems": false }, "name": { "description": "Name is the name of the MCP server", "type": "string" }, "oidc_config": { "$ref": "#/components/schemas/auth.TokenValidatorConfig" }, "permission_profile_name_or_path": { "description": "PermissionProfileNameOrPath is the name or path of the permission profile", "type": "string" }, "port": { "description": "Port is the port for the HTTP proxy to listen on (host port)", "type": "integer" }, "proxy_mode": { "description": "ProxyMode is the effective HTTP protocol the proxy uses.\nFor stdio transports, this is the configured mode (sse or streamable-http).\nFor direct transports (sse/streamable-http), this matches the transport type.\nNote: \"sse\" is deprecated; use \"streamable-http\" instead.", "enum": ["sse", "streamable-http"], "type": "string" }, "publish": { "description": "Publish lists ports to publish to the host in format \"hostPort:containerPort\"", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "rate_limit_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_cmd_thv-operator_api_v1beta1.RateLimitConfig" }, "rate_limit_namespace": { "description": "RateLimitNamespace is the Kubernetes namespace for Redis key derivation.", "type": "string" }, "registry_api_url": { "description": "RegistryAPIURL is the registry API URL that served this server's metadata.\nEmpty when the server was not discovered via registry lookup.", "type": "string" }, "registry_server_name": { "description": "RegistryServerName is the registry entry name used to look up this server's metadata.\nEmpty when the server was not discovered via registry lookup.", "type": "string" }, "registry_url": { "description": "RegistryURL is the registry URL that served this server's metadata.\nEmpty when the server was not discovered via registry lookup.", "type": "string" }, "remote_auth_config": { "$ref": "#/components/schemas/remote.Config" }, "remote_url": { "description": "RemoteURL is the URL of the remote MCP server (if running remotely)", "type": "string" }, "runtime_config": { "$ref": "#/components/schemas/templates.RuntimeConfig" }, "scaling_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_runner.ScalingConfig" }, "schema_version": { "description": "SchemaVersion is the version of the RunConfig schema", "type": "string" }, "secrets": { "description": "Secrets are the secret parameters to pass to the container\nFormat: \"\u003csecret name\u003e,target=\u003ctarget environment variable\u003e\"", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "session_ttl": { "description": "SessionTTL is the inactivity timeout for proxy sessions, expressed as a Go\nduration string (e.g. \"30m\", \"2h\", \"168h\"). Empty uses the transport\ndefault (2h). Negative durations and values that fail time.ParseDuration\nare rejected at runtime.\nString (not time.Duration) keeps the wire format unit-explicit: a\ntime.Duration field serializes as nanoseconds in JSON.", "example": "2h", "type": "string" }, "stateless": { "description": "Stateless indicates the server only supports POST (no SSE/GET).\nWhen true, the proxy returns 405 for incoming GET requests and uses a\nPOST-based health check instead of the default GET probe.\nApplies to both remote URLs and local container workloads.", "type": "boolean" }, "strict_protocol_validation": { "description": "StrictProtocolValidation enables strict MCP-Protocol-Version validation\non the streamable HTTP proxy: a request whose header names an unknown\nMCP revision is rejected with HTTP 400. Default false accepts any\nversion string (an absent header is always accepted in either mode).", "type": "boolean" }, "target_host": { "description": "TargetHost is the host to forward traffic to (only applicable to SSE transport)", "type": "string" }, "target_port": { "description": "TargetPort is the port for the container to expose (only applicable to SSE transport)", "type": "integer" }, "telemetry_config": { "$ref": "#/components/schemas/telemetry.Config" }, "thv_ca_bundle": { "description": "DEPRECATED: No longer appears to be used.\nThvCABundle is the path to the CA certificate bundle for ToolHive HTTP operations", "type": "string" }, "token_exchange_config": { "$ref": "#/components/schemas/tokenexchange.Config" }, "tools_filter": { "description": "DEPRECATED: Middleware configuration.\nToolsFilter is the list of tools to filter", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "tools_override": { "additionalProperties": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_runner.ToolOverride" }, "description": "DEPRECATED: Middleware configuration.\nToolsOverride is a map from an actual tool to its overridden name and/or description", "type": "object" }, "transport": { "description": "Transport is the transport mode (stdio, sse, or streamable-http)", "enum": ["stdio", "sse", "streamable-http", "inspector"], "type": "string" }, "trust_proxy_headers": { "description": "TrustProxyHeaders indicates whether to trust X-Forwarded-* headers from reverse proxies", "type": "boolean" }, "upstream_swap_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_auth_upstreamswap.Config" }, "validating_webhooks": { "description": "ValidatingWebhooks contains the configuration for validating webhook middleware.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_webhook.Config" }, "type": "array", "uniqueItems": false }, "volumes": { "description": "Volumes are the directory mounts to pass to the container\nFormat: \"host-path:container-path[:ro]\"", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_runner.ScalingConfig": { "description": "ScalingConfig contains configuration for horizontal scaling of the proxy runner.\nOnly applicable when running in Kubernetes with the ToolHive operator.\nWhen nil, no scaling configuration is applied (single-replica default behavior).", "properties": { "backend_replicas": { "description": "BackendReplicas is the desired StatefulSet replica count for the proxy runner backend.\nWhen nil, replicas are unmanaged (preserving HPA or manual kubectl control).\nWhen set (including 0), the value is an explicit replica count.", "type": "integer" }, "session_redis": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_runner.SessionRedisConfig" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_runner.SessionRedisConfig": { "description": "SessionRedis holds non-sensitive Redis connection parameters for distributed session storage.\nPopulated only when MCPServer.spec.sessionStorage.provider == \"redis\".\nThe Redis password is not included — it is injected as env var THV_SESSION_REDIS_PASSWORD.\n+optional", "properties": { "address": { "description": "Address is the Redis server address (host:port).", "type": "string" }, "db": { "description": "DB is the Redis database number.", "type": "integer" }, "key_prefix": { "description": "KeyPrefix is an optional prefix applied to all Redis keys used by ToolHive.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_runner.ToolOverride": { "properties": { "description": { "description": "Description is the redefined description of the tool", "type": "string" }, "name": { "description": "Name is the redefined name of the tool", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.BuildResult": { "properties": { "reference": { "description": "Reference is the OCI reference of the built skill artifact.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.Dependency": { "properties": { "digest": { "description": "Digest is the OCI digest for upgrade detection.", "type": "string" }, "name": { "description": "Name is the dependency name.", "type": "string" }, "reference": { "description": "Reference is the OCI reference for the dependency.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.FailureReason": { "description": "Reason is a typed failure reason when Status is UpgradeStatusFailed.", "enum": [ "registry-unreachable", "digest-missing", "validation-rejected", "lock-write-failed", "unknown" ], "type": "string", "x-enum-varnames": [ "FailureReasonRegistryUnreachable", "FailureReasonDigestMissing", "FailureReasonValidationRejected", "FailureReasonLockWriteFailed", "FailureReasonUnknown" ] }, "github_com_stacklok_toolhive_pkg_skills.InstallStatus": { "description": "Status is the current installation status.", "enum": ["installed", "pending", "failed"], "type": "string", "x-enum-varnames": [ "InstallStatusInstalled", "InstallStatusPending", "InstallStatusFailed" ] }, "github_com_stacklok_toolhive_pkg_skills.InstalledSkill": { "description": "InstalledSkill contains the full installation record.", "properties": { "clients": { "description": "Clients is the list of client identifiers the skill is installed for.\nTODO: Refactor client.ClientApp to a shared package so it can be used here instead of []string.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "dependencies": { "description": "Dependencies is the list of external skill dependencies.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.Dependency" }, "type": "array", "uniqueItems": false }, "digest": { "description": "Digest is the OCI digest (sha256:...) for upgrade detection.", "type": "string" }, "installed_at": { "description": "InstalledAt is the timestamp when the skill was installed.", "type": "string" }, "managed": { "description": "Managed indicates this install is tracked in the project's\ntoolhive.lock.yaml. Only ever true for project-scoped installs. No\nomitempty: false is an observable state (unmanaged), not an absence.", "type": "boolean" }, "metadata": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SkillMetadata" }, "project_root": { "description": "ProjectRoot is the project root path for project-scoped skills. Empty for user-scoped.", "type": "string" }, "reference": { "description": "Reference is the full OCI reference (e.g. ghcr.io/org/skill:v1).", "type": "string" }, "scope": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.Scope" }, "status": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.InstallStatus" }, "tag": { "description": "Tag is the OCI tag (e.g. v1.0.0).", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.LocalBuild": { "properties": { "description": { "description": "Description is the skill description extracted from the artifact metadata, if available.", "type": "string" }, "digest": { "description": "Digest is the OCI digest of the artifact (sha256:...).", "type": "string" }, "name": { "description": "Name is the skill name extracted from the artifact metadata, if available.", "type": "string" }, "tag": { "description": "Tag is the OCI tag or name used to reference the artifact.", "type": "string" }, "version": { "description": "Version is the skill version extracted from the artifact metadata, if available.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.Scope": { "description": "Scope for the installation", "enum": ["user", "project"], "type": "string", "x-enum-varnames": ["ScopeUser", "ScopeProject"] }, "github_com_stacklok_toolhive_pkg_skills.SkillContent": { "properties": { "body": { "description": "Body is the raw SKILL.md markdown content.", "type": "string" }, "description": { "description": "Description is the skill description from the OCI config labels.", "type": "string" }, "files": { "description": "Files is the list of all files in the artifact with their sizes.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SkillFileEntry" }, "type": "array", "uniqueItems": false }, "license": { "description": "License is the SPDX license identifier from the OCI config labels.", "type": "string" }, "name": { "description": "Name is the skill name from the OCI config labels.", "type": "string" }, "version": { "description": "Version is the skill version from the OCI config labels.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.SkillFileEntry": { "properties": { "path": { "description": "Path is the file path within the artifact.", "type": "string" }, "size": { "description": "Size is the uncompressed file size in bytes.", "type": "integer" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.SkillInfo": { "properties": { "installed_skill": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.InstalledSkill" }, "metadata": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SkillMetadata" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.SkillMetadata": { "description": "Metadata contains the skill's metadata.", "properties": { "author": { "description": "Author is the skill author or maintainer.", "type": "string" }, "description": { "description": "Description is a human-readable description of the skill.", "type": "string" }, "name": { "description": "Name is the unique name of the skill.", "type": "string" }, "tags": { "description": "Tags is a list of tags for categorization.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "version": { "description": "Version is the semantic version of the skill.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.SyncFailure": { "properties": { "error": { "description": "Error is a human-readable description of the failure.", "type": "string" }, "name": { "description": "Name is the skill name that failed.", "type": "string" }, "reason": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.FailureReason" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.SyncResult": { "properties": { "already_current": { "description": "AlreadyCurrent lists skills that already matched the lock file.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "drifted": { "description": "Drifted lists skills whose on-disk contentDigest differed from the lock\nfile. Normally these are reinstalled to match it; when Check is set,\nnothing is written and this field reports the drift only.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "failed": { "description": "Failed lists skills that could not be synced, with the reason for each.\nDrift alone is never reported here — see Drifted.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SyncFailure" }, "type": "array", "uniqueItems": false }, "installed": { "description": "Installed lists skills that were installed or reinstalled to match the lock file.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "missing": { "description": "Missing lists lock entries with no corresponding install record at all\n— the fresh-clone state. Normally these are installed at their pinned\nreference; when Check is set, nothing is written and this field\nreports the gap only.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "never_managed": { "description": "NeverManaged lists project-scoped skills never recorded as lock-managed.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "pruned": { "description": "Pruned lists removed-from-lock skills that were uninstalled because Prune was set.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "removed_from_lock": { "description": "RemovedFromLock lists previously managed skills absent from the lock file.", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.UpgradeOutcome": { "properties": { "error": { "description": "Error is a human-readable description of the failure, set only when Status is UpgradeStatusFailed.", "type": "string" }, "name": { "description": "Name is the skill name.", "type": "string" }, "new_digest": { "description": "NewDigest is the digest the source currently resolves to. Equal to\nOldDigest when Status is UpgradeStatusUpToDate.", "type": "string" }, "new_resolved_reference": { "description": "NewResolvedReference is the new resolvedReference when it changed.", "type": "string" }, "old_digest": { "description": "OldDigest is the digest pinned in the lock file before this operation.", "type": "string" }, "reason": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.FailureReason" }, "status": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.UpgradeStatus" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.UpgradeResult": { "properties": { "outcomes": { "description": "Outcomes contains one entry per skill considered for upgrade.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.UpgradeOutcome" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_skills.UpgradeStatus": { "description": "Status is the outcome of the upgrade attempt.", "enum": [ "upgraded", "up-to-date", "not-upgradable", "ref-change-blocked", "failed" ], "type": "string", "x-enum-varnames": [ "UpgradeStatusUpgraded", "UpgradeStatusUpToDate", "UpgradeStatusNotUpgradable", "UpgradeStatusRefChangeBlocked", "UpgradeStatusFailed" ] }, "github_com_stacklok_toolhive_pkg_skills.ValidationResult": { "properties": { "errors": { "description": "Errors is a list of validation errors, if any.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "valid": { "description": "Valid indicates whether the skill definition is valid.", "type": "boolean" }, "warnings": { "description": "Warnings is a list of non-blocking validation warnings, if any.", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_webhook.Config": { "properties": { "failure_policy": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_webhook.FailurePolicy" }, "hmac_secret_ref": { "description": "HMACSecretRef is an optional reference to an HMAC secret for payload signing.", "type": "string" }, "name": { "description": "Name is a unique identifier for this webhook.", "type": "string" }, "timeout": { "description": "Timeout is the maximum time to wait for a webhook response.", "type": "integer" }, "tls_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_webhook.TLSConfig" }, "url": { "description": "URL is the HTTPS endpoint to call.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_webhook.FailurePolicy": { "description": "FailurePolicy determines behavior when the webhook call fails.", "enum": ["fail", "ignore"], "type": "string", "x-enum-varnames": ["FailurePolicyFail", "FailurePolicyIgnore"] }, "github_com_stacklok_toolhive_pkg_webhook.TLSConfig": { "description": "TLSConfig holds optional TLS configuration (CA bundles, client certs).", "properties": { "ca_bundle_path": { "description": "CABundlePath is the path to a CA certificate bundle for server verification.", "type": "string" }, "client_cert_path": { "description": "ClientCertPath is the path to a client certificate for mTLS.", "type": "string" }, "client_key_path": { "description": "ClientKeyPath is the path to a client key for mTLS.", "type": "string" }, "insecure_skip_verify": { "description": "InsecureSkipVerify disables server certificate verification.\nWARNING: This should only be used for development/testing.", "type": "boolean" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_workloads_upgrade.CheckResult": { "description": "Result is the upgrade-check outcome for the workload. It carries only\nmetadata (status, image references, drift) and never secret values.", "properties": { "candidate_image": { "description": "CandidateImage is the image reference the registry currently reports.", "type": "string" }, "config_drift": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.ConfigDrift" }, "current_image": { "description": "CurrentImage is the image reference the workload is currently running.", "type": "string" }, "env_var_drift": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.EnvVarDrift" }, "reason": { "description": "Reason provides additional context, primarily for StatusUnknown.", "type": "string" }, "registry_server": { "description": "RegistryServer is the registry entry name the workload was sourced from.\nEmpty when the workload is not registry-sourced.", "type": "string" }, "status": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.UpgradeStatus" }, "workload_name": { "description": "WorkloadName is the name of the workload that was checked.", "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_workloads_upgrade.ConfigDrift": { "description": "ConfigDrift describes posture differences (transport, permission profile)\nbetween the workload and the candidate registry entry.", "properties": { "permission_profile": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.StringChange" }, "transport": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.StringChange" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_workloads_upgrade.EnvVarDrift": { "description": "EnvVarDrift describes environment variables the candidate registry entry\ndeclares that differ from the workload's current configuration.", "properties": { "added": { "description": "Added lists environment variables the candidate declares that the\nworkload does not currently supply (via plain env vars or secrets).", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.EnvVarInfo" }, "type": "array", "uniqueItems": false }, "removed": { "description": "Removed lists environment variables the workload supplies that the\ncandidate no longer declares. Populated on a best-effort basis; may be\nempty even when removals exist (forward-compatible field).", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.EnvVarInfo" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_workloads_upgrade.EnvVarInfo": { "properties": { "default": { "description": "Default is the candidate's default value. It is cleared (left empty)\nwhenever Secret is true: a secret env var's default could carry sensitive\ndata, and surfacing it in a drift report (which may be logged or returned\nover the API) would leak it. Non-secret defaults are safe to display.", "type": "string" }, "description": { "description": "Description is the human-readable purpose of the variable.", "type": "string" }, "name": { "description": "Name is the environment variable name.", "type": "string" }, "required": { "description": "Required indicates whether the candidate marks the variable as required.", "type": "boolean" }, "secret": { "description": "Secret indicates whether the variable holds sensitive data.", "type": "boolean" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_workloads_upgrade.StringChange": { "description": "PermissionProfile is set when the candidate's permission profile differs\nfrom the workload's current profile.", "properties": { "from": { "type": "string" }, "to": { "type": "string" } }, "type": "object" }, "github_com_stacklok_toolhive_pkg_workloads_upgrade.UpgradeStatus": { "description": "Status is the upgrade status for the workload.", "enum": [ "up-to-date", "upgrade-available", "not-registry-sourced", "server-not-found", "unknown" ], "type": "string", "x-enum-varnames": [ "StatusUpToDate", "StatusUpgradeAvailable", "StatusNotRegistrySourced", "StatusServerNotFound", "StatusUnknown" ] }, "ignore.Config": { "description": "IgnoreConfig contains configuration for ignore processing", "properties": { "loadGlobal": { "description": "Whether to load global ignore patterns", "type": "boolean" }, "printOverlays": { "description": "Whether to print resolved overlay paths for debugging", "type": "boolean" } }, "type": "object" }, "model.Argument": { "properties": { "choices": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "default": { "type": "string" }, "description": { "type": "string" }, "format": { "$ref": "#/components/schemas/model.Format" }, "isRepeated": { "type": "boolean" }, "isRequired": { "type": "boolean" }, "isSecret": { "type": "boolean" }, "name": { "example": "--port", "type": "string" }, "placeholder": { "type": "string" }, "type": { "$ref": "#/components/schemas/model.ArgumentType" }, "value": { "type": "string" }, "valueHint": { "example": "file_path", "type": "string" }, "variables": { "additionalProperties": { "$ref": "#/components/schemas/model.Input" }, "type": "object" } }, "type": "object" }, "model.ArgumentType": { "enum": ["positional", "named"], "example": "positional", "type": "string", "x-enum-varnames": ["ArgumentTypePositional", "ArgumentTypeNamed"] }, "model.Format": { "enum": ["string", "number", "boolean", "filepath"], "type": "string", "x-enum-varnames": [ "FormatString", "FormatNumber", "FormatBoolean", "FormatFilePath" ] }, "model.Icon": { "properties": { "mimeType": { "example": "image/png", "type": "string" }, "sizes": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "src": { "example": "https://example.com/icon.png", "format": "uri", "maxLength": 255, "type": "string" }, "theme": { "type": "string" } }, "type": "object" }, "model.Input": { "properties": { "choices": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "default": { "type": "string" }, "description": { "type": "string" }, "format": { "$ref": "#/components/schemas/model.Format" }, "isRequired": { "type": "boolean" }, "isSecret": { "type": "boolean" }, "placeholder": { "type": "string" }, "value": { "type": "string" } }, "type": "object" }, "model.KeyValueInput": { "properties": { "choices": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "default": { "type": "string" }, "description": { "type": "string" }, "format": { "$ref": "#/components/schemas/model.Format" }, "isRequired": { "type": "boolean" }, "isSecret": { "type": "boolean" }, "name": { "example": "SOME_VARIABLE", "type": "string" }, "placeholder": { "type": "string" }, "value": { "type": "string" }, "variables": { "additionalProperties": { "$ref": "#/components/schemas/model.Input" }, "type": "object" } }, "type": "object" }, "model.Package": { "properties": { "environmentVariables": { "description": "EnvironmentVariables are set when running the package", "items": { "$ref": "#/components/schemas/model.KeyValueInput" }, "type": "array", "uniqueItems": false }, "fileSha256": { "description": "FileSHA256 is the SHA-256 hash for integrity verification (required for mcpb, optional for others)", "example": "fe333e598595000ae021bd27117db32ec69af6987f507ba7a63c90638ff633ce", "pattern": "^[a-f0-9]{64}$", "type": "string" }, "identifier": { "description": "Identifier is the package identifier:\n - For NPM/PyPI/NuGet: package name or ID\n - For OCI: full image reference (e.g., \"ghcr.io/owner/repo:v1.0.0\")\n - For MCPB: direct download URL", "example": "@modelcontextprotocol/server-brave-search", "minLength": 1, "type": "string" }, "packageArguments": { "description": "PackageArguments are passed to the package's binary", "items": { "$ref": "#/components/schemas/model.Argument" }, "type": "array", "uniqueItems": false }, "registryBaseUrl": { "description": "RegistryBaseURL is the base URL of the package registry (used by npm, pypi, nuget, cargo; not used by oci, mcpb)", "example": "https://registry.npmjs.org", "format": "uri", "type": "string" }, "registryType": { "description": "RegistryType indicates how to download packages (e.g., \"npm\", \"pypi\", \"cargo\", \"oci\", \"nuget\", \"mcpb\")", "example": "npm", "minLength": 1, "type": "string" }, "runtimeArguments": { "description": "RuntimeArguments are passed to the package's runtime command (e.g., docker, npx)", "items": { "$ref": "#/components/schemas/model.Argument" }, "type": "array", "uniqueItems": false }, "runtimeHint": { "description": "RunTimeHint suggests the appropriate runtime for the package", "example": "npx", "type": "string" }, "transport": { "$ref": "#/components/schemas/model.Transport" }, "version": { "description": "Version is the package version (required for npm, pypi, nuget; optional for mcpb; not used by oci where version is in the identifier)", "example": "1.0.2", "maxLength": 255, "minLength": 1, "type": "string" } }, "type": "object" }, "model.Repository": { "properties": { "id": { "example": "b94b5f7e-c7c6-d760-2c78-a5e9b8a5b8c9", "type": "string" }, "source": { "example": "github", "type": "string" }, "subfolder": { "example": "src/everything", "type": "string" }, "url": { "example": "https://github.com/modelcontextprotocol/servers", "format": "uri", "type": "string" } }, "type": "object" }, "model.Transport": { "description": "Transport is required and specifies the transport protocol configuration", "properties": { "headers": { "items": { "$ref": "#/components/schemas/model.KeyValueInput" }, "type": "array", "uniqueItems": false }, "type": { "example": "stdio", "type": "string" }, "url": { "example": "https://api.example.com/mcp", "type": "string" }, "variables": { "additionalProperties": { "$ref": "#/components/schemas/model.Input" }, "type": "object" } }, "type": "object" }, "permissions.InboundNetworkPermissions": { "description": "Inbound defines inbound network permissions", "properties": { "allow_host": { "description": "AllowHost is a list of allowed hosts for inbound connections", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "permissions.NetworkPermissions": { "description": "Network defines network permissions", "properties": { "inbound": { "$ref": "#/components/schemas/permissions.InboundNetworkPermissions" }, "mode": { "description": "Mode specifies the network mode for the container (e.g., \"host\", \"bridge\", \"none\")\nWhen empty, the default container runtime network mode is used", "type": "string" }, "outbound": { "$ref": "#/components/schemas/permissions.OutboundNetworkPermissions" } }, "type": "object" }, "permissions.OutboundNetworkPermissions": { "description": "Outbound defines outbound network permissions", "properties": { "allow_host": { "description": "AllowHost is a list of allowed hosts", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "allow_port": { "description": "AllowPort is a list of allowed ports", "items": { "type": "integer" }, "type": "array", "uniqueItems": false }, "insecure_allow_all": { "description": "InsecureAllowAll allows all outbound network connections", "type": "boolean" } }, "type": "object" }, "permissions.Profile": { "description": "Permission profile to apply", "properties": { "name": { "description": "Name is the name of the profile", "type": "string" }, "network": { "$ref": "#/components/schemas/permissions.NetworkPermissions" }, "privileged": { "description": "Privileged indicates whether the container should run in privileged mode\nWhen true, the container has access to all host devices and capabilities\nUse with extreme caution as this removes most security isolation", "type": "boolean" }, "read": { "description": "Read is a list of mount declarations that the container can read from\nThese can be in the following formats:\n- A single path: The same path will be mounted from host to container\n- host-path:container-path: Different paths for host and container\n- resource-uri:container-path: Mount a resource identified by URI to a container path", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "write": { "description": "Write is a list of mount declarations that the container can write to\nThese follow the same format as Read mounts but with write permissions", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.RegistryType": { "description": "Type of registry (file, url, or default)", "enum": ["file", "url", "api", "default"], "type": "string", "x-enum-varnames": [ "RegistryTypeFile", "RegistryTypeURL", "RegistryTypeAPI", "RegistryTypeDefault" ] }, "pkg_api_v1.UpdateRegistryAuthRequest": { "description": "OAuth authentication configuration (optional)", "properties": { "audience": { "description": "OAuth audience (optional)", "type": "string" }, "client_id": { "description": "OAuth client ID", "type": "string" }, "issuer": { "description": "OIDC issuer URL", "type": "string" }, "scopes": { "description": "OAuth scopes (optional)", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.UpdateRegistryRequest": { "description": "Request containing registry configuration updates", "properties": { "allow_private_ip": { "description": "Allow private IP addresses for registry URL or API URL", "type": "boolean" }, "api_url": { "description": "MCP Registry API URL", "type": "string" }, "auth": { "$ref": "#/components/schemas/pkg_api_v1.UpdateRegistryAuthRequest" }, "local_path": { "description": "Local registry file path", "type": "string" }, "url": { "description": "Registry URL (for remote registries)", "type": "string" } }, "type": "object" }, "pkg_api_v1.UpdateRegistryResponse": { "description": "Response containing update result", "properties": { "type": { "description": "Registry type after update", "type": "string" } }, "type": "object" }, "pkg_api_v1.buildListResponse": { "description": "Response containing a list of locally-built OCI skill artifacts", "properties": { "builds": { "description": "List of locally-built OCI skill artifacts", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.LocalBuild" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.buildSkillRequest": { "description": "Request to build a skill from a local directory", "properties": { "path": { "description": "Path to the skill definition directory", "type": "string" }, "tag": { "description": "OCI tag for the built artifact", "type": "string" } }, "type": "object" }, "pkg_api_v1.bulkClientRequest": { "properties": { "groups": { "description": "Groups is the list of groups configured on the client.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "names": { "description": "Names is the list of client names to operate on.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.ClientApp" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.bulkOperationRequest": { "properties": { "group": { "description": "Group name to operate on (mutually exclusive with names)", "type": "string" }, "names": { "description": "Names of the workloads to operate on", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.clientStatusResponse": { "properties": { "clients": { "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.ClientAppStatus" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.createClientRequest": { "properties": { "groups": { "description": "Groups is the list of groups configured on the client.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "name": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.ClientApp" } }, "type": "object" }, "pkg_api_v1.createClientResponse": { "properties": { "groups": { "description": "Groups is the list of groups configured on the client.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "name": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.ClientApp" } }, "type": "object" }, "pkg_api_v1.createGroupRequest": { "properties": { "name": { "description": "Name of the group to create", "type": "string" } }, "type": "object" }, "pkg_api_v1.createGroupResponse": { "properties": { "name": { "description": "Name of the created group", "type": "string" } }, "type": "object" }, "pkg_api_v1.createRequest": { "description": "Request to create a new workload", "properties": { "allow_docker_gateway": { "description": "Whether to permit outbound connections to Docker gateway addresses\n(host.docker.internal, gateway.docker.internal, 172.17.0.1). These are\nblocked by default in the egress proxy even when network isolation is on.\nOnly applicable to Docker deployments with network isolation enabled.", "type": "boolean" }, "authz_config": { "description": "Authorization configuration", "type": "string" }, "cmd_arguments": { "description": "Command arguments to pass to the container", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "env_vars": { "additionalProperties": { "type": "string" }, "description": "Environment variables to set in the container", "type": "object" }, "group": { "description": "Group name this workload belongs to", "type": "string" }, "header_forward": { "$ref": "#/components/schemas/pkg_api_v1.headerForwardConfig" }, "headers": { "items": { "$ref": "#/components/schemas/registry.Header" }, "type": "array", "uniqueItems": false }, "host": { "description": "Host to bind to", "type": "string" }, "image": { "description": "Docker image to use", "type": "string" }, "name": { "description": "Name of the workload", "type": "string" }, "network_isolation": { "description": "Whether network isolation is turned on. This applies the rules in the permission profile.\nPointer so that omitting the field defaults to network isolation ENABLED (matching the\n`thv run` CLI default); set it explicitly to false to disable network isolation.\nThis also applies on update: a request that omits this field enables isolation, so\nclients that build update requests from scratch should send it explicitly to avoid\nunintentionally turning isolation on for a workload that had it off.", "type": "boolean" }, "oauth_config": { "$ref": "#/components/schemas/pkg_api_v1.remoteOAuthConfig" }, "oidc": { "$ref": "#/components/schemas/pkg_api_v1.oidcOptions" }, "permission_profile": { "$ref": "#/components/schemas/permissions.Profile" }, "proxy_mode": { "description": "Proxy mode to use", "type": "string" }, "proxy_port": { "description": "Port for the HTTP proxy to listen on", "type": "integer" }, "registry": { "description": "Registry is the optional registry name to resolve the server from (e.g. \"default\").", "type": "string" }, "runtime_config": { "$ref": "#/components/schemas/templates.RuntimeConfig" }, "secrets": { "description": "Secret parameters to inject", "items": { "$ref": "#/components/schemas/secrets.SecretParameter" }, "type": "array", "uniqueItems": false }, "server": { "description": "Server is the optional server name in the registry (e.g. \"io.github.stacklok/fetch\").\nWhen both Registry and Server are set, thv resolves the server metadata\nserver-side, filling in image, transport, env vars, permissions, etc.\nUser-provided fields always override registry defaults.", "type": "string" }, "target_port": { "description": "Port to expose from the container", "type": "integer" }, "tools": { "description": "Tools filter", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "tools_override": { "additionalProperties": { "$ref": "#/components/schemas/pkg_api_v1.toolOverride" }, "description": "Tools override", "type": "object" }, "transport": { "description": "Transport configuration", "type": "string" }, "trust_proxy_headers": { "description": "Whether to trust X-Forwarded-* headers from reverse proxies", "type": "boolean" }, "url": { "description": "Remote server specific fields", "type": "string" }, "volumes": { "description": "Volume mounts", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.createSecretRequest": { "description": "Request to create a new secret", "properties": { "key": { "description": "Secret key name", "type": "string" }, "value": { "description": "Secret value", "type": "string" } }, "type": "object" }, "pkg_api_v1.createSecretResponse": { "description": "Response after creating a secret", "properties": { "key": { "description": "Secret key that was created", "type": "string" }, "message": { "description": "Success message", "type": "string" } }, "type": "object" }, "pkg_api_v1.createWorkloadResponse": { "description": "Response after successfully creating a workload", "properties": { "name": { "description": "Name of the created workload", "type": "string" }, "port": { "description": "Port the workload is listening on", "type": "integer" } }, "type": "object" }, "pkg_api_v1.getRegistryResponse": { "description": "Response containing registry details", "properties": { "auth_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_registry.OAuthPublicConfig" }, "auth_status": { "description": "AuthStatus is one of: \"none\", \"configured\", \"authenticated\".\nIntentionally omits omitempty — see registryInfo for rationale.", "type": "string" }, "auth_type": { "description": "AuthType is \"oauth\", \"bearer\" (future), or empty string when no auth.\nIntentionally omits omitempty — see registryInfo for rationale.", "type": "string" }, "last_updated": { "description": "Last updated timestamp", "type": "string" }, "name": { "description": "Name of the registry", "type": "string" }, "registry": { "$ref": "#/components/schemas/registry.Registry" }, "server_count": { "description": "Number of servers in the registry", "type": "integer" }, "source": { "description": "Source of the registry (URL, file path, or empty string for built-in)", "type": "string" }, "type": { "$ref": "#/components/schemas/pkg_api_v1.RegistryType" }, "version": { "description": "Version of the registry schema", "type": "string" } }, "type": "object" }, "pkg_api_v1.getSecretsProviderResponse": { "description": "Response containing secrets provider details", "properties": { "capabilities": { "$ref": "#/components/schemas/pkg_api_v1.providerCapabilitiesResponse" }, "name": { "description": "Name of the secrets provider", "type": "string" }, "provider_type": { "description": "Type of the secrets provider", "type": "string" } }, "type": "object" }, "pkg_api_v1.getServerResponse": { "description": "Response containing server details", "properties": { "is_remote": { "description": "Indicates if this is a remote server", "type": "boolean" }, "remote_server": { "$ref": "#/components/schemas/registry.RemoteServerMetadata" }, "server": { "$ref": "#/components/schemas/registry.ImageMetadata" } }, "type": "object" }, "pkg_api_v1.groupListResponse": { "properties": { "groups": { "description": "List of groups", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_groups.Group" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.headerForwardConfig": { "description": "HeaderForward configures headers to inject into requests to remote MCP servers.\nUse this to add custom headers like X-Tenant-ID or correlation IDs.", "properties": { "add_headers_from_secret": { "additionalProperties": { "type": "string" }, "description": "AddHeadersFromSecret maps header names to secret names in ToolHive's secrets manager.\nKey: HTTP header name, Value: secret name in the secrets manager", "type": "object" }, "add_plaintext_headers": { "additionalProperties": { "type": "string" }, "description": "AddPlaintextHeaders contains literal header values to inject.\nWARNING: These values are stored and transmitted in plaintext.\nUse AddHeadersFromSecret for sensitive data like API keys.", "type": "object" } }, "type": "object" }, "pkg_api_v1.installSkillRequest": { "description": "Request to install a skill", "properties": { "clients": { "description": "Clients lists target client identifiers (e.g., \"claude-code\"),\nor [\"all\"] to target every skill-supporting client.\nOmitting this field installs to all available clients.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "force": { "description": "Force allows overwriting unmanaged skill directories", "type": "boolean" }, "group": { "description": "Group is the group name to add the skill to after installation", "type": "string" }, "name": { "description": "Name or OCI reference of the skill to install", "type": "string" }, "project_root": { "description": "ProjectRoot is the project root path for project-scoped installs", "type": "string" }, "scope": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.Scope" }, "version": { "description": "Version to install (empty means latest)", "type": "string" } }, "type": "object" }, "pkg_api_v1.installSkillResponse": { "description": "Response after successfully installing a skill", "properties": { "skill": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.InstalledSkill" } }, "type": "object" }, "pkg_api_v1.listSecretsResponse": { "description": "Response containing a list of secret keys", "properties": { "keys": { "description": "List of secret keys", "items": { "$ref": "#/components/schemas/pkg_api_v1.secretKeyResponse" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.listServersResponse": { "description": "Response containing a list of servers", "properties": { "remote_servers": { "description": "List of remote servers in the registry (if any)", "items": { "$ref": "#/components/schemas/registry.RemoteServerMetadata" }, "type": "array", "uniqueItems": false }, "servers": { "description": "List of container servers in the registry", "items": { "$ref": "#/components/schemas/registry.ImageMetadata" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.oidcOptions": { "description": "OIDC configuration options", "properties": { "audience": { "description": "Expected audience", "type": "string" }, "client_id": { "description": "OAuth2 client ID", "type": "string" }, "client_secret": { "description": "OAuth2 client secret", "type": "string" }, "introspection_url": { "description": "Token introspection URL for OIDC", "type": "string" }, "issuer": { "description": "OIDC issuer URL", "type": "string" }, "jwks_url": { "description": "JWKS URL for key verification", "type": "string" }, "scopes": { "description": "OAuth scopes to advertise in well-known endpoint (RFC 9728)", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.paginationV01Metadata": { "description": "Metadata contains pagination information", "properties": { "limit": { "description": "Limit is the maximum number of items per page", "type": "integer" }, "page": { "description": "Page is the current page number (1-based)", "type": "integer" }, "total": { "description": "Total is the total number of items matching the query", "type": "integer" } }, "type": "object" }, "pkg_api_v1.providerCapabilitiesResponse": { "description": "Capabilities of the secrets provider", "properties": { "can_cleanup": { "description": "Whether the provider can cleanup all secrets", "type": "boolean" }, "can_delete": { "description": "Whether the provider can delete secrets", "type": "boolean" }, "can_list": { "description": "Whether the provider can list secrets", "type": "boolean" }, "can_read": { "description": "Whether the provider can read secrets", "type": "boolean" }, "can_write": { "description": "Whether the provider can write secrets", "type": "boolean" } }, "type": "object" }, "pkg_api_v1.pushSkillRequest": { "description": "Request to push a built skill artifact", "properties": { "reference": { "description": "OCI reference to push", "type": "string" } }, "type": "object" }, "pkg_api_v1.registryErrorResponse": { "description": "Structured error response returned by registry endpoints", "properties": { "code": { "description": "Code is a machine-readable error code (e.g. \"not_found\", \"registry_auth_required\")", "type": "string" }, "message": { "description": "Message is a human-readable description of the error", "type": "string" } }, "type": "object" }, "pkg_api_v1.registryInfo": { "description": "Basic information about a registry", "properties": { "auth_config": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_registry.OAuthPublicConfig" }, "auth_status": { "description": "AuthStatus is one of: \"none\", \"configured\", \"authenticated\".\nIntentionally omits omitempty so clients always receive the field,\neven when the value is \"none\" (the zero-value equivalent).", "type": "string" }, "auth_type": { "description": "AuthType is \"oauth\", \"bearer\" (future), or empty string when no auth.\nIntentionally omits omitempty so clients can distinguish \"no auth\nconfigured\" (empty string) from \"field missing\" without extra logic.", "type": "string" }, "last_updated": { "description": "Last updated timestamp", "type": "string" }, "name": { "description": "Name of the registry", "type": "string" }, "server_count": { "description": "Number of servers in the registry", "type": "integer" }, "source": { "description": "Source of the registry (URL, file path, or empty string for built-in)", "type": "string" }, "type": { "$ref": "#/components/schemas/pkg_api_v1.RegistryType" }, "version": { "description": "Version of the registry schema", "type": "string" } }, "type": "object" }, "pkg_api_v1.registryListResponse": { "description": "Response containing a list of registries", "properties": { "registries": { "description": "List of registries", "items": { "$ref": "#/components/schemas/pkg_api_v1.registryInfo" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.remoteOAuthConfig": { "description": "OAuth configuration for remote server authentication", "properties": { "authorize_url": { "description": "OAuth authorization endpoint URL (alternative to issuer for non-OIDC OAuth)", "type": "string" }, "bearer_token": { "$ref": "#/components/schemas/secrets.SecretParameter" }, "callback_port": { "description": "Specific port for OAuth callback server", "type": "integer" }, "client_id": { "description": "OAuth client ID for authentication", "type": "string" }, "client_secret": { "$ref": "#/components/schemas/secrets.SecretParameter" }, "issuer": { "description": "OAuth/OIDC issuer URL (e.g., https://accounts.google.com)", "type": "string" }, "oauth_params": { "additionalProperties": { "type": "string" }, "description": "Additional OAuth parameters for server-specific customization", "type": "object" }, "resource": { "description": "OAuth 2.0 resource indicator (RFC 8707)", "type": "string" }, "scopes": { "description": "OAuth scopes to request", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "skip_browser": { "description": "Whether to skip opening browser for OAuth flow (defaults to false)", "type": "boolean" }, "token_url": { "description": "OAuth token endpoint URL (alternative to issuer for non-OIDC OAuth)", "type": "string" }, "use_pkce": { "description": "Whether to use PKCE for the OAuth flow", "type": "boolean" } }, "type": "object" }, "pkg_api_v1.secretKeyResponse": { "description": "Secret key information", "properties": { "description": { "description": "Optional description of the secret", "type": "string" }, "key": { "description": "Secret key name", "type": "string" } }, "type": "object" }, "pkg_api_v1.serversV01Response": { "description": "Paginated list of servers from the registry", "properties": { "metadata": { "$ref": "#/components/schemas/pkg_api_v1.paginationV01Metadata" }, "servers": { "description": "Servers is the list of servers on the current page", "items": { "$ref": "#/components/schemas/v0.ServerJSON" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.setupSecretsRequest": { "description": "Request to setup a secrets provider", "properties": { "password": { "description": "Password for encrypted provider (optional, can be set via environment variable)\nTODO Review environment variable for this", "type": "string" }, "provider_type": { "description": "Type of the secrets provider (encrypted, 1password, environment)", "type": "string" } }, "type": "object" }, "pkg_api_v1.setupSecretsResponse": { "description": "Response after initializing a secrets provider", "properties": { "message": { "description": "Success message", "type": "string" }, "provider_type": { "description": "Type of the secrets provider that was setup", "type": "string" } }, "type": "object" }, "pkg_api_v1.skillListResponse": { "description": "Response containing a list of installed skills", "properties": { "skills": { "description": "List of installed skills", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.InstalledSkill" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.skillsV01Response": { "description": "Paginated list of skills from the registry", "properties": { "metadata": { "$ref": "#/components/schemas/pkg_api_v1.paginationV01Metadata" }, "skills": { "description": "Skills is the list of skills on the current page", "items": { "$ref": "#/components/schemas/registry.Skill" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.syncSkillsRequest": { "description": "Request to restore a project's installed skills to match its lock file", "properties": { "adopt": { "description": "Adopt writes lock entries for existing unmanaged project-scope installs", "type": "boolean" }, "check": { "description": "Check verifies on-disk content against the lock file without installing or writing anything", "type": "boolean" }, "clients": { "description": "Clients lists target client identifiers. Empty means every\nskill-supporting client detected on this host.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "project_root": { "description": "ProjectRoot is the project root path whose lock file should be synced", "type": "string" }, "prune": { "description": "Prune removes project-scoped skills installed but not present in the lock file", "type": "boolean" } }, "type": "object" }, "pkg_api_v1.toolOverride": { "description": "Tool override", "properties": { "description": { "description": "Description of the tool", "type": "string" }, "name": { "description": "Name of the tool", "type": "string" } }, "type": "object" }, "pkg_api_v1.updateRequest": { "description": "Request to update an existing workload (name cannot be changed)", "properties": { "allow_docker_gateway": { "description": "Whether to permit outbound connections to Docker gateway addresses\n(host.docker.internal, gateway.docker.internal, 172.17.0.1). These are\nblocked by default in the egress proxy even when network isolation is on.\nOnly applicable to Docker deployments with network isolation enabled.", "type": "boolean" }, "authz_config": { "description": "Authorization configuration", "type": "string" }, "cmd_arguments": { "description": "Command arguments to pass to the container", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "env_vars": { "additionalProperties": { "type": "string" }, "description": "Environment variables to set in the container", "type": "object" }, "group": { "description": "Group name this workload belongs to", "type": "string" }, "header_forward": { "$ref": "#/components/schemas/pkg_api_v1.headerForwardConfig" }, "headers": { "items": { "$ref": "#/components/schemas/registry.Header" }, "type": "array", "uniqueItems": false }, "host": { "description": "Host to bind to", "type": "string" }, "image": { "description": "Docker image to use", "type": "string" }, "network_isolation": { "description": "Whether network isolation is turned on. This applies the rules in the permission profile.\nPointer so that omitting the field defaults to network isolation ENABLED (matching the\n`thv run` CLI default); set it explicitly to false to disable network isolation.\nThis also applies on update: a request that omits this field enables isolation, so\nclients that build update requests from scratch should send it explicitly to avoid\nunintentionally turning isolation on for a workload that had it off.", "type": "boolean" }, "oauth_config": { "$ref": "#/components/schemas/pkg_api_v1.remoteOAuthConfig" }, "oidc": { "$ref": "#/components/schemas/pkg_api_v1.oidcOptions" }, "permission_profile": { "$ref": "#/components/schemas/permissions.Profile" }, "proxy_mode": { "description": "Proxy mode to use", "type": "string" }, "proxy_port": { "description": "Port for the HTTP proxy to listen on", "type": "integer" }, "runtime_config": { "$ref": "#/components/schemas/templates.RuntimeConfig" }, "secrets": { "description": "Secret parameters to inject", "items": { "$ref": "#/components/schemas/secrets.SecretParameter" }, "type": "array", "uniqueItems": false }, "target_port": { "description": "Port to expose from the container", "type": "integer" }, "tools": { "description": "Tools filter", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "tools_override": { "additionalProperties": { "$ref": "#/components/schemas/pkg_api_v1.toolOverride" }, "description": "Tools override", "type": "object" }, "transport": { "description": "Transport configuration", "type": "string" }, "trust_proxy_headers": { "description": "Whether to trust X-Forwarded-* headers from reverse proxies", "type": "boolean" }, "url": { "description": "Remote server specific fields", "type": "string" }, "volumes": { "description": "Volume mounts", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.updateSecretRequest": { "description": "Request to update an existing secret", "properties": { "value": { "description": "New secret value", "type": "string" } }, "type": "object" }, "pkg_api_v1.updateSecretResponse": { "description": "Response after updating a secret", "properties": { "key": { "description": "Secret key that was updated", "type": "string" }, "message": { "description": "Success message", "type": "string" } }, "type": "object" }, "pkg_api_v1.upgradeCheckBulkResponse": { "description": "Results of checking multiple workloads for available upgrades", "properties": { "results": { "description": "Results holds one upgrade-check outcome per scoped workload, in the order\nthe workloads were enumerated. Each entry carries only metadata and never\nsecret values.", "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.CheckResult" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.upgradeCheckResponse": { "description": "Result of checking a single workload for an available upgrade", "properties": { "result": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_workloads_upgrade.CheckResult" } }, "type": "object" }, "pkg_api_v1.upgradeRequest": { "description": "Request to apply an available upgrade to a workload. All fields are optional; an empty body applies the upgrade preserving the workload's existing configuration.", "properties": { "env": { "additionalProperties": { "type": "string" }, "description": "Env holds additional or overriding environment variables to merge into the\nupgraded workload's configuration.", "type": "object" }, "secrets": { "description": "Secrets holds additional secret parameters (`\u003cname\u003e,target=\u003cenv\u003e`) to merge\ninto the upgraded workload's configuration. Only references are accepted;\nno secret values are transmitted in the request.", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.upgradeSkillsRequest": { "description": "Request to re-resolve a project's lock entries and install newer content", "properties": { "allow_ref_change": { "description": "AllowRefChange permits resolvedReference changes during upgrade", "type": "boolean" }, "clients": { "description": "Clients lists target client identifiers. Empty means every\nskill-supporting client detected on this host.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "fail_on_changes": { "description": "FailOnChanges exits with an error when any mutable source would upgrade", "type": "boolean" }, "names": { "description": "Names restricts the upgrade to specific skill names. Empty means every entry.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "preview": { "description": "Preview reports what would change without installing (still fetches to compare digests)", "type": "boolean" }, "project_root": { "description": "ProjectRoot is the project root path whose lock file should be upgraded", "type": "string" } }, "type": "object" }, "pkg_api_v1.validateSkillRequest": { "description": "Request to validate a skill definition", "properties": { "path": { "description": "Path to the skill definition directory", "type": "string" } }, "type": "object" }, "pkg_api_v1.versionResponse": { "properties": { "version": { "type": "string" } }, "type": "object" }, "pkg_api_v1.workloadListResponse": { "description": "Response containing a list of workloads", "properties": { "workloads": { "description": "List of container information for each workload", "items": { "$ref": "#/components/schemas/core.Workload" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "pkg_api_v1.workloadStatusResponse": { "description": "Response containing workload status information", "properties": { "status": { "description": "Current status of the workload", "enum": [ "running", "stopped", "error", "starting", "stopping", "unhealthy", "removing", "unknown", "unauthenticated", "auth_retrying", "policy_stopped" ], "type": "string" } }, "type": "object" }, "registry.EnvVar": { "properties": { "default": { "description": "Default is the value to use if the environment variable is not explicitly provided\nOnly used for non-required variables", "type": "string" }, "description": { "description": "Description is a human-readable explanation of the variable's purpose", "type": "string" }, "name": { "description": "Name is the environment variable name (e.g., API_KEY)", "type": "string" }, "required": { "description": "Required indicates whether this environment variable must be provided\nIf true and not provided via command line or secrets, the user will be prompted for a value", "type": "boolean" }, "secret": { "description": "Secret indicates whether this environment variable contains sensitive information\nIf true, the value will be stored as a secret rather than as a plain environment variable", "type": "boolean" } }, "type": "object" }, "registry.Group": { "properties": { "description": { "description": "Description is a human-readable description of the group's purpose and functionality", "type": "string" }, "name": { "description": "Name is the identifier for the group, used when referencing the group in commands", "type": "string" }, "remote_servers": { "additionalProperties": { "$ref": "#/components/schemas/registry.RemoteServerMetadata" }, "description": "RemoteServers is a map of server names to their corresponding remote server definitions within this group", "type": "object" }, "servers": { "additionalProperties": { "$ref": "#/components/schemas/registry.ImageMetadata" }, "description": "Servers is a map of server names to their corresponding server definitions within this group", "type": "object" } }, "type": "object" }, "registry.Header": { "properties": { "choices": { "description": "Choices provides a list of valid values for the header (optional)", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "default": { "description": "Default is the value to use if the header is not explicitly provided\nOnly used for non-required headers", "type": "string" }, "description": { "description": "Description is a human-readable explanation of the header's purpose", "type": "string" }, "name": { "description": "Name is the header name (e.g., X-API-Key, Authorization)", "type": "string" }, "required": { "description": "Required indicates whether this header must be provided\nIf true and not provided via command line or secrets, the user will be prompted for a value", "type": "boolean" }, "secret": { "description": "Secret indicates whether this header contains sensitive information\nIf true, the value will be stored as a secret rather than as plain text", "type": "boolean" } }, "type": "object" }, "registry.ImageMetadata": { "description": "Container server details (if it's a container server)", "properties": { "args": { "description": "Args are the default command-line arguments to pass to the MCP server container.\nThese arguments will be used only if no command-line arguments are provided by the user.\nIf the user provides arguments, they will override these defaults.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "custom_metadata": { "additionalProperties": {}, "description": "CustomMetadata allows for additional user-defined metadata", "type": "object" }, "description": { "description": "Description is a human-readable description of the server's purpose and functionality", "type": "string" }, "docker_tags": { "description": "DockerTags lists the available Docker tags for this server image", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "env_vars": { "description": "EnvVars defines environment variables that can be passed to the server", "items": { "$ref": "#/components/schemas/registry.EnvVar" }, "type": "array", "uniqueItems": false }, "image": { "description": "Image is the Docker image reference for the MCP server", "type": "string" }, "metadata": { "$ref": "#/components/schemas/registry.Metadata" }, "name": { "description": "Name is the identifier for the MCP server, used when referencing the server in commands\nIf not provided, it will be auto-generated from the registry key", "type": "string" }, "overview": { "description": "Overview is a longer Markdown-formatted description for web display.\nUnlike the Description field (limited to 500 chars), this supports\nfull Markdown and is intended for rich rendering on catalog pages.", "type": "string" }, "permissions": { "$ref": "#/components/schemas/permissions.Profile" }, "provenance": { "$ref": "#/components/schemas/registry.Provenance" }, "proxy_port": { "description": "ProxyPort is the port for the HTTP proxy to listen on (host port)\nIf not specified, a random available port will be assigned", "type": "integer" }, "repository_url": { "description": "RepositoryURL is the URL to the source code repository for the server", "type": "string" }, "stateless": { "description": "Stateless indicates the server only supports POST (no SSE/GET)", "type": "boolean" }, "status": { "description": "Status indicates whether the server is currently active or deprecated", "type": "string" }, "tags": { "description": "Tags are categorization labels for the server to aid in discovery and filtering", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "target_port": { "description": "TargetPort is the port for the container to expose (only applicable to SSE and Streamable HTTP transports)", "type": "integer" }, "tier": { "description": "Tier represents the tier classification level of the server, e.g., \"Official\" or \"Community\"", "type": "string" }, "title": { "description": "Title is an optional human-readable display name for the server.\nIf not provided, the Name field is used for display purposes.", "type": "string" }, "tools": { "description": "Tools is a list of tool names provided by this MCP server", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "transport": { "description": "Transport defines the communication protocol for the server\nFor containers: stdio, sse, or streamable-http\nFor remote servers: sse or streamable-http (stdio not supported)", "type": "string" } }, "type": "object" }, "registry.KubernetesMetadata": { "description": "Kubernetes contains Kubernetes-specific metadata when the MCP server is deployed in a cluster.\nThis field is optional and only populated when:\n- The server is served from ToolHive Registry Server\n- The server was auto-discovered from a Kubernetes deployment\n- The Kubernetes resource has the required registry annotations", "properties": { "image": { "description": "Image is the container image used by the Kubernetes workload (applicable to MCPServer)", "type": "string" }, "kind": { "description": "Kind is the Kubernetes resource kind (e.g., MCPServer, VirtualMCPServer, MCPRemoteProxy)", "type": "string" }, "name": { "description": "Name is the Kubernetes resource name", "type": "string" }, "namespace": { "description": "Namespace is the Kubernetes namespace where the resource is deployed", "type": "string" }, "transport": { "description": "Transport is the transport type configured for the Kubernetes workload (applicable to MCPServer)", "type": "string" }, "uid": { "description": "UID is the Kubernetes resource UID", "type": "string" } }, "type": "object" }, "registry.Metadata": { "description": "Metadata contains additional information about the server such as popularity metrics", "properties": { "kubernetes": { "$ref": "#/components/schemas/registry.KubernetesMetadata" }, "last_updated": { "description": "LastUpdated is the timestamp when the server was last updated, in RFC3339 format", "type": "string" }, "stars": { "description": "Stars represents the popularity rating or number of stars for the server", "type": "integer" } }, "type": "object" }, "registry.OAuthConfig": { "description": "OAuthConfig provides OAuth/OIDC configuration for authentication to the remote server\nUsed with the thv proxy command's --remote-auth flags", "properties": { "authorize_url": { "description": "AuthorizeURL is the OAuth authorization endpoint URL\nUsed for non-OIDC OAuth flows when issuer is not provided", "type": "string" }, "callback_port": { "description": "CallbackPort is the specific port to use for the OAuth callback server\nIf not specified, a random available port will be used", "type": "integer" }, "client_id": { "description": "ClientID is the OAuth client ID for authentication", "type": "string" }, "issuer": { "description": "Issuer is the OAuth/OIDC issuer URL (e.g., https://accounts.google.com)\nUsed for OIDC discovery to find authorization and token endpoints", "type": "string" }, "oauth_params": { "additionalProperties": { "type": "string" }, "description": "OAuthParams contains additional OAuth parameters to include in the authorization request\nThese are server-specific parameters like \"prompt\", \"response_mode\", etc.", "type": "object" }, "resource": { "description": "Resource is the OAuth 2.0 resource indicator (RFC 8707)", "type": "string" }, "scopes": { "description": "Scopes are the OAuth scopes to request\nIf not specified, defaults to [\"openid\", \"profile\", \"email\"] for OIDC", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "token_url": { "description": "TokenURL is the OAuth token endpoint URL\nUsed for non-OIDC OAuth flows when issuer is not provided", "type": "string" }, "use_pkce": { "description": "UsePKCE indicates whether to use PKCE for the OAuth flow\nDefaults to true for enhanced security", "type": "boolean" } }, "type": "object" }, "registry.Provenance": { "description": "Provenance contains verification and signing metadata", "properties": { "attestation": { "$ref": "#/components/schemas/registry.VerifiedAttestation" }, "cert_issuer": { "type": "string" }, "repository_ref": { "type": "string" }, "repository_uri": { "type": "string" }, "runner_environment": { "type": "string" }, "signer_identity": { "type": "string" }, "sigstore_url": { "type": "string" } }, "type": "object" }, "registry.Registry": { "description": "Full registry data", "properties": { "groups": { "description": "Groups is a slice of group definitions containing related MCP servers", "items": { "$ref": "#/components/schemas/registry.Group" }, "type": "array", "uniqueItems": false }, "last_updated": { "description": "LastUpdated is the timestamp when the registry was last updated, in RFC3339 format", "type": "string" }, "remote_servers": { "additionalProperties": { "$ref": "#/components/schemas/registry.RemoteServerMetadata" }, "description": "RemoteServers is a map of server names to their corresponding remote server definitions\nThese are MCP servers accessed via HTTP/HTTPS using the thv proxy command", "type": "object" }, "servers": { "additionalProperties": { "$ref": "#/components/schemas/registry.ImageMetadata" }, "description": "Servers is a map of server names to their corresponding server definitions", "type": "object" }, "version": { "description": "Version is the schema version of the registry", "type": "string" } }, "type": "object" }, "registry.RemoteServerMetadata": { "description": "Remote server details (if it's a remote server)", "properties": { "custom_metadata": { "additionalProperties": {}, "description": "CustomMetadata allows for additional user-defined metadata", "type": "object" }, "description": { "description": "Description is a human-readable description of the server's purpose and functionality", "type": "string" }, "env_vars": { "description": "EnvVars defines environment variables that can be passed to configure the client\nThese might be needed for client-side configuration when connecting to the remote server", "items": { "$ref": "#/components/schemas/registry.EnvVar" }, "type": "array", "uniqueItems": false }, "headers": { "description": "Headers defines HTTP headers that can be passed to the remote server for authentication\nThese are used with the thv proxy command's authentication features", "items": { "$ref": "#/components/schemas/registry.Header" }, "type": "array", "uniqueItems": false }, "metadata": { "$ref": "#/components/schemas/registry.Metadata" }, "name": { "description": "Name is the identifier for the MCP server, used when referencing the server in commands\nIf not provided, it will be auto-generated from the registry key", "type": "string" }, "oauth_config": { "$ref": "#/components/schemas/registry.OAuthConfig" }, "overview": { "description": "Overview is a longer Markdown-formatted description for web display.\nUnlike the Description field (limited to 500 chars), this supports\nfull Markdown and is intended for rich rendering on catalog pages.", "type": "string" }, "proxy_port": { "description": "ProxyPort is the port for the HTTP proxy to listen on (host port)\nIf not specified, a random available port will be assigned", "type": "integer" }, "repository_url": { "description": "RepositoryURL is the URL to the source code repository for the server", "type": "string" }, "stateless": { "description": "Stateless indicates the server only supports POST (no SSE/GET)", "type": "boolean" }, "status": { "description": "Status indicates whether the server is currently active or deprecated", "type": "string" }, "tags": { "description": "Tags are categorization labels for the server to aid in discovery and filtering", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "tier": { "description": "Tier represents the tier classification level of the server, e.g., \"Official\" or \"Community\"", "type": "string" }, "title": { "description": "Title is an optional human-readable display name for the server.\nIf not provided, the Name field is used for display purposes.", "type": "string" }, "tools": { "description": "Tools is a list of tool names provided by this MCP server", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "transport": { "description": "Transport defines the communication protocol for the server\nFor containers: stdio, sse, or streamable-http\nFor remote servers: sse or streamable-http (stdio not supported)", "type": "string" }, "url": { "description": "URL is the endpoint URL for the remote MCP server (e.g., https://api.example.com/mcp)", "type": "string" } }, "type": "object" }, "registry.Skill": { "properties": { "_meta": { "additionalProperties": {}, "description": "Meta is an opaque payload with extended meta data details of the skill.", "type": "object" }, "allowedTools": { "description": "AllowedTools is the list of tools that the skill is compatible with.\nThis is experimental.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "compatibility": { "description": "Compatibility is the environment requirements of the skill.", "type": "string" }, "description": { "description": "Description is the description of the skill.", "type": "string" }, "icons": { "description": "Icons is the list of icons for the skill.", "items": { "$ref": "#/components/schemas/registry.SkillIcon" }, "type": "array", "uniqueItems": false }, "license": { "description": "License is the SPDX license identifier of the skill.", "type": "string" }, "metadata": { "additionalProperties": {}, "description": "Metadata is the official metadata of the skill as reported in the\nSKILL.md file.", "type": "object" }, "name": { "description": "Name is the name of the skill.\nThe format is that of identifiers, e.g. \"my-skill\".", "type": "string" }, "namespace": { "description": "Namespace is the namespace of the skill.\nThe format is reverse-DNS, e.g. \"io.github.user\".", "type": "string" }, "packages": { "description": "Packages is the list of packages for the skill.", "items": { "$ref": "#/components/schemas/registry.SkillPackage" }, "type": "array", "uniqueItems": false }, "repository": { "$ref": "#/components/schemas/registry.SkillRepository" }, "status": { "description": "Status is the status of the skill.\nCan be one of \"active\", \"deprecated\", or \"archived\".", "type": "string" }, "title": { "description": "Title is the title of the skill.\nThis is for human consumption, not an identifier.", "type": "string" }, "version": { "description": "Version is the version of the skill.\nAny non-empty string is valid, but ideally it should be either a\nsemantic version or a commit hash.", "type": "string" } }, "type": "object" }, "registry.SkillIcon": { "properties": { "label": { "description": "Label is the label of the icon.", "type": "string" }, "size": { "description": "Size is the size of the icon.", "type": "string" }, "src": { "description": "Src is the source of the icon.", "type": "string" }, "type": { "description": "Type is the type of the icon.", "type": "string" } }, "type": "object" }, "registry.SkillPackage": { "properties": { "commit": { "description": "Commit is the commit of the package.", "type": "string" }, "digest": { "description": "Digest is the digest of the package.", "type": "string" }, "identifier": { "description": "Identifier is the OCI identifier of the package.", "type": "string" }, "mediaType": { "description": "MediaType is the media type of the package.", "type": "string" }, "ref": { "description": "Ref is the reference of the package.", "type": "string" }, "registryType": { "description": "RegistryType is the type of registry the package is from.\nCan be \"oci\" or \"git\".", "type": "string" }, "subfolder": { "description": "Subfolder is the subfolder of the package.", "type": "string" }, "url": { "description": "URL is the URL of the package.", "type": "string" } }, "type": "object" }, "registry.SkillRepository": { "description": "Repository is the source repository of the skill.", "properties": { "type": { "description": "Type is the type of the repository.", "type": "string" }, "url": { "description": "URL is the URL of the repository.", "type": "string" } }, "type": "object" }, "registry.VerifiedAttestation": { "properties": { "predicate": {}, "predicate_type": { "type": "string" } }, "type": "object" }, "remote.Config": { "description": "RemoteAuthConfig contains OAuth configuration for remote MCP servers", "properties": { "authorize_url": { "type": "string" }, "bearer_token": { "description": "Bearer token configuration (alternative to OAuth)", "type": "string" }, "bearer_token_file": { "type": "string" }, "cached_cimd_client_id": { "description": "CachedCIMDClientID stores the CIMD metadata URL used as client_id when CIMD\nauthentication was used. Kept separate from CachedClientID (which holds\nDCR-issued IDs) so the two can have independent lifecycles — DCR credential\nrotation clears CachedClientID without touching the stable CIMD URL.\nRead by resolveClientCredentials to send the correct client_id on token refresh.", "type": "string" }, "cached_client_id": { "description": "Cached DCR client credentials for persistence across restarts.\nThese are obtained during Dynamic Client Registration and needed to refresh tokens.\nClientID is stored as plain text since it's public information.", "type": "string" }, "cached_client_secret_ref": { "type": "string" }, "cached_dcr_callback_port": { "description": "CachedDCRCallbackPort is the callback port that was actually registered\nduring DCR. It may differ from CallbackPort when the requested port was\nunavailable and a fallback port was selected.", "type": "integer" }, "cached_refresh_token_ref": { "description": "Cached OAuth token reference for persistence across restarts.\nThe refresh token is stored securely in the secret manager, and this field\ncontains the reference to retrieve it (e.g., \"OAUTH_REFRESH_TOKEN_workload\").\nThis enables session restoration without requiring a new browser-based login.", "type": "string" }, "cached_reg_client_uri": { "description": "CachedRegClientURI is the registration_client_uri from the DCR response.\nThis is the endpoint used for RFC 7592 client read/update/delete operations.\nStored as plain text since it is not sensitive.", "type": "string" }, "cached_reg_token_ref": { "description": "CachedRegTokenRef is a secret manager reference to the registration_access_token\nreturned in the DCR response. Used for RFC 7592 client update operations.\nStored as a secret reference since it's sensitive.", "type": "string" }, "cached_secret_expiry": { "description": "ClientSecretExpiresAt indicates when the client secret expires (if provided by the DCR server).\nA zero value means the secret does not expire.", "type": "string" }, "cached_token_auth_method": { "description": "CachedTokenEndpointAuthMethod is the auth method used for the token endpoint\n(e.g., \"client_secret_basic\", \"none\"). Persisted for RFC 7592 updates.", "type": "string" }, "cached_token_expiry": { "type": "string" }, "callback_port": { "type": "integer" }, "client_id": { "type": "string" }, "client_secret": { "type": "string" }, "client_secret_file": { "type": "string" }, "issuer": { "description": "OAuth endpoint configuration (from registry)", "type": "string" }, "oauth_params": { "additionalProperties": { "type": "string" }, "description": "OAuth parameters for server-specific customization", "type": "object" }, "resource": { "description": "Resource is the OAuth 2.0 resource indicator (RFC 8707).", "type": "string" }, "scope_param_name": { "description": "ScopeParamName overrides the query parameter name used to send scopes in the\nauthorization URL. When empty, the standard \"scope\" parameter is used.\nSome providers require a non-standard name (e.g., Slack uses \"user_scope\").", "type": "string" }, "scopes": { "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "skip_browser": { "type": "boolean" }, "timeout": { "example": "5m", "type": "string" }, "token_url": { "type": "string" }, "use_pkce": { "type": "boolean" } }, "type": "object" }, "secrets.SecretParameter": { "description": "Bearer token for authentication (alternative to OAuth)", "properties": { "name": { "type": "string" }, "target": { "type": "string" } }, "type": "object" }, "storage.ACLUserRunConfig": { "description": "ACLUserConfig contains ACL user authentication configuration.", "properties": { "password_env_var": { "description": "PasswordEnvVar is the environment variable containing the Redis password.", "type": "string" }, "username_env_var": { "description": "UsernameEnvVar is the environment variable containing the Redis username.", "type": "string" } }, "type": "object" }, "storage.RedisRunConfig": { "description": "RedisConfig is the Redis-specific configuration when Type is \"redis\".", "properties": { "acl_user_config": { "$ref": "#/components/schemas/storage.ACLUserRunConfig" }, "addr": { "description": "Addr is the Redis server address (host:port). Required for standalone and cluster modes.\nMutually exclusive with SentinelConfig.", "type": "string" }, "auth_type": { "description": "AuthType must be \"aclUser\" - only ACL user authentication is supported.", "type": "string" }, "cluster_mode": { "description": "ClusterMode enables the Redis Cluster protocol. Requires Addr to be set.", "type": "boolean" }, "dial_timeout": { "description": "DialTimeout is the timeout for establishing connections (e.g., \"5s\").", "type": "string" }, "key_prefix": { "description": "KeyPrefix for multi-tenancy, typically \"thv:auth:{ns}:{name}:\".", "type": "string" }, "read_timeout": { "description": "ReadTimeout is the timeout for read operations (e.g., \"3s\").", "type": "string" }, "sentinel_config": { "$ref": "#/components/schemas/storage.SentinelRunConfig" }, "sentinel_tls": { "$ref": "#/components/schemas/storage.RedisTLSRunConfig" }, "tls": { "$ref": "#/components/schemas/storage.RedisTLSRunConfig" }, "write_timeout": { "description": "WriteTimeout is the timeout for write operations (e.g., \"3s\").", "type": "string" } }, "type": "object" }, "storage.RedisTLSRunConfig": { "description": "SentinelTLS configures TLS for Sentinel connections. Only applies when SentinelConfig is set.", "properties": { "ca_cert_file": { "description": "CACertFile is the path to a PEM-encoded CA certificate file.", "type": "string" }, "insecure_skip_verify": { "description": "InsecureSkipVerify skips certificate verification.", "type": "boolean" } }, "type": "object" }, "storage.RunConfig": { "description": "Storage configures the storage backend for the auth server.\nIf nil, defaults to in-memory storage.", "properties": { "redis_config": { "$ref": "#/components/schemas/storage.RedisRunConfig" }, "type": { "description": "Type specifies the storage backend type. Defaults to \"memory\".", "type": "string" } }, "type": "object" }, "storage.SentinelRunConfig": { "description": "SentinelConfig contains Sentinel-specific configuration.\nMutually exclusive with Addr.", "properties": { "db": { "description": "DB is the Redis database number (default: 0).", "type": "integer" }, "master_name": { "description": "MasterName is the name of the Redis Sentinel master.", "type": "string" }, "sentinel_addrs": { "description": "SentinelAddrs is the list of Sentinel addresses (host:port).", "items": { "type": "string" }, "type": "array", "uniqueItems": false } }, "type": "object" }, "telemetry.Config": { "description": "DEPRECATED: Middleware configuration.\nTelemetryConfig contains the OpenTelemetry configuration", "properties": { "caCertPath": { "description": "CACertPath is the file path to a CA certificate bundle for the OTLP endpoint.\nWhen set, the OTLP exporters use this CA to verify the collector's TLS certificate\ninstead of relying solely on the system CA pool.\n+optional", "type": "string" }, "customAttributes": { "additionalProperties": { "type": "string" }, "description": "CustomAttributes contains custom resource attributes to be added to all telemetry signals.\nThese are parsed from CLI flags (--otel-custom-attributes) or environment variables\n(OTEL_RESOURCE_ATTRIBUTES) as key=value pairs.\n+optional", "type": "object" }, "enablePrometheusMetricsPath": { "description": "EnablePrometheusMetricsPath controls whether to expose Prometheus-style /metrics endpoint.\nThe metrics are served on the main transport port at /metrics.\nThis is separate from OTLP metrics which are sent to the Endpoint.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "endpoint": { "description": "Endpoint is the OTLP endpoint URL\n+optional", "type": "string" }, "environmentVariables": { "description": "EnvironmentVariables is a list of environment variable names that should be\nincluded in telemetry spans as attributes. Only variables in this list will\nbe read from the host machine and included in spans for observability.\nExample: [\"NODE_ENV\", \"DEPLOYMENT_ENV\", \"SERVICE_VERSION\"]\n+optional", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "headers": { "additionalProperties": { "type": "string" }, "description": "Headers contains authentication headers for the OTLP endpoint.\n+optional", "type": "object" }, "insecure": { "description": "Insecure indicates whether to use HTTP instead of HTTPS for the OTLP endpoint.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "metricsEnabled": { "description": "MetricsEnabled controls whether OTLP metrics are enabled.\nWhen false, OTLP metrics are not sent even if an endpoint is configured.\nThis is independent of EnablePrometheusMetricsPath.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "samplingRate": { "description": "SamplingRate is the trace sampling rate (0.0-1.0) as a string.\nOnly used when TracingEnabled is true.\nExample: \"0.05\" for 5% sampling.\n+kubebuilder:default=\"0.05\"\n+optional", "type": "string" }, "serviceName": { "description": "ServiceName is the service name for telemetry.\nWhen omitted, defaults to the server name (e.g., VirtualMCPServer name).\n+optional", "type": "string" }, "serviceVersion": { "description": "ServiceVersion is the service version for telemetry.\nWhen omitted, defaults to the ToolHive version.\n+optional", "type": "string" }, "tracingEnabled": { "description": "TracingEnabled controls whether distributed tracing is enabled.\nWhen false, no tracer provider is created even if an endpoint is configured.\n+kubebuilder:default=false\n+optional", "type": "boolean" }, "useLegacyAttributes": { "description": "UseLegacyAttributes controls whether legacy (pre-MCP OTEL semconv) attribute names\nare emitted alongside the new standard attribute names. When true, spans include both\nold and new attribute names for backward compatibility with existing dashboards.\nCurrently defaults to true; this will change to false in a future release.\n+kubebuilder:default=true\n+optional", "type": "boolean" } }, "type": "object" }, "templates.RuntimeConfig": { "description": "RuntimeConfig allows overriding the default runtime configuration\nfor this specific workload (base images and packages)", "properties": { "additional_packages": { "description": "AdditionalPackages lists extra packages to install in the builder and\nruntime stages.\nExamples for Alpine: [\"git\", \"make\", \"gcc\"]\nExamples for Debian: [\"git\", \"build-essential\"]", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "build_with": { "description": "BuildWith lists build-time dependency constraints, interpreted per\npackage ecosystem. For uvx:// builds these are PEP 508 requirement\nspecifiers passed to `uv tool install --with`, used to constrain\ntransitive dependencies the package itself leaves unbounded\n(e.g. \"mcp\u003c2\"). Ecosystems without constraint support (npx://, go://)\nreject a non-empty BuildWith at build time.", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "builder_image": { "description": "BuilderImage is the full image reference for the builder stage.\nAn empty string signals \"use the default for this transport type\" during config merging.\nExamples: \"golang:1.26-alpine\", \"node:24-alpine\", \"python:3.14-slim\"", "type": "string" }, "runtime_env": { "additionalProperties": { "type": "string" }, "description": "RuntimeEnv contains environment variables to inject into the Dockerfile's\nfinal runtime stage. Unlike BuildEnv (pkg/container/templates.TemplateData.BuildEnv),\nwhich only affects the builder stage, these variables are baked into the\nshipped image and are present in the running container's process\nenvironment at startup. Use this for values a packaged MCP server reads at\nprocess start (e.g. feature flags, cache backend selection), not for\nbuild-time package manager configuration.\nKeys must be uppercase with underscores, values are validated for safety.", "type": "object" } }, "type": "object" }, "tokenexchange.Config": { "description": "TokenExchangeConfig contains token exchange configuration for external authentication", "properties": { "audience": { "description": "Audience is the target audience for the exchanged token", "type": "string" }, "client_id": { "description": "ClientID is the OAuth 2.0 client identifier", "type": "string" }, "client_secret": { "description": "ClientSecret is the OAuth 2.0 client secret", "type": "string" }, "external_token_header_name": { "description": "ExternalTokenHeaderName is the name of the custom header to use when HeaderStrategy is \"custom\"", "type": "string" }, "header_strategy": { "description": "HeaderStrategy determines how to inject the token\nValid values: HeaderStrategyReplace (default), HeaderStrategyCustom", "type": "string" }, "scopes": { "description": "Scopes is the list of scopes to request for the exchanged token", "items": { "type": "string" }, "type": "array", "uniqueItems": false }, "subject_token_type": { "description": "SubjectTokenType specifies the type of the subject token being exchanged.\nCommon values: oauthproto.TokenTypeAccessToken (default), oauthproto.TokenTypeIDToken, oauthproto.TokenTypeJWT.\nIf empty, defaults to oauthproto.TokenTypeAccessToken.", "type": "string" }, "token_url": { "description": "TokenURL is the OAuth 2.0 token endpoint URL", "type": "string" } }, "type": "object" }, "types.MiddlewareConfig": { "properties": { "parameters": { "description": "Parameters is a JSON object containing the middleware parameters.\nIt is stored as a raw message to allow flexible parameter types.", "type": "object" }, "type": { "description": "Type is a string representing the middleware type.", "type": "string" } }, "type": "object" }, "v0.ServerJSON": { "properties": { "$schema": { "example": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "format": "uri", "minLength": 1, "type": "string" }, "_meta": { "$ref": "#/components/schemas/v0.ServerMeta" }, "description": { "example": "MCP server providing weather data and forecasts via OpenWeatherMap API", "maxLength": 100, "minLength": 1, "type": "string" }, "icons": { "items": { "$ref": "#/components/schemas/model.Icon" }, "type": "array", "uniqueItems": false }, "name": { "example": "io.github.user/weather", "maxLength": 200, "minLength": 3, "pattern": "^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$", "type": "string" }, "packages": { "items": { "$ref": "#/components/schemas/model.Package" }, "type": "array", "uniqueItems": false }, "remotes": { "items": { "$ref": "#/components/schemas/model.Transport" }, "type": "array", "uniqueItems": false }, "repository": { "$ref": "#/components/schemas/model.Repository" }, "title": { "example": "Weather API", "maxLength": 100, "minLength": 1, "type": "string" }, "version": { "example": "1.0.2", "maxLength": 255, "minLength": 1, "type": "string" }, "websiteUrl": { "example": "https://modelcontextprotocol.io/examples", "format": "uri", "type": "string" } }, "type": "object" }, "v0.ServerMeta": { "properties": { "io.modelcontextprotocol.registry/publisher-provided": { "additionalProperties": {}, "type": "object" } }, "type": "object" }, "v1.Duration": { "description": "RefillPeriod is the duration to fully refill the bucket from zero to maxTokens.\nThe effective refill rate is maxTokens / refillPeriod tokens per second.\nFormat: Go duration string (e.g., \"1m0s\", \"30s\", \"1h0m0s\").\n+kubebuilder:validation:Required", "type": "object" } } }, "info": { "description": "This is the ToolHive API server.", "title": "ToolHive API", "version": "1.0" }, "externalDocs": { "description": "", "url": "" }, "paths": { "/api/openapi.json": { "get": { "description": "Returns the OpenAPI specification for the API", "responses": { "200": { "content": { "application/json": { "schema": { "type": "object" } } }, "description": "OpenAPI specification" } }, "summary": "Get OpenAPI specification", "tags": ["system"] } }, "/api/v1beta/clients": { "get": { "description": "List all registered clients in ToolHive", "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_client.RegisteredClient" }, "type": "array" } } }, "description": "OK" } }, "summary": "List all clients", "tags": ["clients"] }, "post": { "description": "Register a new client with ToolHive", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.createClientRequest", "summary": "client", "description": "Client to register" } ] } } }, "description": "Client to register", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.createClientResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Invalid request or unsupported client type" } }, "summary": "Register a new client", "tags": ["clients"] } }, "/api/v1beta/clients/register": { "post": { "description": "Register multiple clients with ToolHive", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.bulkClientRequest", "summary": "clients", "description": "Clients to register" } ] } } }, "description": "Clients to register", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/pkg_api_v1.createClientResponse" }, "type": "array" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Invalid request or unsupported client type" } }, "summary": "Register multiple clients", "tags": ["clients"] } }, "/api/v1beta/clients/unregister": { "post": { "description": "Unregister multiple clients from ToolHive", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.bulkClientRequest", "summary": "clients", "description": "Clients to unregister" } ] } } }, "description": "Clients to unregister", "required": true }, "responses": { "204": { "description": "No Content" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Invalid request or unsupported client type" } }, "summary": "Unregister multiple clients", "tags": ["clients"] } }, "/api/v1beta/clients/{name}": { "delete": { "description": "Unregister a client from ToolHive", "parameters": [ { "description": "Client name to unregister", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "No Content" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Invalid request or unsupported client type" } }, "summary": "Unregister a client", "tags": ["clients"] } }, "/api/v1beta/clients/{name}/groups/{group}": { "delete": { "description": "Unregister a client from a specific group in ToolHive", "parameters": [ { "description": "Client name to unregister", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } }, { "description": "Group name to remove client from", "in": "path", "name": "group", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "No Content" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Invalid request or unsupported client type" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Client or group not found" } }, "summary": "Unregister a client from a specific group", "tags": ["clients"] } }, "/api/v1beta/discovery/clients": { "get": { "description": "List all clients compatible with ToolHive and their status.\nEach object includes supports_skills when ToolHive can install skills for that client.", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.clientStatusResponse" } } }, "description": "OK" } }, "summary": "List all clients status", "tags": ["discovery"] } }, "/api/v1beta/groups": { "get": { "description": "Get a list of all groups", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.groupListResponse" } } }, "description": "OK" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "List all groups", "tags": ["groups"] }, "post": { "description": "Create a new group with the specified name", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.createGroupRequest", "summary": "group", "description": "Group creation request" } ] } } }, "description": "Group creation request", "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.createGroupResponse" } } }, "description": "Created" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "409": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Conflict" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Create a new group", "tags": ["groups"] } }, "/api/v1beta/groups/{name}": { "delete": { "description": "Delete a group by name.", "parameters": [ { "description": "Group name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } }, { "description": "Delete all workloads in the group (default: false, moves workloads to default group)", "in": "query", "name": "with-workloads", "schema": { "type": "boolean" } } ], "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Delete a group", "tags": ["groups"] }, "get": { "description": "Get details of a specific group", "parameters": [ { "description": "Group name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_groups.Group" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Get group details", "tags": ["groups"] } }, "/api/v1beta/registry": { "get": { "description": "Get a list of the current registries", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryListResponse" } } }, "description": "OK" } }, "summary": "List registries", "tags": ["registry"] }, "post": { "description": "Add a new registry", "requestBody": { "content": { "application/json": { "schema": { "type": "object" } } } }, "responses": { "501": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Implemented" } }, "summary": "Add a registry", "tags": ["registry"] } }, "/api/v1beta/registry/auth/login": { "post": { "description": "Trigger an interactive OAuth flow to authenticate with the configured registry. Only available in serve mode.", "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object" } } }, "description": "Authenticated successfully" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request - Registry OAuth not configured" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Registry login", "tags": ["registry"] } }, "/api/v1beta/registry/auth/logout": { "post": { "description": "Clear cached OAuth tokens for the configured registry. Only available in serve mode.", "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object" } } }, "description": "Logged out successfully" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request - Registry OAuth not configured" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Registry logout", "tags": ["registry"] } }, "/api/v1beta/registry/{name}": { "delete": { "description": "Remove a specific registry", "parameters": [ { "description": "Registry name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" }, "403": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Forbidden - blocked by policy" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Remove a registry", "tags": ["registry"] }, "get": { "description": "Get details of a specific registry", "parameters": [ { "description": "Registry name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.getRegistryResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Get a registry", "tags": ["registry"] }, "put": { "description": "Update registry URL or local path for the default registry", "parameters": [ { "description": "Registry name (must be 'default')", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.UpdateRegistryRequest", "summary": "body", "description": "Registry configuration" } ] } } }, "description": "Registry configuration", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.UpdateRegistryResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "403": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Forbidden - blocked by policy" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "502": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Gateway - Registry validation failed" }, "504": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Gateway Timeout - Registry unreachable" } }, "summary": "Update registry configuration", "tags": ["registry"] } }, "/api/v1beta/registry/{name}/refresh": { "post": { "description": "Force a refresh of the server-side registry cache for the default registry", "parameters": [ { "description": "Registry name (must be 'default')", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object" } } }, "description": "Registry refreshed" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" }, "503": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Registry authentication required or upstream registry unavailable" } }, "summary": "Refresh registry cache", "tags": ["registry"] } }, "/api/v1beta/registry/{name}/servers": { "get": { "description": "Get a list of servers in a specific registry", "parameters": [ { "description": "Registry name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.listServersResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "List servers in a registry", "tags": ["registry"] } }, "/api/v1beta/registry/{name}/servers/{serverName}": { "get": { "description": "Get details of a specific server in a registry", "parameters": [ { "description": "Registry name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } }, { "description": "ImageMetadata name", "in": "path", "name": "serverName", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.getServerResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Get a server from a registry", "tags": ["registry"] } }, "/api/v1beta/secrets": { "post": { "description": "Setup the secrets provider with the specified type and configuration.", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.setupSecretsRequest", "summary": "request", "description": "Setup secrets provider request" } ] } } }, "description": "Setup secrets provider request", "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.setupSecretsResponse" } } }, "description": "Created" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Setup or reconfigure secrets provider", "tags": ["secrets"] } }, "/api/v1beta/secrets/default": { "get": { "description": "Get details of the default secrets provider", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.getSecretsProviderResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found - Provider not setup" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Get secrets provider details", "tags": ["secrets"] } }, "/api/v1beta/secrets/default/keys": { "get": { "description": "Get a list of all secret keys from the default provider", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.listSecretsResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found - Provider not setup" }, "405": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Method Not Allowed - Provider doesn't support listing" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "List secrets", "tags": ["secrets"] }, "post": { "description": "Create a new secret in the default provider (encrypted provider only)", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.createSecretRequest", "summary": "request", "description": "Create secret request" } ] } } }, "description": "Create secret request", "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.createSecretResponse" } } }, "description": "Created" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found - Provider not setup" }, "405": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Method Not Allowed - Provider doesn't support writing" }, "409": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Conflict - Secret already exists" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Create a new secret", "tags": ["secrets"] } }, "/api/v1beta/secrets/default/keys/{key}": { "delete": { "description": "Delete a secret from the default provider (encrypted provider only)", "parameters": [ { "description": "Secret key", "in": "path", "name": "key", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found - Provider not setup or secret not found" }, "405": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Method Not Allowed - Provider doesn't support deletion" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Delete a secret", "tags": ["secrets"] }, "put": { "description": "Update an existing secret in the default provider (encrypted provider only)", "parameters": [ { "description": "Secret key", "in": "path", "name": "key", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.updateSecretRequest", "summary": "request", "description": "Update secret request" } ] } } }, "description": "Update secret request", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.updateSecretResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found - Provider not setup or secret not found" }, "405": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Method Not Allowed - Provider doesn't support writing" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Update a secret", "tags": ["secrets"] } }, "/api/v1beta/skills": { "get": { "description": "Get a list of all installed skills", "parameters": [ { "description": "Filter by scope (user or project)", "in": "query", "name": "scope", "schema": { "enum": ["user", "project"], "type": "string" } }, { "description": "Filter by client app", "in": "query", "name": "client", "schema": { "type": "string" } }, { "description": "Filter by project root path", "in": "query", "name": "project_root", "schema": { "type": "string" } }, { "description": "Filter by group name", "in": "query", "name": "group", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.skillListResponse" } } }, "description": "OK" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "List all installed skills", "tags": ["skills"] }, "post": { "description": "Install a skill from a remote source", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.installSkillRequest", "summary": "request", "description": "Install request" } ] } } }, "description": "Install request", "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.installSkillResponse" } } }, "description": "Created", "headers": { "Location": { "description": "URI of the installed skill resource", "schema": { "type": "string" } } } }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "401": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Unauthorized (registry refused credentials)" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found (artifact not present in registry)" }, "409": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Conflict" }, "429": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Too Many Requests (registry rate limit)" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" }, "502": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Gateway (upstream registry failure)" }, "504": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Gateway Timeout (upstream pull timed out)" } }, "summary": "Install a skill", "tags": ["skills"] } }, "/api/v1beta/skills/build": { "post": { "description": "Build a skill from a local directory", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.buildSkillRequest", "summary": "request", "description": "Build request" } ] } } }, "description": "Build request", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.BuildResult" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Build a skill", "tags": ["skills"] } }, "/api/v1beta/skills/builds": { "get": { "description": "Get a list of all locally-built OCI skill artifacts in the local store", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.buildListResponse" } } }, "description": "OK" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "List locally-built skill artifacts", "tags": ["skills"] } }, "/api/v1beta/skills/builds/{tag}": { "delete": { "description": "Remove a locally-built OCI skill artifact and its blobs from the local store", "parameters": [ { "description": "Artifact tag", "in": "path", "name": "tag", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Delete a locally-built skill artifact", "tags": ["skills"] } }, "/api/v1beta/skills/content": { "get": { "description": "Retrieve the SKILL.md body and file listing from an artifact\nwithout installing it. Accepts OCI refs, git refs, or local tags.", "parameters": [ { "description": "OCI reference or local build tag", "in": "query", "name": "ref", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SkillContent" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "401": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Unauthorized (registry refused credentials)" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found (artifact not present in registry)" }, "429": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Too Many Requests (registry rate limit)" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" }, "502": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Gateway (upstream registry or git resolver failure)" }, "504": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Gateway Timeout (upstream pull timed out)" } }, "summary": "Get skill content", "tags": ["skills"] } }, "/api/v1beta/skills/push": { "post": { "description": "Push a built skill artifact to a remote registry", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.pushSkillRequest", "summary": "request", "description": "Push request" } ] } } }, "description": "Push request", "required": true }, "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Push a skill", "tags": ["skills"] } }, "/api/v1beta/skills/sync": { "post": { "description": "Restore a project's installed skills to match toolhive.lock.yaml", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.syncSkillsRequest", "summary": "request", "description": "Sync request" } ] } } }, "description": "Sync request", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SyncResult" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "403": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Forbidden (feature not enabled)" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" }, "501": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Implemented" } }, "summary": "Sync project skills from the lock file", "tags": ["skills"] } }, "/api/v1beta/skills/upgrade": { "post": { "description": "Re-resolve a project's lock entries and install newer content where available", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.upgradeSkillsRequest", "summary": "request", "description": "Upgrade request" } ] } } }, "description": "Upgrade request", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.UpgradeResult" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "403": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Forbidden (feature not enabled)" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found (a requested name is not in the lock file)" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" }, "501": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Implemented" } }, "summary": "Upgrade project skills", "tags": ["skills"] } }, "/api/v1beta/skills/validate": { "post": { "description": "Validate a skill definition", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.validateSkillRequest", "summary": "request", "description": "Validate request" } ] } } }, "description": "Validate request", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.ValidationResult" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Validate a skill", "tags": ["skills"] } }, "/api/v1beta/skills/{name}": { "delete": { "description": "Remove an installed skill", "parameters": [ { "description": "Skill name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } }, { "description": "Scope to uninstall from (user or project)", "in": "query", "name": "scope", "schema": { "enum": ["user", "project"], "type": "string" } }, { "description": "Project root path for project-scoped skills", "in": "query", "name": "project_root", "schema": { "type": "string" } } ], "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Uninstall a skill", "tags": ["skills"] }, "get": { "description": "Get detailed information about a specific skill", "parameters": [ { "description": "Skill name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } }, { "description": "Filter by scope (user or project)", "in": "query", "name": "scope", "schema": { "enum": ["user", "project"], "type": "string" } }, { "description": "Project root path for project-scoped skills", "in": "query", "name": "project_root", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_skills.SkillInfo" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Get skill details", "tags": ["skills"] } }, "/api/v1beta/version": { "get": { "description": "Returns the current version of the server", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.versionResponse" } } }, "description": "OK" } }, "summary": "Get server version", "tags": ["version"] } }, "/api/v1beta/workloads": { "get": { "description": "Get a list of all running workloads, optionally filtered by group", "parameters": [ { "description": "List all workloads, including stopped ones", "in": "query", "name": "all", "schema": { "type": "boolean" } }, { "description": "Filter workloads by group name", "in": "query", "name": "group", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.workloadListResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Group not found" } }, "summary": "List all workloads", "tags": ["workloads"] }, "post": { "description": "Create and start a new workload", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.createRequest", "summary": "request", "description": "Create workload request" } ] } } }, "description": "Create workload request", "required": true }, "responses": { "201": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.createWorkloadResponse" } } }, "description": "Created" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "409": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Conflict" } }, "summary": "Create a new workload", "tags": ["workloads"] } }, "/api/v1beta/workloads/delete": { "post": { "description": "Delete multiple workloads by name or by group asynchronously.\nReturns 202 Accepted immediately. Deletion happens in the background.", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.bulkOperationRequest", "summary": "request", "description": "Bulk delete request (names or group)" } ] } } }, "description": "Bulk delete request (names or group)", "required": true }, "responses": { "202": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Accepted - deletion started" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" } }, "summary": "Delete workloads in bulk", "tags": ["workloads"] } }, "/api/v1beta/workloads/restart": { "post": { "description": "Restart multiple workloads by name or by group", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.bulkOperationRequest", "summary": "request", "description": "Bulk restart request (names or group)" } ] } } }, "description": "Bulk restart request (names or group)", "required": true }, "responses": { "202": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Accepted" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" } }, "summary": "Restart workloads in bulk", "tags": ["workloads"] } }, "/api/v1beta/workloads/stop": { "post": { "description": "Stop multiple workloads by name or by group", "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.bulkOperationRequest", "summary": "request", "description": "Bulk stop request (names or group)" } ] } } }, "description": "Bulk stop request (names or group)", "required": true }, "responses": { "202": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Accepted" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" } }, "summary": "Stop workloads in bulk", "tags": ["workloads"] } }, "/api/v1beta/workloads/upgrade-check": { "get": { "description": "Check all workloads (optionally filtered by group) for newer\nimages available in their source registries. This is an offline\nmetadata comparison; it does not pull images. Secret values are\nnever returned.", "parameters": [ { "description": "Include stopped workloads", "in": "query", "name": "all", "schema": { "type": "boolean" } }, { "description": "Filter workloads by group name", "in": "query", "name": "group", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.upgradeCheckBulkResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Group not found" } }, "summary": "Check workloads for available upgrades", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}": { "delete": { "description": "Delete a workload asynchronously. Returns 202 Accepted immediately.\nThe deletion happens in the background. Poll the workload list to confirm deletion.", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "202": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Accepted - deletion started" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Delete a workload", "tags": ["workloads"] }, "get": { "description": "Get details of a specific workload", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.createRequest" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Get workload details", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/edit": { "post": { "description": "Update an existing workload configuration", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.updateRequest", "summary": "request", "description": "Update workload request" } ] } } }, "description": "Update workload request", "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.createWorkloadResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Update workload", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/export": { "get": { "description": "Export a workload's run configuration as JSON", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/github_com_stacklok_toolhive_pkg_runner.RunConfig" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Export workload configuration", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/logs": { "get": { "description": "Retrieve at most 1000 lines of logs for a specific workload by name.", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "text/plain": { "schema": { "type": "string" } } }, "description": "Logs for the specified workload" }, "400": { "content": { "text/plain": { "schema": { "type": "string" } } }, "description": "Invalid workload name" }, "404": { "content": { "text/plain": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Get logs for a specific workload", "tags": ["logs"] } }, "/api/v1beta/workloads/{name}/proxy-logs": { "get": { "description": "Retrieve at most 1000 lines of proxy logs for a specific workload by name from the file system.", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "text/plain": { "schema": { "type": "string" } } }, "description": "Proxy logs for the specified workload" }, "400": { "content": { "text/plain": { "schema": { "type": "string" } } }, "description": "Invalid workload name" }, "404": { "content": { "text/plain": { "schema": { "type": "string" } } }, "description": "Proxy logs not found for workload" } }, "summary": "Get proxy logs for a specific workload", "tags": ["logs"] } }, "/api/v1beta/workloads/{name}/restart": { "post": { "description": "Restart a running workload", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "202": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Accepted" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Restart a workload", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/status": { "get": { "description": "Get the current status of a specific workload", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.workloadStatusResponse" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Get workload status", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/stop": { "post": { "description": "Stop a running workload", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "202": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Accepted" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Stop a workload", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/upgrade": { "post": { "description": "Apply a registry-sourced upgrade to a single workload. This\nre-resolves and verifies the candidate image, pulls it, and only\nthen recreates the workload with the new image, preserving the\nexisting configuration. If the workload is already up to date or\nis not registry-sourced, the current check result is returned\nunchanged (no-op). Secret values are never accepted or returned.", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "oneOf": [ { "type": "object" }, { "$ref": "#/components/schemas/pkg_api_v1.upgradeRequest", "summary": "request", "description": "Upgrade options" } ] } } }, "description": "Upgrade options" }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.upgradeCheckResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" }, "422": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Unprocessable Entity" }, "500": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Internal Server Error" } }, "summary": "Apply an available upgrade to a workload", "tags": ["workloads"] } }, "/api/v1beta/workloads/{name}/upgrade-check": { "get": { "description": "Check whether a single workload has a newer image available in\nits source registry. This is an offline metadata comparison; it\ndoes not pull images. Secret values are never returned.", "parameters": [ { "description": "Workload name", "in": "path", "name": "name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.upgradeCheckResponse" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Bad Request" }, "404": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "Not Found" } }, "summary": "Check a workload for an available upgrade", "tags": ["workloads"] } }, "/health": { "get": { "description": "Check if the API is healthy", "responses": { "204": { "content": { "application/json": { "schema": { "type": "string" } } }, "description": "No Content" } }, "summary": "Health check", "tags": ["system"] } }, "/registry/{registryName}/v0.1/servers": { "get": { "description": "Get a paginated list of servers from the registry. Supports optional full-text search and pagination.", "parameters": [ { "description": "Registry name (currently ignored, uses the default provider)", "in": "path", "name": "registryName", "required": true, "schema": { "type": "string" } }, { "description": "Search filter — matches against server name and description", "in": "query", "name": "q", "schema": { "type": "string" } }, { "description": "Page number, 1-based (default: 1)", "in": "query", "name": "page", "schema": { "type": "integer" } }, { "description": "Items per page, max 200 (default: 50)", "in": "query", "name": "limit", "schema": { "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.serversV01Response" } } }, "description": "OK" }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Internal server error" }, "503": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Registry authentication required or upstream registry unavailable" } }, "summary": "List available registry servers", "tags": ["registry-servers"] } }, "/registry/{registryName}/v0.1/servers/{serverName}/versions/latest": { "get": { "description": "Retrieve a single server by name. Names use reverse-DNS format; URL-encode slashes.", "parameters": [ { "description": "Registry name (currently ignored, uses the default provider)", "in": "path", "name": "registryName", "required": true, "schema": { "type": "string" } }, { "description": "Server name (URL-encoded reverse-DNS format)", "in": "path", "name": "serverName", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/v0.ServerJSON" } } }, "description": "OK" }, "400": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Invalid server name encoding" }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Server not found" }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Internal server error" }, "503": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Registry authentication required or upstream registry unavailable" } }, "summary": "Get a registry server", "tags": ["registry-servers"] } }, "/registry/{registryName}/v0.1/x/dev.toolhive/skills": { "get": { "description": "Get a paginated list of skills from the registry. Supports optional full-text search and pagination.", "parameters": [ { "description": "Registry name (currently ignored, uses the default provider)", "in": "path", "name": "registryName", "required": true, "schema": { "type": "string" } }, { "description": "Search filter — matches against skill name, namespace, and description", "in": "query", "name": "q", "schema": { "type": "string" } }, { "description": "Page number, 1-based (default: 1)", "in": "query", "name": "page", "schema": { "type": "integer" } }, { "description": "Items per page, max 200 (default: 50)", "in": "query", "name": "limit", "schema": { "type": "integer" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.skillsV01Response" } } }, "description": "OK" }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Internal server error" }, "503": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Registry authentication required or upstream registry unavailable" } }, "summary": "List available registry skills", "tags": ["registry-skills"] } }, "/registry/{registryName}/v0.1/x/dev.toolhive/skills/{namespace}/{skillName}": { "get": { "description": "Retrieve a single skill by its namespace and name from the registry.", "parameters": [ { "description": "Registry name (currently ignored, uses the default provider)", "in": "path", "name": "registryName", "required": true, "schema": { "type": "string" } }, { "description": "Skill namespace in reverse-DNS format (e.g. io.github.stacklok)", "in": "path", "name": "namespace", "required": true, "schema": { "type": "string" } }, { "description": "Skill name", "in": "path", "name": "skillName", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/registry.Skill" } } }, "description": "OK" }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Skill not found" }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Internal server error" }, "503": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/pkg_api_v1.registryErrorResponse" } } }, "description": "Registry authentication required or upstream registry unavailable" } }, "summary": "Get a registry skill", "tags": ["registry-skills"] } } }, "openapi": "3.1.0" }