VirtualMCPServer (toolhive.stacklok.dev/v1alpha1)

Type: object

VirtualMCPServer is the deprecated v1alpha1 version of the VirtualMCPServer resource.

Type: string

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

Type: string

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta

Type: object

Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

Type: object

Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations

Each additional property must conform to the following schema

Type: string

io.k8s.apimachinery.pkg.apis.meta.v1.Time

Type: string

CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.

Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

Type: integerFormat: int64

Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.

io.k8s.apimachinery.pkg.apis.meta.v1.Time

Type: string

DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.

Populated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

Same definition as creationTimestamp

Type: array of string

Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. Finalizers may be processed and removed in any order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processed in order, then this can lead to a situation in which the component responsible for the first finalizer in the list is waiting for a signal (field value, external system, or other) produced by a component responsible for a finalizer later in the list, resulting in a deadlock. Without enforced ordering finalizers are free to order amongst themselves and are not vulnerable to ordering changes in the list.

No Additional Items

Each item of this array must be:

Type: string

GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.

If this field is specified and the generated name exists, the server will return a 409.

Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency

Type: integerFormat: int64

A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.

Type: object

Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels

Each additional property must conform to the following schema

Type: string

Type: array

ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like "ci-cd". The set of fields is always in the version that the workflow used when modifying the object.

No Additional Items

Each item of this array must be:

io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry

Type: object

ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.

Type: string

APIVersion defines the version of this resource that this field set applies to. The format is "group/version" just like the top-level APIVersion field. It is necessary to track the version of a field set because it cannot be automatically converted.

Type: string

FieldsType is the discriminator for the different fields format and version. There is currently only one possible value: "FieldsV1"

io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1

Type: object

FieldsV1 holds the first JSON version format as described in the "FieldsV1" type.

Type: string

Manager is an identifier of the workflow managing these fields.

Type: string

Operation is the type of operation which lead to this ManagedFieldsEntry being created. The only valid values for this field are 'Apply' and 'Update'.

Type: string

Subresource is the name of the subresource used to update that object, or empty string if the object was updated through the main resource. The value of this field is used to distinguish between managers, even if they share the same name. For example, a status update will be distinct from a regular update using the same manager name. Note that the APIVersion field is not related to the Subresource field and it always corresponds to the version of the main resource.

io.k8s.apimachinery.pkg.apis.meta.v1.Time

Type: string

Time is the timestamp of when the ManagedFields entry was added. The timestamp will also be updated if a field is added, the manager changes any of the owned fields value or removes a field. The timestamp does not update when a field is removed from the entry because another manager took it over.

Same definition as creationTimestamp

Type: string

Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names

Type: string

Namespace defines the space within which each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.

Must be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces

Type: array

List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.

No Additional Items

Each item of this array must be:

io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference

Type: object

OwnerReference contains enough information to let you identify an owning object. An owning object must be in the same namespace as the dependent, or be cluster-scoped, so there is no namespace field.

Type: boolean

If true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion for how the garbage collector interacts with this field and enforces the foreground deletion. Defaults to false. To set this field, a user needs "delete" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.

Type: boolean

If true, this reference points to the managing controller.

Type: string

Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

Type: string

Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names

Type: string

UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids

Type: string

An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.

Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency

Type: string

UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.

Populated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids

Type: object

VirtualMCPServerSpec defines the desired state of VirtualMCPServer

Type: object

AuthServerConfig configures an embedded OAuth authorization server.
When set, the vMCP server acts as an OIDC issuer, drives users through
upstream IDPs, and issues ToolHive JWTs. The embedded AS becomes the
IncomingAuth OIDC provider — its issuer must match IncomingAuth.OIDCConfigRef
so that tokens it issues are accepted by the vMCP's incoming auth middleware.
When nil, IncomingAuth uses an external IDP and behavior is unchanged.

Type: string

AuthorizationEndpointBaseURL overrides the base URL used for the authorization_endpoint
in the OAuth discovery document. When set, the discovery document will advertise
{authorizationEndpointBaseUrl}/oauth/authorize instead of {issuer}/oauth/authorize.
All other endpoints (token, registration, JWKS) remain derived from the issuer.
This is useful when the browser-facing authorization endpoint needs to be on a
different host than the issuer used for backend-to-backend calls.
Must be a valid HTTPS URL (or HTTP for localhost, or HTTP for trusted in-cluster hosts
when insecureAllowHTTP is true) without query, fragment, or trailing slash.

Must match regular expression: ^https?://[^\s?#]+[^/\s?#]$

Type: array of string

BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
included in every client registration. The embedded auth server unions these
scopes into the registered set returned by RFC 7591 Dynamic Client
Registration, so a client that narrows the scope field at /oauth/register
can still request the baseline scopes at /oauth/authorize. All values must
be present in the upstream-derived scopesSupported set; the auth server
fails to start if any value is missing.

Security: every client registered via /oauth/register will gain the
ability to request these scopes at /oauth/authorize, regardless of what
the client itself requested. Keep the baseline narrow (typically
"openid" and "offline_access"). Adding a privileged scope here — e.g.
"admin:read" — would grant it to every DCR-registered client, including
public clients like Claude Code, Cursor, and VS Code.
When cimd.enabled is true, every dynamically resolved CIMD client will
also gain the ability to request these scopes, including third-party
clients resolved from arbitrary HTTPS URLs.

Must contain a maximum of 10 items

No Additional Items

Each item of this array must be:

