agentic
sidebar_position: 16
Agentic Domain
The Agentic domain manages the lifecycle of MCP (Model Context Protocol) servers within the Control Plane — from server registration through exposure to subscription. It acts as an abstraction layer above the Gateway domain, handling business logic for who can access which MCP servers and under what conditions.
Custom Resources
| Resource | Purpose |
|---|---|
McpServer | Registers an MCP server endpoint for a given basePath. Created and owned by the Rover domain via McpSpecification. Only the oldest active McpServer per basePath is considered active. |
McpExposure | Exposes an active McpServer on the AI Gateway by creating gateway Routes. Only one McpExposure per basePath can be active at a time (oldest-wins). |
McpSubscription | Requests access to an MCP exposure. Triggers an approval workflow; once approved, a ConsumeRoute is created on the gateway. |
Reconciliation Flow
rover-ctl apply mcpspec.yaml
│
├──▶ McpSpecification created (rover domain)
│ └──▶ McpServer created (registered)
│
├──▶ McpExposure created (by exposing team)
│ └──▶ AI Gateway Route(s) provisioned
│
└──▶ McpSubscription created (by subscribing team)
│
├──▶ Approval created (if strategy ≠ auto)
├──▶ Approval granted
└──▶ Gateway ConsumeRoute created (access granted)
Subscription Approval Scopes
An AgenticSubscription approval request includes the requested
spec.security.m2m.scopes in its properties, following the API subscription
approval flow. These properties determine the request identity, so changing
the requested scopes creates a distinct approval request. The configured
approval strategy applies to that new request, including automatic approval
where configured.
While the new request is pending or rejected, the existing ConsumeRoute
remains unchanged. The controller updates its scopes once approval is granted
for the new request. Rejecting or suspending the Approval itself removes the
ConsumeRoute.
Route Provisioning
When an McpExposure is reconciled, the Agentic operator provisions gateway Routes on the AI Gateway:
| Route created | When | Location |
|---|---|---|
| Primary route | Always — one per exposure | Provider's zone namespace |
| Proxy route | For each zone with an approved cross-zone subscription, and for the Telecontext Application's zone (TELECONTEXTMCP only) | Proxy zone namespace, upstream = provider zone's AI Gateway |
After approval, an AgenticSubscription publishes the path-specific AI Gateway
URL in its status. The Projector persists this value and exposes it as
gatewayURL on the GraphQL AgenticSubscription type.
Subscription Readiness
AgenticSubscription uses the shared Ready condition reason vocabulary used by
API subscriptions. The condition message provides the specific cause.
| Ready status | Reason | Meaning |
|---|---|---|
True | Provisioned | Subscription provisioning completed. |
False | PreconditionNotMet | An active server, ready exposure, required route reference, or AI Gateway feature is unavailable. |
False | ValidationFailed | The base path has a case conflict, or requested OAuth2 scopes are invalid or undefined by the server. |
False | AccessDenied | Visibility rules disallow the subscription, or its approval or approval request was denied. |
False | ApprovalPending | An approval decision is pending. |
False | Processing | A previously pending approval was granted; provisioning is in progress. |
False | SubResourceNotReady | The child-resource readiness check has not passed. |
Once approval is granted, a previous ApprovalPending reason is cleared before
provisioning continues, including when a subsequent provisioning operation fails.
The child-resource readiness check reports Ready=False / SubResourceNotReady
when a condition-bearing resource created or updated during reconciliation,
including the ApprovalRequest or ConsumeRoute, explicitly reports
Ready=False. This check does not reject missing or unknown Ready conditions
and does not check child ObservedGeneration.
Cross-Zone Meshing
When subscribers exist in a different zone than the exposure, the operator creates a proxy Route in the subscriber's zone. That proxy gateway stamps a Last-Mile-Security (LMS) token when forwarding traffic to the provider zone. The primary route therefore adds the subscriber zone's LmsIssuer to its TrustedIssuers so that forwarded requests are accepted.
Forwarded requests arrive at the primary route as the gateway mesh client (gateway consumer), so the primary route allows this consumer as soon as at least one proxy route exists. The proxy routes themselves do not allow the gateway consumer: they are the source of the mesh hop, not its target. Subscribers access their zone's proxy route through their ConsumeRoute.
The primary route's TrustedIssuers are composed as follows:
- Exposure zone's IDP issuer — only when there are local callers: at least one local (same-zone) subscriber, or the Telecontext Application in the exposure zone (
TELECONTEXTMCPonly) - LMS issuers from each cross-zone proxy gateway — for mesh-forwarded traffic from proxy zones (subscriber zones and the Telecontext zone)
Variants
An McpExposure can declare a spec.variant that changes how access is provisioned:
MCP (default)
Standard exposure. The AI Gateway Route is created with normal access control. Consumers gain access by subscribing and having a ConsumeRoute provisioned.
TELECONTEXTMCP
Used for MCP servers that should be accessible by the Telecontext platform consumer without going through the standard subscription/approval flow.
How it works: When spec.variant: TELECONTEXTMCP is set on an McpExposure, the operator resolves the Telecontext Application using a platform-level configuration (AGENTIC_TELECONTEXT_APPLICATION_ID, format: group--team--appName). From this, the operator:
- Looks up the Application CR to discover its zone and uses its
status.clientId(group--team--appName) as the consumer name. This is the name of the Application's gateway consumer and its ACL group, and the same value that subscriptions use for their ConsumeRoutes. - Adds the consumer to
spec.security.defaultConsumersof the Route that the Telecontext Application calls directly, giving it pre-authorized access without a ConsumeRoute or approval flow:- Telecontext in another zone: the proxy route in the Telecontext zone. The operator creates this proxy route even if no regular subscribers exist in that zone. The primary route does not get the consumer, because mesh-forwarded traffic arrives there as the
gatewayconsumer. - Telecontext in the exposure zone: the primary route. The primary route then also trusts the exposure zone's own IDP issuer, even without local subscribers.
- Telecontext in another zone: the proxy route in the Telecontext zone. The operator creates this proxy route even if no regular subscribers exist in that zone. The primary route does not get the consumer, because mesh-forwarded traffic arrives there as the
- Trusts the Telecontext zone's LMS issuer on the primary route if the Telecontext Application is in another zone, so mesh-forwarded traffic from the Telecontext zone is accepted
Subscribers in other zones keep their own proxy routes, which only allow the subscribers' ConsumeRoute consumers. If the Telecontext zone is also a subscriber zone, the operator creates a single proxy route for that zone.
If the Telecontext Application does not exist, is not ready, or has no client ID, the exposure is blocked. The operator does not change the existing routes and keeps them in the exposure status, so subscriptions keep their route reference. The exposure controller does not watch Applications, so a Telecontext Application that becomes ready later is picked up at the next periodic reconcile.
This mirrors how the legacy Java controlplane handled Telecontext integration: iterating all zones and creating proxy routes where the Telecontext Application is located, plus granting access via a dedicated RoutePermission (now replaced by the DefaultConsumers mechanism).
Why not a ConsumeRoute? A ConsumeRoute is namespace-scoped and goes through the approval flow. DefaultConsumers is a gateway-level bypass that is more appropriate for a trusted platform component that needs seamless, always-on access to TeleMCP servers across the whole platform.
McpExposure (variant: TELECONTEXTMCP)
│
├──▶ Resolve Application (from AGENTIC_TELECONTEXT_APPLICATION_ID)
│ └──▶ Get zone + status.clientId (e.g. mcp--telecontext--tcapp)
│
├──▶ AI Gateway Route (proxy, one per subscriber zone + Telecontext zone — if different)
│ ├──▶ upstream = exposure zone's AI Gateway
│ └──▶ spec.security.defaultConsumers:
│ - mcp--telecontext--tcapp (only on the proxy route in the Telecontext zone)
│
└──▶ AI Gateway Route (primary, on exposure zone)
├──▶ spec.security.defaultConsumers:
│ - gateway (if any proxy route exists)
│ - mcp--telecontext--tcapp (only if Telecontext is in the exposure zone)
└──▶ spec.security.trustedIssuers:
- exposure zone's IDP issuer (if local subscribers exist or Telecontext is in the exposure zone)
- LMS issuer of each proxy zone
The AGENTIC_TELECONTEXT_APPLICATION_ID value is injected at operator startup via environment variable and must be configured for environments that support the TELECONTEXTMCP variant.
Domain Interactions
- Rover domain — Creates
McpSpecificationwhich owns theMcpServer.McpExposureandMcpSubscriptionare also created from rover configuration. - Gateway domain — The Agentic operator creates
Route(primary, proxy) andConsumeRouteresources on the AI Gateway. - Admin domain — Zones provide the AI Gateway reference, preset URLs, and identity issuers used to wire up routes and mesh trust.
- Approval domain — Subscriptions trigger approval workflows before
ConsumeRouteis created. - Projector / ControlPlane API — The Projector syncs
McpServer,AgentCard,AgenticExposure(fromMcpExposure), andAgenticSubscription(fromMcpSubscription) into PostgreSQL, making the agentic catalogue and subscription state queryable via GraphQL. See ControlPlane API & Projector.
The AI Gateway
The AI Gateway is a regular zone gateway that an AI-typed preset points at:
# Excerpt: spec.gateways and spec.presets only. A complete Zone also needs
# visibility and identityProviders — see Environments and Zones below.
spec:
gateways:
- name: standard
admin:
identityProviderRef: primary
url: https://gateway-admin.example.com
- name: ai
admin:
identityProviderRef: primary
url: https://ai-gateway-admin.example.com
presets:
# Every zone needs an API preset: it is the representative profile for
# callers that carry no traffic type of their own.
- name: default
type: API
default: true
gatewayRef: standard
identityProviderRef: primary
urls:
- hostname: api.gateway.example.com
basePath: /
- name: ai
type: AI
default: true
gatewayRef: ai
identityProviderRef: primary
urls:
- hostname: ai.gateway.example.com
basePath: /
The type lives on the preset, not on the gateway: a gateway serves the union of the types of the
presets referencing it. The two presets above could equally point at the same gateway, which is
how you run agentic and API traffic on one gateway instance. The Agentic operator resolves its
routes through the AI preset of the zone; a zone with no AI preset rejects agentic exposures
and subscriptions during Rover validation. See
Environments and Zones for the full
traffic type reference and the rules the admission webhook enforces.