MCPRegistry
toolhive.stacklok.dev / v1alpha1
apiVersion: toolhive.stacklok.dev/v1alpha1
kind: MCPRegistry
metadata:
name: example
apiVersion
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
kind
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
metadata
object
spec object
MCPRegistrySpec defines the desired state of MCPRegistry
configYAML
string required
ConfigYAML is the complete registry server config.yaml content.
The operator creates a ConfigMap from this string and mounts it
at /config/config.yaml in the registry-api container.
The operator does NOT parse, validate, or transform this content —
configuration validation is the registry server's responsibility.
Security note: this content is stored in a ConfigMap, not a Secret.
Do not inline credentials (passwords, tokens, client secrets) in this
field. Instead, reference credentials via file paths and mount the
actual secrets using the Volumes and VolumeMounts fields. For database
passwords, use PGPassSecretRef.
minLength:
1
displayName
string
DisplayName is a human-readable name for the registry.
imagePullSecrets []object
ImagePullSecrets allows specifying image pull secrets for the registry API workload.
These are applied to both the registry-api Deployment's PodSpec.ImagePullSecrets
and to the operator-managed ServiceAccount the registry API runs as, so private
images are pullable through either path.
Use this field for new manifests.
Important: this is the ONLY way to attach image-pull credentials to the
operator-managed ServiceAccount. The legacy
spec.podTemplateSpec.spec.imagePullSecrets path populates the Deployment's pod
spec ONLY — it does NOT touch the ServiceAccount. On managed Kubernetes
platforms that rely on ServiceAccount-level credential injection (for example
GKE Workload Identity, OpenShift's per-SA dockercfg secrets, EKS IRSA), using
only the legacy PodTemplateSpec path can fail to pull private images even when
the secret exists in the namespace. Always set spec.imagePullSecrets when
SA-level credentials matter.
Precedence with PodTemplateSpec:
- This field is applied first as the controller-generated default.
- Values set under spec.podTemplateSpec.spec.imagePullSecrets are user overrides
and win on overlap. If the user supplies imagePullSecrets via PodTemplateSpec,
those replace the default list on the Deployment (the list is treated atomically).
- The ServiceAccount is always populated from this field — PodTemplateSpec does not
affect the ServiceAccount.
An omitted field and an explicitly empty list are equivalent: both leave the
ServiceAccount's existing ImagePullSecrets unchanged. This preserves
platform-managed pull secrets (for example OpenShift's per-SA dockercfg
entries) when overlays or patches emit an empty list. Truly clearing the
ServiceAccount's pull secrets requires recreating the resource.
name
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
pgpassSecretRef object
PGPassSecretRef references a Secret containing a pre-created pgpass file.
Why this is a dedicated field instead of a regular volume/volumeMount:
PostgreSQL's libpq rejects pgpass files that aren't mode 0600. Kubernetes
secret volumes mount files as root-owned, and the registry-api container
runs as non-root (UID 65532). A root-owned 0600 file is unreadable by
UID 65532, and using fsGroup changes permissions to 0640 which libpq also
rejects. The only solution is an init container that copies the file to an
emptyDir as the app user and runs chmod 0600. This cannot be expressed
through volumes/volumeMounts alone -- it requires an init container, two
extra volumes (secret + emptyDir), a subPath mount, and an environment
variable, all wired together correctly.
When specified, the operator generates all of that plumbing invisibly.
The user creates the Secret with pgpass-formatted content; the operator
handles only the Kubernetes permission mechanics.
Example Secret:
apiVersion: v1
kind: Secret
metadata:
name: my-pgpass
stringData:
.pgpass: |
postgres:5432:registry:db_app:mypassword
postgres:5432:registry:db_migrator:otherpassword
Then reference it:
pgpassSecretRef:
name: my-pgpass
key: .pgpass
key
string required
The key of the secret to select from. Must be a valid secret key.
name
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
optional
boolean
Specify whether the Secret or its key must be defined
podTemplateSpec
object
PodTemplateSpec defines the pod template to use for the registry API server.
This allows for customizing the pod configuration beyond what is provided by the other fields.
Note that to modify the specific container the registry API server runs in, you must specify
the `registry-api` container name in the PodTemplateSpec.
This field accepts a PodTemplateSpec object as JSON/YAML.
volumeMounts
[]
VolumeMounts defines additional volume mounts for the registry-api container.
Each entry is a standard Kubernetes VolumeMount object (JSON/YAML).
The operator appends them to the container's volume mounts alongside the config mount.
Mount paths must match the file paths referenced in configYAML.
For example, if configYAML references passwordFile: /secrets/git-creds/token,
a corresponding volume mount must exist with mountPath: /secrets/git-creds.
volumes
[]
Volumes defines additional volumes to add to the registry API pod.
Each entry is a standard Kubernetes Volume object (JSON/YAML).
The operator appends them to the pod spec alongside its own config volume.
Use these to mount:
- Secrets (git auth tokens, OAuth client secrets, CA certs)
- ConfigMaps (registry data files)
- PersistentVolumeClaims (registry data on persistent storage)
- Any other volume type the registry server needs
status object
MCPRegistryStatus defines the observed state of MCPRegistry
conditions []object
Conditions represent the latest available observations of the MCPRegistry's state
lastTransitionTime
string required
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.
format:
date-time
message
string required
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength:
32768
observedGeneration
integer
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.
format:
int64minimum:
0
reason
string required
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.
pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$minLength:
1maxLength:
1024
status
string required
status of the condition, one of True, False, Unknown.
enum:
True, False, Unknown
type
string required
type of condition in CamelCase or in foo.example.com/CamelCase.
pattern:
^([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])$maxLength:
316
message
string
Message provides additional information about the current phase
observedGeneration
integer
ObservedGeneration reflects the generation most recently observed by the controller
format:
int64
phase
string
Phase represents the current overall phase of the MCPRegistry
enum:
Pending, Ready, Failed, Terminating
readyReplicas
integer
ReadyReplicas is the number of ready registry API replicas
format:
int32
url
string
URL is the URL where the registry API can be accessed
No matches. Try .spec.configYAML for an exact path