Type: string
Must match regular expression: ^[\x21\x23-\x5B\x5D-\x7E]+$

Must be at least 1 characters long

Type: object

CIMD configures Client ID Metadata Document support. When omitted, CIMD is disabled.

Type: string

CacheFallbackTTL is the fixed TTL applied to every cached CIMD document.
Cache-Control header parsing is not yet implemented; all entries use this value.
Format: Go duration string (e.g. "5m", "10m", "1h").
Defaults to 5 minutes when Enabled is true and this field is omitted.

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: integer

CacheMaxSize is the maximum number of CIMD documents held in the LRU cache.
Defaults to 256 when Enabled is true and this field is omitted.

Value must be greater or equal to 1

Type: boolean

Enabled activates CIMD client lookup. When false (the default), the AS only
accepts client_id values that were registered via DCR.

Type: boolean

DisableUpstreamTokenInjection prevents the embedded auth server from injecting
upstream IdP tokens into requests forwarded to the backend MCP server.
When true, the embedded auth server still handles OAuth flows for clients,
but instead of swapping ToolHive JWTs for upstream tokens the proxy STRIPS
the client's credential headers (Authorization, Cookie, Proxy-Authorization)
after validating the JWT — the backend receives an unauthenticated request.
Use headerForward to attach static credentials (e.g. an API key) if the
backend needs them. Cannot be combined with token exchange or AWS STS,
which would re-add credentials after the strip.
This is useful when the backend MCP server does not require authentication
(e.g., public documentation servers) but you still want client authentication.

Type: array of object

HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing
authorization codes and refresh tokens (opaque tokens).
Current secret must be at least 32 bytes and cryptographically random.
Supports secret rotation via multiple entries (first is current, rest are for verification).
If not specified, an ephemeral secret will be auto-generated (development only -
auth codes and refresh tokens will be invalid after restart).

No Additional Items

Each item of this array must be:

Type: object

SecretKeyRef is a reference to a key within a Secret

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: boolean

InsecureAllowHTTP permits an http:// issuer URL for non-localhost hosts.
Only set this for in-cluster Kubernetes deployments where traffic between
pods traverses a trusted network (e.g. the in-cluster service mesh).
Production deployments reachable outside the cluster MUST use https://.

On VirtualMCPServer: when false (the default), http:// issuers for non-localhost
hosts are rejected at reconcile time with an AuthServerConfigValidated=False condition.

On MCPServer and MCPRemoteProxy (via MCPExternalAuthConfig): this field is
structurally present but enforcement is deferred to pod startup via Config.Validate();
a misconfigured issuer will cause the pod to crash at startup rather than surface
as an operator condition.

Type: string

Issuer is the issuer identifier for this authorization server.
This will be included in the "iss" claim of issued tokens.
Must be a valid HTTPS URL (or HTTP for localhost, or HTTP for trusted in-cluster hosts when
insecureAllowHTTP is true) without query, fragment, or trailing slash (per RFC 8414).

Must match regular expression: ^https?://[^\s?#]+[^/\s?#]$

Type: string

PrimaryUpstreamProvider names the upstream IDP whose access token Cedar
should read claims from when authorising a request. Must match the name
of one of the entries in UpstreamProviders. When empty, the controller
auto-selects the first entry of UpstreamProviders.

Only meaningful on VirtualMCPServer, where multiple upstream providers
can be configured and Cedar needs to pick which token's claims to
evaluate. The VirtualMCPServer controller validates this field against
UpstreamProviders at admission and rejects unresolvable values.

On MCPServer and MCPRemoteProxy this field is structurally present (the
EmbeddedAuthServerConfig struct is shared) but has no runtime effect:
those CRDs are restricted to a single upstream so there is no choice to
make. Setting it on those CRDs is silently ignored.

Must match regular expression: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$

Must be at least 1 characters long

Must be at most 63 characters long

Type: array of object

SigningKeySecretRefs references Kubernetes Secrets containing signing keys for JWT operations.
Supports key rotation by allowing multiple keys (oldest keys are used for verification only).
If not specified, an ephemeral signing key will be auto-generated (development only -
JWTs will be invalid after restart).

Must contain a maximum of 5 items

No Additional Items

Each item of this array must be:

Type: object

SecretKeyRef is a reference to a key within a Secret

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: object

Storage configures the storage backend for the embedded auth server.
If not specified, defaults to in-memory storage.

Type: object

Redis configures the Redis storage backend.
Required when type is "redis".

Type: object

ACLUserConfig configures Redis ACL user authentication.

Type: object

PasswordSecretRef references a Secret containing the Redis ACL password.

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: object

UsernameSecretRef references a Secret containing the Redis ACL username.
When omitted, connections use legacy password-only AUTH. Omit for managed
Redis tiers that do not support ACL users (e.g. GCP Memorystore Basic/Standard
HA, Azure Cache for Redis). Set for services that support ACL users (e.g. AWS
ElastiCache non-cluster with Redis 6+ RBAC).

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: string

Addr is the Redis server address (host:port). Required for standalone and cluster modes.
Use for managed Redis services that expose a single endpoint (GCP Memorystore basic tier,
AWS ElastiCache without cluster mode, or cluster-mode services when clusterMode is true).
Mutually exclusive with sentinelConfig.

Type: boolean

ClusterMode enables the Redis Cluster protocol. Set to true when addr points to a
Redis Cluster discovery endpoint (e.g., GCP Memorystore Cluster, AWS ElastiCache
cluster mode enabled). Requires addr to be set.

