Configure OAuth clients for AI agents and MCP servers
Consul Enterprise uses dynamic client registration (DCR) to register OAuth clients for AI agents and Model Context Protocol (MCP) servers in the service mesh. When an AI agent calls the next service, the mesh proxy uses the agent's client to exchange the caller's token for an on-behalf-of token bound to that service.
A service whose role is inference-model does not get an OAuth client. Refer to the inference_model block on the service definition for its fields.
Consul registers clients with IBM Verify. Each client authenticates with private_key_jwt and an inline JSON Web Key Set (JWKS).
Enterprise
This feature requires Consul Enterprise. Refer to the Enterprise feature matrix for additional information.
Requirements
Complete the following steps before you register an ai-agent or mcp-server:
Enable the
consul-aifeature gate. Consul rejects a service registration that contains anaiblock while the gate is disabled. The followingconsul operator feature setcommand enables the gate:$ consul operator feature set consul-ai enabled Name Stage Desired Effective Eligible Source Reason Min Version Policy Index Status Index consul-ai experimental true true true operator operator-enabled 2.1.0 25 25Confirm that the
Effectivecolumn showstrue. If it showsfalse, check theReasoncolumn. Refer to Feature gate states for more information.Create exactly one access control list (ACL) auth method with
Typeset tooidcandEnableServiceDCRset totrue. The flagged method is the cluster identity provider. Consul waits to register clients when the cluster has no flagged method or more than one flagged method. Refer toEnableServiceDCR.Configure the following settings on the flagged auth method:
- Set
OIDCDiscoveryURL,OIDCClientID, andOIDCClientSecret. Consul usesOIDCClientIDandOIDCClientSecretas the bootstrap client that registers service clients.OIDCClientAssertioncannot replaceOIDCClientSecretfor this bootstrap. Consul rejects the auth method for dynamic client registration when the secret is empty. - Set
JWTSupportedAlgsto["ES256"]. IBM Verify signs tokens with ES256, and this field defaults to RS256. - Set a nonzero
MaxTokenTTL. This field is outsideConfig, and Consul rejects anoidcmethod when it is unset. The service registration example uses1h. - You can omit
AllowedRedirectURIswhen you use the method only for service registration.
- Set
Register the service with an
aiblock whoseroleisai-agentormcp-server. You can set the block in a service definition file, the catalog register API, or the agent service register API.
Roles that receive OAuth clients
The ai.role value selects which services receive a client.
role | Sub-block | On-behalf-of credential |
|---|---|---|
ai-agent | agent | Yes. The agent exchanges tokens for outbound calls. |
mcp-server | mcp_server | No. The server is an audience for callers. |
Set the one sub-block that matches role. inference-model is not a client role. An inference-model registration requires the same feature gate and does not create a client or a key-value record. Configure it on the service definition.
Client registration limitations
Client registration has the following limitations:
- Consul registers clients only for services in the
defaultnamespace anddefaultpartition. - Consul does not register a second client for the sidecar proxy.
- Consul rejects an agent configuration block named
oauth.iam. Configure the identity provider with the auth method instead.
On-behalf-of token audiences
An on-behalf-of audience is the identity of the next service in the call. Consul builds that map from explicit proxy upstreams in the default namespace, default partition, and local datacenter. For each of those upstreams, Consul uses the destination service's registered client ID. You do not set an audience list on the service definition.
Consul does not add an audience for a wildcard upstream, a centrally configured upstream, a prepared query, a peered service, a service in another datacenter, or a service outside the default namespace and partition.
MCP calls from an AI agent
Set agent.mcp and register a sidecar proxy for the agent. The local agent copies the ai-agent block onto that sidecar. Consul then opens a loopback listener at http://127.0.0.1:<mcp.port>/mcp. The port is 15101 when unset.
A catalog registration of the application service creates the OAuth client and does not open this listener. Consul does not copy an inference-model or mcp-server block onto a sidecar.
The listener allows a tool call when a service intention names the MCP server as the destination and the agent as the source. The allow permission must set the HTTP path to exactly /mcp and match the x-mcp-tool header with Exact or Regex. The header value is the tool name.
A Regex match is not a general regular expression. Consul expands only one anchored alternation of literal tool names, such as ^(hotel\.search|flight\.search)$. Any other pattern is one literal tool name, so ^billing\..*$ matches a tool named billing..*.
A <server>__<tool> prefix names the MCP server. Without that prefix, the intention destination is the server. Consul ignores permissions that use a different path or that omit an x-mcp-tool exact or regex match.
Set the connect proxy mode to transparent when agent.mcp is set. Consul rejects the connect proxy when agent.mcp is set and mode is not transparent. An intention that allows a tool does not add that MCP server as an on-behalf-of audience. Add an explicit upstream for each server whose client ID must be an audience.
When agent.mcp is set, Consul installs the governance interceptor as the first filter on this listener. The port is 21101 when interceptor.port is unset. A process must be listening on that port. Consul rejects every tool call when nothing is listening.
Set mcp.hitl to install human-in-the-loop approval. Approval then runs only for requests that include the x-mcp-hitl header. Requests without the header skip approval. Consul applies mcp.hitl.approval_timeout to the requests that require approval. The default is 60s. Consul rejects the call when the approval server is missing or unreachable.
To allow billing-agent to call the billing.lookup tool on billing-tools, first set the destination protocol to http. The default protocol is tcp, and Consul rejects a layer 7 (L7) permission for a TCP destination. Refer to service defaults.
The following service defaults configuration entry sets the protocol for billing-tools:
Kind = "service-defaults"
Name = "billing-tools"
Protocol = "http"
The following service intentions configuration entry allows billing-agent to call the billing.lookup tool:
Kind = "service-intentions"
Name = "billing-tools"
Sources = [
{
Name = "billing-agent"
Permissions = [
{
Action = "allow"
HTTP = {
PathExact = "/mcp"
Header = [
{
Name = "x-mcp-tool"
Exact = "billing.lookup"
}
]
}
}
]
}
]
Client registration state
Consul stores the registration record in the key-value store at oauth/<service>/state. <service> is the service name, not the service ID. The state field is one of the following:
state | Meaning |
|---|---|
PENDING | Registration has started and is not finished. If the identity provider rejects the client, Consul retries and does not write a separate failure state. |
ACTIVE | The identity provider accepted the client. Delivery of the on-behalf-of credential to an ai-agent can still be in progress. |
ROTATING | Consul is rotating the client key. |
REVOKING | The service was deregistered and Consul is removing the client. |
The record is an ordinary key-value entry and includes the OAuth client credential, including the private key. GET /v1/kv/oauth/<service>/state returns that entry to any caller that can read the key. When ACLs are disabled, every caller can read it. A management token can read it even when another policy denies the prefix. Do not grant key:read or key:write on oauth/ to workload tokens. A token with key:write can replace the client ID and private key. A client agent loads this credential with a KV read that carries no ACL token. Denying key:read on oauth/ to the anonymous token can prevent that load.
API
Use the following endpoints to configure the identity provider and register AI services:
- Update a feature gate to enable the
consul-aifeature gate. - Create an ACL auth method to create the
oidcauth method withEnableServiceDCRset totrue. - Register a catalog entity to register a service with an
AIobject. - Register an agent service to register a service with an
AIobject on the local agent.