The following example demonstrates using a Kuadrant AuthPolicy custom resource (CR) with Common Expression Language (CEL) to implement role-based access control. You can use this procedure as a general pattern for applying the authorization specific to your use case. The {mcpg} supports Istio or Gateway API compatible authorization mechanisms.
-
You installed {mcpg}.
-
You installed {prodname}.
-
You configured a
Gatewayobject with anmcplistener and anmcpslistener. Themcpslistener is required for internaltools/callrouting and authorization. -
You completed authentication procedures, including creating an
AuthPolicyCR on themcplistener. -
You configured your identity provider to include
groupandroleclaims in JSON Web Tokens (JWT). -
The identity provider client IDs match the namespaced
MCPServerRegistrationname in the format<namespace>/<mcpserverregistration_name>.
-
Ensure that your identity provider includes the required
groupandroleclaims in the issued JWTs. In the following example, {keycloak} is used:Example issued OAuth token claims:{ "resource_access": { "mcp-ns/arithmetic-mcp-server": { "roles": ["add", "sum", "multiply", "divide"] }, "mcp-ns/geometry-mcp-server": { "roles": ["area", "distance", "volume"] } } }-
The
"mcp-ns/arithmetic-mcp-server"specification must match the namespaced name of theMCPServerRegistrationCR in the format{namespace}/{name}. For example, if yourMCPServerRegistrationCR is namedarithmetic-mcp-serverand is applied in themcp-nsnamespace, the {keycloak} client ID must bemcp-ns/arithmetic-mcp-server. -
The
"roles": ["add", "sum", "multiply", "divide"]parameter and values specify the roles representing the allowed tools.
-
-
Configure tool-level authorization by creating an
AuthPolicyCR that enforces tool-level access control on themcpslistener, as shown in the following example:ImportantThe authorization
AuthPolicyCR must target themcpslistener, not themcplistener. Themcplistener only handles public traffic and has an authentication-onlyAuthPolicyCR.Example tool-level access control AuthPolicyapiVersion: kuadrant.io/v1 kind: AuthPolicy metadata: name: <mcp_tool_auth_policy> namespace: <gateway_system> spec: targetRef: group: gateway.networking.k8s.io kind: Gateway name: <mcp_gateway> sectionName: <mcps> rules: authentication: 'sso-server': jwt: issuerUrl: https://<keycloak.example.com>/realms/mcp authorization: 'tool-access-check': patternMatching: patterns: - predicate: | request.headers['x-mcp-toolname'] in (has(auth.identity.resource_access) && auth.identity.resource_access.exists(p, p == request.headers['x-mcp-servername']) ? auth.identity.resource_access[request.headers['x-mcp-servername']].roles : []) response: unauthenticated: headers: 'WWW-Authenticate': value: Bearer resource_metadata=http://<mcp.example.com:8001>/.well-known/oauth-protected-resource body: value: | { "error": "Unauthorized", "message": "MCP Tool Access denied: Authentication required." } unauthorized: body: value: | { "error": "Forbidden", "message": "MCP Tool Access denied: Insufficient permissions for this tool." }
-
Replace
metadata.name:with the name of theAuthPolicy. -
Replace
metadata.namespace:with the namespace where theAuthPolicyCR is applied. -
Replace
spec.targetRef.name:with the name of theGatewayCR. -
The
spec.targetRef.sectionName:value must bemcps, which is the internal listener fortool/callauthorization. This listener must exist on yourGatewayobject. -
Authentication: Validates the JWT token using the configured issuer URL. Replace
<keycloak.example.com>with your identity provider hostname. -
Authorization Logic: CEL expression checks if user’s roles allow access to the requested tool
-
CEL Breakdown:
-
request.headers['x-mcp-toolname']: The name of the requested MCP tool, stripped from prefix. -
request.headers['x-mcp-servername']: The namespaced name of the MCP server matching theMCPServerRegistrationCR. -
auth.identity.resource_access: The JWT claim containing all roles representing each allowed tool the user can access, grouped by MCP server.
-
-
Response handling: Custom
401and403responses for unauthenticated and unauthorized access attempts.
-
-
Apply the AuthPolicy CR by running the following command:
$ oc apply -f <mcp_tool_auth_policy.yaml>-
Replace
<mcp_tool_auth_policy.yaml>with the name of theAuthPolicyYAML filename.
-
-
Monitor authorization decisions by checking the
AuthPolicyCRstatuswith the following command:$ oc get authpolicy <mcp_tool_auth_policy> -n <gateway_system> -o jsonpath='{.status.conditions[?(@.type=="Enforced")].status}'Example outputTrue -
Check the authorization logs by running the following command:
$ oc logs -n mcp-system -l app.kubernetes.io/name=mcp-gateway