Type: string

DialTimeout is the timeout for establishing connections.
Format: Go duration string (e.g., "5s", "1m").

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: string

ReadTimeout is the timeout for socket reads.
Format: Go duration string (e.g., "3s", "1m").

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: object

SentinelConfig holds Redis Sentinel configuration.
Use for self-managed Redis with Sentinel-based HA. Mutually exclusive with addr.

Type: integerFormat: int32

DB is the Redis database number.

Type: string

MasterName is the name of the Redis master monitored by Sentinel.

Type: array of string

SentinelAddrs is a list of Sentinel host:port addresses.
Mutually exclusive with SentinelService.

No Additional Items

Each item of this array must be:

Type: object

SentinelService enables automatic discovery from a Kubernetes Service.
Mutually exclusive with SentinelAddrs.

Type: string

Name of the Sentinel Service.

Type: string

Namespace of the Sentinel Service (defaults to same namespace).

Type: integerFormat: int32

Port of the Sentinel service.

Type: object

SentinelTLS configures TLS for connections to Sentinel instances.
Only applies when sentinelConfig is set. Presence of this field enables TLS.

Type: object

CACertSecretRef references a Secret containing a PEM-encoded CA certificate
for verifying the server. When not specified, system root CAs are used.

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: boolean

InsecureSkipVerify skips TLS certificate verification.
Use when connecting to services with self-signed certificates.

Type: object

TLS configures TLS for connections to the Redis/Valkey master or cluster nodes.
Presence of this field enables TLS. Omit to use plaintext.

Type: object

CACertSecretRef references a Secret containing a PEM-encoded CA certificate
for verifying the server. When not specified, system root CAs are used.

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: boolean

InsecureSkipVerify skips TLS certificate verification.
Use when connecting to services with self-signed certificates.

Type: string

WriteTimeout is the timeout for socket writes.
Format: Go duration string (e.g., "3s", "1m").

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: enum (of string)

Type specifies the storage backend type.
Valid values: "memory" (default), "redis".

Must be one of:

  • "memory"
  • "redis"

Type: object

TokenLifespans configures the duration that various tokens are valid.
If not specified, defaults are applied (access: 1h, refresh: 7d, authCode: 10m).

Type: string

AccessTokenLifespan is the duration that access tokens are valid.
Format: Go duration string (e.g., "1h", "30m", "24h").
If empty, defaults to 1 hour.

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: string

AuthCodeLifespan is the duration that authorization codes are valid.
Format: Go duration string (e.g., "10m", "5m").
If empty, defaults to 10 minutes.

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: string

RefreshTokenLifespan is the duration that refresh tokens are valid.
Format: Go duration string (e.g., "168h", "7d" as "168h").
If empty, defaults to 7 days (168h).

Must match regular expression: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$

Type: array of object

UpstreamProviders configures connections to upstream Identity Providers.
The embedded auth server delegates authentication to these providers.
MCPServer and MCPRemoteProxy support a single upstream; VirtualMCPServer supports multiple.

Must contain a minimum of 1 items

No Additional Items

Each item of this array must be:

Type: object

UpstreamProviderConfig defines configuration for an upstream Identity Provider.

Exactly one of OIDCConfig or OAuth2Config must be set and must match the
declared Type: oidc-typed providers set OIDCConfig, oauth2-typed providers
set OAuth2Config. The CEL rule below enforces the pairing at admission; the
matching Go-level check in validateUpstreamProvider provides defense-in-depth
for stored objects.

The rule is structured as a chain of equality checks ending in an explicit
false, so adding a new UpstreamProviderType value without extending this
rule fails admission instead of silently demanding the OAuth2 shape. When
adding a new type, extend both this rule and validateUpstreamProvider.

Type: string

Name uniquely identifies this upstream provider.
Used for routing decisions and session binding in multi-upstream scenarios.
Must be lowercase alphanumeric with hyphens (DNS-label-like).

Must match regular expression: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$

Must be at least 1 characters long

Must be at most 63 characters long

Type: object

OAuth2Config contains OAuth 2.0-specific configuration.
Required when Type is "oauth2", must be nil when Type is "oidc".

Type: object

AdditionalAuthorizationParams are extra query parameters to include in
authorization requests sent to the upstream provider.
This is useful for providers that require custom parameters, such as
Google's accesstype=offline for obtaining refresh tokens.
Framework-managed parameters (response
type, clientid, redirecturi,
scope, state, codechallenge, codechallenge_method, nonce) are not allowed.

Each additional property must conform to the following schema

Type: string

Type: string

AuthorizationEndpoint is the URL for the OAuth authorization endpoint.

Must match regular expression: ^https?://.*$

Type: string

ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.
Mutually exclusive with DCRConfig: when DCRConfig is set, ClientID is obtained
at runtime via RFC 7591 Dynamic Client Registration and must be left empty.

Type: object

ClientSecretRef references a Kubernetes Secret containing the OAuth 2.0 client secret.
Optional for public clients using PKCE instead of client secret.

Type: object

DCRConfig enables RFC 7591 Dynamic Client Registration against the upstream
authorization server. When set, the client credentials are obtained at
runtime rather than being pre-provisioned, and ClientID must be left empty.
Mutually exclusive with ClientID.

Type: string

