MCPServer
MCPServer (maqpna.com/v1alpha1): every field, type, default and validation rule, generated from the CRD schema.
MCPServer registers an MCP server with the gateway's per-namespace tool
registry. Agents in the same namespace reach it at /mcp/
At a glance#
| Property | Value |
|---|---|
| API version | maqpna.com/v1alpha1 |
| Kind | MCPServer |
| Scope | Namespaced |
| Plural | mcpservers |
| Short names | mcps, mcp |
| Categories | maqpna |
| Status subresource | yes |
kubectl get mcpservers -A
kubectl get mcps <name> -o yaml
kubectl explain mcpservers.spec
Columns in kubectl get#
| Column | Type | From |
|---|---|---|
| URL | string | .spec.url |
| Auth | string | .spec.auth.type |
| Trust | string | .spec.trust |
| Ready | string | .status.conditions[?(@.type=="Ready")].status |
| Pinned | string | .status.conditions[?(@.type=="Pinned")].status |
| Tools | integer | .status.observedTools |
| Age | date | .metadata.creationTimestamp |
Example#
From config/samples/mcpserver-github.yaml:
# A per-namespace MCP server registration (F-01). Agents in team-a reach it at
# {gateway}/mcp/github with scope tools:github; the gateway injects the token
# from Secret github-mcp (F-06) — the sandbox never sees it.
apiVersion: maqpna.com/v1alpha1
kind: MCPServer
metadata:
name: github
namespace: team-a
spec:
url: https://mcp-github.tools.acme.eu/mcp
transport: streamable-http
protocolVersions: ["2025-11-25"]
trust: trusted
dataClass: internal
jurisdiction: EU-DE
timeoutSeconds: 60
auth:
type: bearerSecret
secretRef:
name: github-mcp
key: token
Spec fields#
MCPServerSpec registers an upstream MCP server for the gateway.
| Field | Type | Required | Description |
|---|---|---|---|
allowedNamespaces |
[]string | allowedNamespaces may use a shared server (by short name or serverRef). | |
auth |
object | auth configures upstream credential injection (F-06). Rule: bearerSecret requires secretRef. Rule: headerSecret requires secretRef and headerName. Rule: oauthClientCredentials requires oauth. Rule: tokenExchange requires tokenExchange. Rule: mtls requires mtls. Rule: perUser requires provider and type none or mtls. Rule: provider is only valid with perUser. | |
auth.headerName |
string | headerName for headerSecret, e.g. X-Api-Key. Pattern: ^[A-Za-z0-9-]{1,64}$. |
|
auth.mtls |
object | MCPMTLS configures a client certificate presented by the gateway. | |
auth.mtls.certSecretRef |
object | yes | certSecretRef names a kubernetes.io/tls Secret (tls.crt, tls.key). |
auth.mtls.certSecretRef.name |
string | yes | Min length: 1. |
auth.oauth |
object | MCPOAuthClientCredentials configures an OAuth 2.0 client-credentials grant performed by the gateway (tokens cached until exp-60s). | |
auth.oauth.audience |
string | ||
auth.oauth.clientIdRef |
object | yes | clientIdRef selects the client id. |
auth.oauth.clientIdRef.key |
string | yes | Min length: 1. Max length: 253. Pattern: ^[-._a-zA-Z0-9]+$. |
auth.oauth.clientIdRef.name |
string | yes | Min length: 1. Max length: 253. |
auth.oauth.clientSecretRef |
object | yes | clientSecretRef selects the client secret. |
auth.oauth.clientSecretRef.key |
string | yes | Min length: 1. Max length: 253. Pattern: ^[-._a-zA-Z0-9]+$. |
auth.oauth.clientSecretRef.name |
string | yes | Min length: 1. Max length: 253. |
auth.oauth.resource |
string | resource is the RFC 8707 resource indicator. | |
auth.oauth.scopes |
[]string | ||
auth.oauth.tokenURL |
string | yes | tokenURL is the authorization server's token endpoint. Pattern: ^https?://. |
auth.perUser |
boolean | perUser injects the delegating user's own OAuth access token from the gateway's token vault (F-17): the session's verified principal must have connected the provider (GET /v1/connect/ |
|
auth.provider |
string | provider names the token-vault provider (gateway tokenVault.providers) whose per-user token is injected when perUser is true. Pattern: ^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$. |
|
auth.secretRef |
object | secretRef holds the token (bearerSecret) or header value (headerSecret). | |
auth.secretRef.key |
string | yes | Min length: 1. Max length: 253. Pattern: ^[-._a-zA-Z0-9]+$. |
auth.secretRef.name |
string | yes | Min length: 1. Max length: 253. |
auth.tokenExchange |
object | MCPTokenExchange configures a per-session RFC 8693 exchange at the MAQPNA identity broker: the upstream receives a down-scoped token carrying act.sub. | |
auth.tokenExchange.audience |
string | yes | audience must be allowlisted in the broker's -exchange-config. Min length: 1. |
auth.type |
string | yes | One of: none, bearerSecret, headerSecret, oauthClientCredentials, tokenExchange, mtls. Default: "none". |
caBundleRef |
object | caBundleRef selects a PEM CA bundle (ConfigMap, same namespace) that is trusted in addition to the system roots for this server. | |
caBundleRef.key |
string | yes | Min length: 1. |
caBundleRef.name |
string | yes | Min length: 1. |
dataClass |
string | dataClass is the highest classification of data the server handles. One of: public, internal, confidential, restricted. Default: "internal". |
|
dlpProfile |
string | dlpProfile names a gateway DLP profile (gateway config dlpProfiles, F-12) for this server's tool arguments and results; it takes precedence over the gateway's dlp.servers / namespaces / default bindings. "none" disables DLP for the server. Pattern: ^[a-z0-9][a-z0-9-]{0,62}$. |
|
jurisdiction |
string | jurisdiction where the server runs; checked against the SovereigntyPolicy. Pattern: ^[A-Za-z]{2}(-[A-Za-z0-9]{1,8})*$. |
|
protocolVersions |
[]string | protocolVersions the server speaks (F-11). When set, the gateway refuses a 2026-07-28 request with -32022 and the common versions if the list lacks that revision, so clients fall back instead of failing upstream. | |
shared |
boolean | shared makes the server usable from allowedNamespaces (the owner opts in). | |
timeoutSeconds |
integer (int32) | timeoutSeconds bounds the wait for upstream response headers. Minimum: 1. Maximum: 3600. |
|
toolLabels |
map[string]object | toolLabels label individual tools for taint tracking (F-13), keyed by tool name. | |
toolLabels.<key>.clearTaints |
[]string | clearTaints are removed after a successful call ("*" = all). Max items: 16. |
|
toolLabels.<key>.sinks |
[]string | sinks mark the tool as exfiltration-capable (matched by rule sinks). Max items: 16. |
|
toolLabels.<key>.taints |
[]string | taints are added to the session after a call of this tool. Max items: 16. |
|
toolPins |
object | toolPins pins this server's tool definitions (F-04), merged with ToolPolicy spec.toolPins for the same server name. | |
toolPins.allowUnpinned |
boolean | allowUnpinned lets tools without a pin through in enforce mode. | |
toolPins.mode |
string | mode: off | learn (default) | enforce. One of: off, learn, enforce. |
|
toolPins.onChange |
string | onChange in enforce mode: hide (default) | approve | alert. One of: hide, approve, alert. |
|
toolPins.pins |
map[string]string | ||
transport |
string | transport; only streamable-http in v1. One of: streamable-http. Default: "streamable-http". |
|
trust |
string | trust classifies the server's output (feeds taint tracking, F-13). One of: trusted, untrusted. Default: "untrusted". |
|
url |
string | yes | url is the Streamable HTTP endpoint. Only the gateway talks to it. Pattern: ^https?://[^/@\s]+. |
Status fields#
MCPServerStatus is the observed state of an MCPServer.
The operator writes status; do not set it yourself.
| Field | Type | Required | Description |
|---|---|---|---|
conditions |
[]object | conditions: Ready, SovereigntyCompliant and Pinned (F-04: True when every observed tool matches a pin, False on drift). | |
conditions[].lastTransitionTime |
string (date-time) | yes | 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. |
conditions[].message |
string | yes | message is a human readable message indicating details about the transition. This may be an empty string. Max length: 32768. |
conditions[].observedGeneration |
integer (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. Minimum: 0. |
|
conditions[].reason |
string | yes | 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. Min length: 1. Max length: 1024. Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$. |
conditions[].status |
string | yes | status of the condition, one of True, False, Unknown. One of: True, False, Unknown. |
conditions[].type |
string | yes | type of condition in CamelCase or in foo.example.com/CamelCase. Max length: 316. 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])$. |
driftedTools |
[]string | driftedTools are tools whose observed definition differs from every pin (rug-pull / poisoning suspects), sorted, at most 64. Max items: 64. |
|
gatewayKey |
string | gatewayKey is the registry key " |
|
lastSeen |
string (date-time) | lastSeen is when the gateway last reported pin status. | |
observedGeneration |
integer (int64) | ||
observedTools |
integer (int32) | observedTools is the number of tools the gateway has seen (F-04), reported through the maqpna.com/tool-pins annotation. |