DiscoveryURL is the RFC 8414 / OIDC Discovery document URL. The resolver
issues a single GET against this URL (no well-known-path fallback) and
reads registrationendpoint, authorizationendpoint, tokenendpoint,
token
endpointauthmethodssupported, and scopessupported from the
response.
Mutually exclusive with RegistrationEndpoint.
HTTPS is required because the registration endpoint resolved from this
document carries the initial access token and the issued client_secret
(RFC 7591 §3, RFC 8414 §3). MaxLength is a defensive size cap (etcd
object budget, regex evaluation cost) and matches the conventional URL
length cap.

Must match regular expression: ^https://[^\s?#]+[^/\s?#]$

Must be at most 2048 characters long

Type: object

InitialAccessTokenRef is an optional reference to a Kubernetes Secret
carrying an RFC 7591 §3 initial access token. When set, the resolver
presents the token value as a Bearer credential on the registration
request. Mirrors the ClientSecretRef pattern.

Type: string

RegistrationEndpoint is the RFC 7591 registration endpoint URL used
directly, bypassing discovery. When using this field, the caller is
expected to also supply AuthorizationEndpoint, TokenEndpoint, and an
explicit Scopes list on the parent OAuth2UpstreamConfig.
Mutually exclusive with DiscoveryURL.
HTTPS is required because the registration endpoint carries the initial
access token and the issued client_secret (RFC 7591 §3, RFC 8414 §3).
MaxLength is a defensive size cap (etcd object budget, regex evaluation
cost) and matches the conventional URL length cap.

Must match regular expression: ^https://[^\s?#]+[^/\s?#]$

Must be at most 2048 characters long

Type: string

SoftwareID is the RFC 7591 "software_id" registration metadata value,
identifying the client software independent of any particular
registration instance. Typically a UUID or short identifier.

Must be at most 255 characters long

Type: string

SoftwareStatement is the RFC 7591 "software_statement" JWT asserting
metadata about the client software, signed by a party the authorization
server trusts.

Stored inline on the CR. The JWT is signed but not encrypted, so its
contents are visible to anyone with get/list/watch on this resource and
appear in etcd backups in plaintext. Treat the value as non-confidential
(signed attestation, not a secret). Operators that rotate software
statements like bearer credentials should keep them at the authorization
server side and rely on the registration endpoint's initial access
token (see InitialAccessTokenRef) instead of placing them on the CR.

Bounded to 16384 characters as a defensive size cap (etcd object
budget, regex evaluation cost). Real-world signed statements with
embedded x5c certificate chains, JWKS keys, or OIDC-Federation
trust-framework metadata routinely exceed 4 KB.

Must be at most 16384 characters long

Type: object

IdentityFromToken extracts user identity (subject, name, email) directly
from the OAuth2 token-endpoint response body using gjson dot-notation paths.
When set, the embedded auth server skips the userinfo HTTP call entirely
and resolves identity from the token response. See IdentityFromTokenConfig
for trust-model and uniqueness considerations.

Type: string

EmailPath is the dot-notation path to the email address field in the token response.
If not specified or if the path does not resolve to a string, the email is omitted.
Omit the field entirely rather than setting it to an empty string.

Must be at least 1 characters long

Must be at most 256 characters long

Type: string

NamePath is the dot-notation path to the display name field in the token response.
If not specified or if the path does not resolve to a string, the display name is omitted.
Omit the field entirely rather than setting it to an empty string.

Must be at least 1 characters long

Must be at most 256 characters long

Type: string

SubjectPath is the dot-notation path to the subject (user ID) field in the token response.
Warning: claims read from the token response are trusted only via TLS, not
cryptographically verified; prefer OIDC ID tokens when verifiable claims are required.
Example: "autheduser.id" for Slack (top-level token-response field). For providers
whose token response embeds the access token as a JWT (e.g. Snowflake), use the
"@upstreamjwt" modifier to decode the payload, e.g. "access
token|@upstreamjwt|sub".
The "@upstreamjwt" modifier performs no signature verification either.

Must be at least 1 characters long

Must be at most 256 characters long

Type: string

RedirectURI is the callback URL where the upstream IdP will redirect after authentication.
When not specified, defaults to {resourceUrl}/oauth/callback where resourceUrl is the
URL associated with the resource (e.g., MCPServer or vMCP) using this config.

Type: array of string

Scopes are the OAuth scopes to request from the upstream IdP.

No Additional Items

Each item of this array must be:

Type: string

TokenEndpoint is the URL for the OAuth token endpoint.

Must match regular expression: ^https?://.*$

Type: object

TokenResponseMapping configures custom field extraction from non-standard token responses.
Some OAuth providers (e.g., GovSlack) nest token fields under non-standard paths
instead of returning them at the top level. When set, ToolHive performs the token
exchange HTTP call directly and extracts fields using the configured dot-notation paths.
If nil, standard OAuth 2.0 token response parsing is used.
For extracting user identity from the token response, see IdentityFromToken.

Type: string

AccessTokenPath is the dot-notation path to the access token in the response.
Example: "autheduser.accesstoken"

Must be at least 1 characters long

Type: string

ExpiresInPath is the dot-notation path to the expiresin value (in seconds).
If not specified, defaults to "expires
in".

Type: string

RefreshTokenPath is the dot-notation path to the refresh token in the response.
If not specified, defaults to "refresh_token".

Type: string

ScopePath is the dot-notation path to the scope string in the response.
If not specified, defaults to "scope".

Type: object

UserInfo contains configuration for fetching user information from the upstream provider.
When omitted and IdentityFromToken is also unset, the embedded auth server runs in
synthesis mode for this upstream: a non-PII subject derived from the access token, no
Name/Email. Use this shape for upstreams with no userinfo surface and no identity in
the token response (e.g., MCP authorization servers per the MCP spec). When
IdentityFromToken is set instead, identity is resolved from the token response body
(e.g., Snowflake's "username" field, Slack's "authed_user.id"); the userinfo HTTP call
is skipped entirely.

Type: object

AdditionalHeaders contains extra headers to include in the userinfo request.
Useful for providers that require specific headers (e.g., GitHub's Accept header).

Each additional property must conform to the following schema

Type: string

Type: string

EndpointURL is the URL of the userinfo endpoint.

Must match regular expression: ^https?://.*$

Type: object

FieldMapping contains custom field mapping configuration for non-standard providers.
If nil, standard OIDC field names are used ("sub", "name", "email").

Type: array of string

EmailFields is an ordered list of field names to try for the email address.
The first non-empty value found will be used.
Default: ["email"]

No Additional Items

Each item of this array must be:

Type: array of string

NameFields is an ordered list of field names to try for the display name.
The first non-empty value found will be used.
Default: ["name"]

No Additional Items

Each item of this array must be:

Type: array of string

SubjectFields is an ordered list of field names to try for the user ID.
The first non-empty value found will be used.
Default: ["sub"]

No Additional Items

Each item of this array must be:

Type: enum (of string)

HTTPMethod is the HTTP method to use for the userinfo request.
If not specified, defaults to GET.

Must be one of:

  • "GET"
  • "POST"

Type: object

OIDCConfig contains OIDC-specific configuration.
Required when Type is "oidc", must be nil when Type is "oauth2".

Type: object

AdditionalAuthorizationParams are extra query parameters to include in
authorization requests sent to the upstream provider.
This is useful for providers that require custom parameters, such as
Google's accesstype=offline for obtaining refresh tokens.
Note: when using access
type=offline, also set explicit scopes to avoid
the default offlineaccess scope being sent alongside it.
Framework-managed parameters (response
type, clientid, redirecturi,
scope, state, codechallenge, codechallenge_method, nonce) are not allowed.

Each additional property must conform to the following schema

Type: string

Type: string

ClientID is the OAuth 2.0 client identifier registered with the upstream IdP.

Type: object

ClientSecretRef references a Kubernetes Secret containing the OAuth 2.0 client secret.
Optional for public clients using PKCE instead of client secret.

Type: string

IssuerURL is the OIDC issuer URL for automatic endpoint discovery.
Must be a valid HTTPS URL.

Must match regular expression: ^https://.*$

Type: string

RedirectURI is the callback URL where the upstream IdP will redirect after authentication.
When not specified, defaults to {resourceUrl}/oauth/callback where resourceUrl is the
URL associated with the resource (e.g., MCPServer or vMCP) using this config.

Type: array of string

Scopes are the OAuth scopes to request from the upstream IdP.
If not specified, defaults to ["openid", "offlineaccess"].
When using additionalAuthorizationParams with provider-specific refresh token
mechanisms (e.g., Google's access
type=offline), set explicit scopes to avoid
sending both offline_access and the provider-specific parameter.

No Additional Items

Each item of this array must be:

Type: string

SubjectClaim names the validated ID-token claim to use as the upstream
subject. Defaults to "sub" when empty. Set it for IdPs where "sub" isn't
stable per user — e.g. Entra/Azure AD, whose "sub" rotates per application
and whose stable identifier is "oid".

The value is looked up verbatim as a top-level claim name, so it is
constrained to a claim-name shape: it must start with a letter or
underscore and contain only letters, digits, and underscores. This rejects
dotted, colon-namespaced, or whitespace-containing values at admission
rather than letting a typo silently miss the claim at login, and keeps the
field aligned with the directory service's per-issuer bindingClaim.

Changing this on a live deployment re-keys existing users (the value
resolves to the internal user ID), so treat it as immutable once users
exist.

Per-IdP notes:
- Entra/Azure AD: use "oid"; it is only emitted when the upstream scopes
include "profile". "oid" is unique within a single tenant — multi-tenant
apps need oid+tid, which this single-claim field cannot express.
- Okta: the org auth server already puts the stable id in "sub" (default
works). A custom auth server's "sub" is the mutable login/email and the
stable "uid" lives only in the access token, not the ID token — map a
custom ID-token claim and point subjectClaim at it.
The pattern matches the claim-name shape and allows empty (defaults to
"sub"). Using Pattern rather than a CEL XValidation rule keeps this off the
CRD's CEL cost budget — a single-field format check via CEL is rejected by
the apiserver as too expensive once multiplied across the upstreams list.

Must match regular expression: ^([a-zA-Z_][a-zA-Z0-9_]*)?$

Must be at most 128 characters long

Type: object

UserInfoOverride allows customizing UserInfo fetching behavior for OIDC providers.
By default, the UserInfo endpoint is discovered automatically via OIDC discovery.
Use this to override the endpoint URL, HTTP method, or field mappings for providers
that return non-standard claim names in their UserInfo response.

Type: object

AdditionalHeaders contains extra headers to include in the userinfo request.
Useful for providers that require specific headers (e.g., GitHub's Accept header).

Each additional property must conform to the following schema

Type: string

Type: string

EndpointURL is the URL of the userinfo endpoint.

Must match regular expression: ^https?://.*$

Type: object

FieldMapping contains custom field mapping configuration for non-standard providers.
If nil, standard OIDC field names are used ("sub", "name", "email").

Type: array of string

EmailFields is an ordered list of field names to try for the email address.
The first non-empty value found will be used.
Default: ["email"]

No Additional Items

Each item of this array must be:

Type: array of string

NameFields is an ordered list of field names to try for the display name.
The first non-empty value found will be used.
Default: ["name"]

No Additional Items

Each item of this array must be:

Type: array of string

SubjectFields is an ordered list of field names to try for the user ID.
The first non-empty value found will be used.
Default: ["sub"]

No Additional Items

Each item of this array must be:

Type: enum (of string)

HTTPMethod is the HTTP method to use for the userinfo request.
If not specified, defaults to GET.

Must be one of:

  • "GET"
  • "POST"

Type: enum (of string)

Type specifies the provider type: "oidc" or "oauth2"

Must be one of:

  • "oidc"
  • "oauth2"

Type: object

Config is the Virtual MCP server configuration.
The audit config from here is also supported, but not required.

Type: object

EmbeddingServerRef references an existing EmbeddingServer resource by name.
When the optimizer is enabled, this field is required to point to a ready EmbeddingServer
that provides embedding capabilities.
The referenced EmbeddingServer must exist in the same namespace and be ready.

Type: string

Name is the name of the EmbeddingServer resource

Type: object

GroupRef references the MCPGroup that defines backend workloads.
The referenced MCPGroup must exist in the same namespace.

Type: string

Name is the name of the MCPGroup resource in the same namespace

Must be at least 1 characters long

Type: array of object

ImagePullSecrets allows specifying image pull secrets for the vMCP workload.
These are applied to both the vMCP Deployment's PodSpec.ImagePullSecrets
and to the operator-managed ServiceAccount the vMCP server runs as, so private
images are pullable through either path.

Merge semantics with PodTemplateSpec:
The deployed PodSpec.ImagePullSecrets is the Kubernetes-native strategic-merge
union of this field and spec.podTemplateSpec.spec.imagePullSecrets, merged by
the patchStrategy:"merge" / patchMergeKey:"name" tags on corev1.PodSpec.
- This field is rendered first as the controller-generated default.
- spec.podTemplateSpec.spec.imagePullSecrets is then strategic-merge-patched
on top, keyed by Name. Distinct names from the two sources are unioned in
the resulting list; entries with the same Name are deduplicated and the
PodTemplateSpec entry wins on overlap (user override).
- Order in the resulting list is not guaranteed and should not be relied on:
strategic merge by name is order-insensitive.
- The operator-managed ServiceAccount's imagePullSecrets list is populated
ONLY from this field. spec.podTemplateSpec.spec.imagePullSecrets does not
reach the ServiceAccount because PodTemplateSpec has no notion of a
ServiceAccount. To make a secret usable via the ServiceAccount path
(e.g. for sidecars or init containers that pull images independently),
list it here rather than under spec.podTemplateSpec.

Note on cross-CRD consistency:
MCPRegistry currently uses an atomic-replace strategy for its imagePullSecrets
(the user-provided value replaces the controller-generated list rather than
being merged on top). VirtualMCPServer follows the Kubernetes-native
strategic-merge-by-name behavior described above. Aligning the two is tracked
as a separate follow-up; until then, manifests that set imagePullSecrets on
both CRDs will see different override behavior between them.

No Additional Items

Each item of this array must be:

Type: object

LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.

Type: string

Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

Type: object

IncomingAuth configures authentication for clients connecting to the Virtual MCP server.
Must be explicitly set - use "anonymous" type when no authentication is required.
This field takes precedence over config.IncomingAuth and should be preferred because it
supports Kubernetes-native secret references (SecretKeyRef, ConfigMapRef) for secure
dynamic discovery of credentials, rather than requiring secrets to be embedded in config.

Type: object

AuthzConfig defines authorization policy configuration.
Reuses MCPServer authz patterns.
AuthzConfig and AuthzConfigRef are mutually exclusive.

Type: object

ConfigMap references a ConfigMap containing authorization configuration
Only used when Type is "configMap"

Type: string

Key is the key in the ConfigMap that contains the authorization configuration

Type: string

Name is the name of the ConfigMap

Type: string

GroupClaimName is the JWT claim key that contains group membership for the
principal. When set, takes priority over the well-known defaults
("groups", "roles", "cognito:groups"). Use this for IDPs that place
groups under a URI-style claim (e.g. "https://example.com/groups"). When
Type is "configMap", a groupclaimname entry in the referenced ConfigMap
is overridden by this field if both are set.

Must be at most 253 characters long

Type: string

GroupEntityType is the Cedar entity type name used for principal parent
UIDs synthesised from JWT group/role claims. Defaults to "THVGroup" when
empty. Must match the entity type used in the static entity store for
transitive in checks (e.g. ClaimGroup → PlatformRole) to resolve.
Namespaced names (Foo::Bar) are not yet supported. When Type is
"configMap", a groupentitytype entry in the referenced ConfigMap is
overridden by this field if both are set.

Must match regular expression: ^[A-Za-z_][A-Za-z0-9_]*$

Must be at most 63 characters long

Type: object

Inline contains direct authorization configuration
Only used when Type is "inline"

Type: string

EntitiesJSON is a JSON string representing Cedar entities. Required when
transitive policies (e.g. ClaimGroup → PlatformRole) need a static
entity store; defaults to "[]".

Type: array of string

Policies is a list of Cedar policy strings

Must contain a minimum of 1 items

No Additional Items

Each item of this array must be:

Type: string

PrimaryUpstreamProvider names the upstream IDP whose access token's
claims Cedar should evaluate.

Deprecated: on VirtualMCPServer this field has moved to
spec.authServerConfig.primaryUpstreamProvider. The old location is
still read for one release for backward compatibility; the
VirtualMCPServer controller emits an AuthzPrimaryUpstreamProviderDeprecated
Warning event whenever it is consumed, and removal is planned for the
release after the deprecation cycle.

On MCPServer and MCPRemoteProxy this field has always been a structural
no-op (those CRDs do not run an embedded auth server). Setting it
continues to surface the AuthzPrimaryUpstreamProviderIgnored advisory
condition; the deprecation does not change that behaviour.

Must match regular expression: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$

Must be at least 1 characters long

Must be at most 63 characters long

Type: string

RoleClaimName is the JWT claim key that contains role membership for the
principal. When set, the claim is extracted separately from GroupClaimName
and both are mapped to the configured GroupEntityType. When Type is
"configMap", a roleclaimname entry in the referenced ConfigMap is
overridden by this field if both are set.

Must be at most 253 characters long

Type: enum (of string)

Type is the type of authorization configuration

Must be one of:

  • "configMap"
  • "inline"

Type: object

AuthzConfigRef references a shared MCPAuthzConfig resource for authorization.
The referenced MCPAuthzConfig must exist in the same namespace as this VirtualMCPServer.
Mutually exclusive with authzConfig.

Only cedarv1 MCPAuthzConfig resources are supported for VirtualMCPServer
today; referencing a non-Cedar config fails reconciliation with a clear
error because the vMCP runtime authz middleware is Cedar-only.

Type: string

Name is the name of the MCPAuthzConfig resource in the same namespace.

Must be at least 1 characters long

Type: object

OIDCConfigRef references a shared MCPOIDCConfig resource for OIDC authentication.
The referenced MCPOIDCConfig must exist in the same namespace as this VirtualMCPServer.
Per-server overrides (audience, scopes) are specified here; shared provider config
lives in the MCPOIDCConfig resource.

Type: string

Audience is the expected audience for token validation.
This MUST be unique per server to prevent token replay attacks.

Must be at least 1 characters long

Type: string

Name is the name of the MCPOIDCConfig resource

Must be at least 1 characters long

Type: string

ResourceURL is the public URL for OAuth protected resource metadata (RFC 9728).
When the server is exposed via Ingress or gateway, set this to the external
URL that MCP clients connect to. If not specified, defaults to the internal
Kubernetes service URL.

Type: array of string

Scopes is the list of OAuth scopes to advertise in the well-known endpoint (RFC 9728).
If empty, defaults to ["openid"].

No Additional Items

Each item of this array must be:

Type: enum (of string)

Type defines the authentication type: anonymous or oidc
When no authentication is required, explicitly set this to "anonymous"

Must be one of:

  • "anonymous"
  • "oidc"

Type: object

OutgoingAuth configures authentication from Virtual MCP to backend MCPServers.
This field takes precedence over config.OutgoingAuth and should be preferred because it
supports Kubernetes-native secret references (SecretKeyRef, ConfigMapRef) for secure
dynamic discovery of credentials, rather than requiring secrets to be embedded in config.

Type: object

Backends defines per-backend authentication overrides
Works in all modes (discovered, inline)

Each additional property must conform to the following schema

Type: object

BackendAuthConfig defines authentication configuration for a backend MCPServer

Type: object

ExternalAuthConfigRef references an MCPExternalAuthConfig resource
Only used when Type is "externalAuthConfigRef"

Type: string

Name is the name of the MCPExternalAuthConfig resource

Type: enum (of string)

Type defines the authentication type

Must be one of:

  • "discovered"
  • "externalAuthConfigRef"

Type: object

Default defines default behavior for backends without explicit auth config

Type: object

ExternalAuthConfigRef references an MCPExternalAuthConfig resource
Only used when Type is "externalAuthConfigRef"

Type: string

Name is the name of the MCPExternalAuthConfig resource

Type: enum (of string)

Type defines the authentication type

Must be one of:

  • "discovered"
  • "externalAuthConfigRef"

Type: enum (of string)

Source defines how backend authentication configurations are determined
- discovered: Automatically discover from backend's MCPServer.spec.externalAuthConfigRef
- inline: Explicit per-backend configuration in VirtualMCPServer

Must be one of:

  • "discovered"
  • "inline"

Type: array of string

PassthroughHeaders is an allowlist of incoming client request header names
forwarded verbatim to all backends (e.g. an API key the backend resolves to
a user). Takes precedence over config.PassthroughHeaders. Names must not be
restricted headers (Host, hop-by-hop, X-Forwarded-*). Forwarded headers are
attacker-influenceable unless a trusted upstream sets them.

No Additional Items

Each item of this array must be:

Type: object

PodTemplateSpec defines the pod template to use for the Virtual MCP server
This allows for customizing the pod configuration beyond what is provided by the other fields.
Note that to modify the specific container the Virtual MCP server runs in, you must specify
the 'vmcp' container name in the PodTemplateSpec.
This field accepts a PodTemplateSpec object as JSON/YAML.

Type: integerFormat: int32

Replicas is the desired number of vMCP pod replicas.
VirtualMCPServer creates a single Deployment for the vMCP aggregator process,
so there is only one replicas field (unlike MCPServer which has separate
Replicas and BackendReplicas for its two Deployments).
When nil, the operator does not set Deployment.Spec.Replicas, leaving replica
management to an HPA or other external controller.

Value must be greater or equal to 0

Type: string

ServiceAccount is the name of an already existing service account to use by the Virtual MCP server.
If not specified, a ServiceAccount will be created automatically and used by the Virtual MCP server.

Type: enum (of string)

ServiceType specifies the Kubernetes service type for the Virtual MCP server

Must be one of:

  • "ClusterIP"
  • "NodePort"
  • "LoadBalancer"

Type: enum (of string)

SessionAffinity controls whether the Service routes repeated client connections to the same pod.
MCP protocols (SSE, streamable-http) are stateful, so ClientIP is the default.
Set to "None" for stateless servers or when using an external load balancer with its own affinity.

Must be one of:

  • "ClientIP"
  • "None"

Type: object

SessionStorage configures session storage for stateful horizontal scaling.
When nil, no session storage is configured.

Type: string

Address is the Redis server address (required when provider is redis)

Must be at least 1 characters long

Type: integerFormat: int32

DB is the Redis database number

Value must be greater or equal to 0

Type: string

KeyPrefix is an optional prefix for all Redis keys used by ToolHive

Type: object

PasswordRef is a reference to a Secret key containing the Redis password

Type: string

Key is the key within the secret

Type: string

Name is the name of the secret

Type: enum (of string)

Provider is the session storage backend type

Must be one of:

  • "memory"
  • "redis"

Type: object

TelemetryConfigRef references an MCPTelemetryConfig resource for shared telemetry configuration.
The referenced MCPTelemetryConfig must exist in the same namespace as this VirtualMCPServer.
Cross-namespace references are not supported for security and isolation reasons.

Type: string

Name is the name of the MCPTelemetryConfig resource

Must be at least 1 characters long

Type: string

ServiceName overrides the telemetry service name for this specific server.
This MUST be unique per server for proper observability (e.g., distinguishing
traces and metrics from different servers sharing the same collector).
If empty, defaults to the server name with "thv-" prefix at runtime.

Type: object

VirtualMCPServerStatus defines the observed state of VirtualMCPServer

Type: string

AuthzConfigHash is the hash of the referenced MCPAuthzConfig spec for change detection.
Only populated when IncomingAuth.AuthzConfigRef is set.

Type: integerFormat: int32

BackendCount is the number of routable backends (ready + unauthenticated).
Excludes unavailable, degraded, and unknown backends.

Type: array of object

Conditions represent the latest available observations of the VirtualMCPServer's state

No Additional Items

Each item of this array must be:

Type: object

Condition contains details for one aspect of the current state of this API Resource.

Type: stringFormat: date-time

lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.

Type: string

message is a human readable message indicating details about the transition.
This may be an empty string.

Must be at most 32768 characters long

Type: integerFormat: int64

observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.

Value must be greater or equal to 0

Type: string

reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.

Must match regular expression: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

Must be at least 1 characters long

Must be at most 1024 characters long

Type: enum (of string)

status of the condition, one of True, False, Unknown.

Must be one of:

  • "True"
  • "False"
  • "Unknown"

Type: string

type of condition in CamelCase or in foo.example.com/CamelCase.

Must match regular expression: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$

Must be at most 316 characters long

Type: array of object

DiscoveredBackends lists discovered backend configurations from the MCPGroup

No Additional Items

Each item of this array must be:

Type: object

DiscoveredBackend represents a backend server discovered by vMCP runtime.
This type is shared with the Kubernetes operator CRD (VirtualMCPServer.Status.DiscoveredBackends).

Type: string

AuthConfigRef is the name of the discovered MCPExternalAuthConfig (if any)

Type: string

AuthType is the type of authentication configured

Type: enum (of string)

CircuitBreakerState is the current circuit breaker state (closed, open, half-open).
Empty when circuit breaker is disabled or not configured.

Must be one of:

  • "closed"
  • "open"
  • "half-open"

Type: stringFormat: date-time

CircuitLastChanged is the timestamp when the circuit breaker state last changed.
Empty when circuit breaker is disabled or has never changed state.

Type: integer

ConsecutiveFailures is the current count of consecutive health check failures.
Resets to 0 when the backend becomes healthy again.

Type: stringFormat: date-time

LastHealthCheck is the timestamp of the last health check

Type: string

MCPRevision is the backend's negotiated MCP protocol revision
("2026-07-28" or "2025-11-25"). Empty when the backend has not been probed.

Type: string

Message provides additional information about the backend status

Type: string

Name is the name of the backend MCPServer

Type: string

Status is the current status of the backend (ready, degraded, unavailable, unauthenticated, unknown).
Use BackendHealthStatus.ToCRDStatus() to populate this field.

Type: string

URL is the URL of the backend MCPServer

Type: string

Message provides additional information about the current phase

Type: integerFormat: int64

ObservedGeneration is the most recent generation observed for this VirtualMCPServer

Type: string

OIDCConfigHash is the hash of the referenced MCPOIDCConfig spec for change detection.
Only populated when IncomingAuth.OIDCConfigRef is set.

Type: enum (of string)

Phase is the current phase of the VirtualMCPServer

Must be one of:

  • "Pending"
  • "Ready"
  • "Degraded"
  • "Failed"

Type: string

TelemetryConfigHash is the hash of the referenced MCPTelemetryConfig spec for change detection.
Only populated when TelemetryConfigRef is set.

Type: string

URL is the URL where the Virtual MCP server can be accessed