Control access or route traffic based on verified claims in a JSON web token (JWT). To learn more about JWTs, see the JWT Overview.

About tool access

In this guide, you learn how to apply CEL-based RBAC rules to your MCP server backend to control access to MCP tools.

The following diagram shows the components that are involved when performing JWT validation and MCP tool authorization with MCP servers:

sequenceDiagram
    autonumber
    Client->>+Agentgateway: Send request with JWT
    Agentgateway->>Agentgateway: Validate JWT token
    Agentgateway->>Agentgateway: Authorize access to MCP server
    Agentgateway->>+MCP: Forward request
    MCP->>+MCP: Authorize access to tools
    MCP-->>Client: Show tools
  1. The MCP client, such as the MCP inspector tool, sends a request to the agentgateway proxy with the JWT token in the Authorization header.
  2. The agentgateway validates the JWT with the JWKS server that you define in a glooJWT policy in the GlooTrafficPolicy resource. This policy is applied to the agentgateway proxy.
  3. If the GlooTrafficPolicy further defines RBAC rules, such as to only grant access for JWT tokens with certain claims, agentgateway validates these claims and either grants or denies access.
  4. If successfully validated and authorized, the agentgateway proxy forwards the request to the MCP backend.
  5. The MCP backend verifies access to the MCP server tools. By default, all tool access is allowed. To limit tool access, you create another GlooTrafficPolicy with the CEL expression that must be matched to view a specific tool. Consider the following sample CEL expressions:
    • 'mcp.tool.name == "add_issue_comment"': Users can only view the add_issue_comment tool. All other tools are hidden.
    • 'jwt.sub == "alice"': Only JWT tokens with a sub=alice claim can access tools. Because no CEL expression is provided for the type of tool, the JWT token with this claim can see all the tools that are exposed on the MCP server.
    • 'jwt.sub == "alice" && mcp.tool.name == "add_issue_comment"': JWT tokens with the sub=alice claim can access the add_issue_comment tool. Access to all other tools is denied.
  6. The MCP server returns the tools that were authorized to access.

Before you begin

  1. Set up an agentgateway proxy.
  2. Follow the steps to connect to the remote GitHub MCP server via HTTPS.

View MCP tools

  1. Create a GlooTrafficPolicy with your JWT validation rules and apply it to the agentgateway proxy that you created before you began. To learn more about how JWT validation works in the agentgateway proxy and the details of this policy, see the secure access to an MCP server guide.

      kubectl apply -f- <<EOF
    apiVersion: gloo.solo.io/v1alpha1
    kind: GlooTrafficPolicy
    metadata:
      name: jwt
      namespace: gloo-system
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: agentgateway
      glooJWT:
        beforeExtAuth:
          providers:
            selfminted:
              issuer: solo.io
              jwks:
                local:
                  key: '{"keys":[{"kty":"RSA","kid":"solo-public-key-001","use":"sig","alg":"RS256","n":"AOfIaJMUm7564sWWNHaXt_hS8H0O1Ew59-nRqruMQosfQqa7tWne5lL3m9sMAkfa3Twx0LMN_7QqRDoztvV3Wa_JwbMzb9afWE-IfKIuDqkvog6s-xGIFNhtDGBTuL8YAQYtwCF7l49SMv-GqyLe-nO9yJW-6wIGoOqImZrCxjxXFzF6mTMOBpIODFj0LUZ54QQuDcD1Nue2LMLsUvGa7V1ZHsYuGvUqzvXFBXMmMS2OzGir9ckpUhrUeHDCGFpEM4IQnu-9U8TbAJxKE5Zp8Nikefr2ISIG2Hk1K2rBAc_HwoPeWAcAWUAR5tWHAxx-UXClSZQ9TMFK850gQGenUp8","e":"AQAB"}]}'
    EOF
      
  2. Save the JWT tokens for the users Alice and Bob. You can optionally create other JWT tokens by using the JWT generator tool. Note that to use JWTs with agentgateway proxies, make sure that the JWTs return Key ID (kid) and expiration date (exp) values in the JWT header.

    1. Save the JWT token for Alice. Alice works in the dev team.

        eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImFsaWNlIiwidGVhbSI6ImRldiIsImV4cCI6MjA3NDI3NDg4NCwibGxtcyI6eyJvcGVuYWkiOlsiZ3B0LTMuNS10dXJibyJdfX0.il5Rjsad65jpQR_pyRzBdEKFSj-ERmBf4K2VksvGvswWVv4n79lYERslr4KCECuiz9y_T-xUiQ9IkhW3YHzl5zo1kajhhIg7Nhnl1AvAqODbnF6wYpLRk0Npna_2T6lK3Yj54qQGi6vXG3IMRpo1_o2DrbdlKx2k_WFegCoQyyYazb4z3ZXfWvTiWqQDJA5wWcM3-jKzAWfNM8zgZWa-1BeAHDvpLcfWtuXEGSjkdCW0FQJOTjgIEqACnnXb2Jio0tWgelh9hDPILI-tvanj3iKCjpf3uF6g8QWSBNoVFfu7F1jJgj5Aj1sX8AV-CQVu2aQx3EHRZ1mL_3w3qSRWPw
        
    2. Save the JWT token for Bob. Bob works in the ops team.

        eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImJvYiIsInRlYW0iOiJvcHMiLCJleHAiOjIwNzQyNzQ5NTQsImxsbXMiOnsibWlzdHJhbGFpIjpbIm1pc3RyYWwtbGFyZ2UtbGF0ZXN0Il19fQ.GF_uyLpZSTT1DIvJeO_eish1WDjMaS4BQSifGQhqPRLjzu3nXtPkaBRjceAmJi9gKZYAzkT25MIrT42ZIe3bHilrd1yqittTPWrrM4sWDDeldnGsfU07DWJHyboNapYR-KZGImSmOYshJlzm1tT_Bjt3-RK3OBzYi90_wl0dyAl9D7wwDCzOD4MRGFpoMrws_OgVrcZQKcadvIsH8figPwN4mK1U_1mxuL08RWTu92xBcezEO4CdBaFTUbkYN66Y2vKSTyPCxg3fLtg1mvlzU1-Wgm2xZIiPiarQHt6Uq7v9ftgzwdUBQM1AYLvUVhCN6XkkR9OU3p0OXiqEDjAxcg
        
  3. Get the agentgateway address.

  4. From the terminal, run the MCP Inspector command. Then, the MCP Inspector opens in your browser. If the MCP inspector tool does not open automatically, run mcp-inspector.

      npx modelcontextprotocol/inspector#0.16.2
      
  5. From the MCP Inspector menu, connect to the MCP server with Alice’s JWT token.

    • Transport Type: Select Streamable HTTP.
    • URL: Enter the agentgateway address, port, and the /mcp-github path. If your agentgateway proxy is exposed with a LoadBalancer server, use http://<lb-address>:8080/mcp-github. In local test setups where you port-forwarded the agentgateway proxy on your local machine, use http://localhost:8080/mcp-github.
    • Expand the Authentication section in the MCP Inspector menu. Enter the following details in the API Token Authentication card:
      • Header Name: Enter Authorization.
      • Bearer Token: Enter the JWT token for Alice.
          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImFsaWNlIiwidGVhbSI6ImRldiIsImV4cCI6MjA3NDI3NDg4NCwibGxtcyI6eyJvcGVuYWkiOlsiZ3B0LTMuNS10dXJibyJdfX0.il5Rjsad65jpQR_pyRzBdEKFSj-ERmBf4K2VksvGvswWVv4n79lYERslr4KCECuiz9y_T-xUiQ9IkhW3YHzl5zo1kajhhIg7Nhnl1AvAqODbnF6wYpLRk0Npna_2T6lK3Yj54qQGi6vXG3IMRpo1_o2DrbdlKx2k_WFegCoQyyYazb4z3ZXfWvTiWqQDJA5wWcM3-jKzAWfNM8zgZWa-1BeAHDvpLcfWtuXEGSjkdCW0FQJOTjgIEqACnnXb2Jio0tWgelh9hDPILI-tvanj3iKCjpf3uF6g8QWSBNoVFfu7F1jJgj5Aj1sX8AV-CQVu2aQx3EHRZ1mL_3w3qSRWPw
          
    • Click Connect.
  6. From the menu bar, click the Tools tab. Then from the Tools pane, click List Tools. Verify that you can see a list of tools.

Limit tool access

  1. Create a TrafficPolicy with your RBAC rules for the MCP tools. In the following example, you only want to allow access to the add_issue_comment tool if the JWT has a sub of alice.

      kubectl apply -f- <<EOF
    apiVersion: gateway.kgateway.dev/v1alpha1
    kind: TrafficPolicy
    metadata:
      name: jwt-rbac
      namespace: gloo-system
    spec:
      targetRefs:
        - group: gateway.kgateway.dev
          kind: Backend
          name: github-mcp-backend
      rbac:
        policy:
          matchExpressions:
            - 'jwt.sub == "alice" && mcp.tool.name == "add_issue_comment"'
    EOF
      
  2. Go back to the MCP inspector tool, and re-connect with Alice’s token. From the Tools tab, click Clear. Then click List Tools. Verify that you can now only see the add_issue_comment tool that you authorized in your TrafficPolicy.

  3. Go back to the MCP inspector tool. In the Authentication > API Token Authentication > Bearer Token field, enter the JWT token for Bob. Then, click Re-connect.

      eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImJvYiIsInRlYW0iOiJvcHMiLCJleHAiOjIwNzQyNzQ5NTQsImxsbXMiOnsibWlzdHJhbGFpIjpbIm1pc3RyYWwtbGFyZ2UtbGF0ZXN0Il19fQ.GF_uyLpZSTT1DIvJeO_eish1WDjMaS4BQSifGQhqPRLjzu3nXtPkaBRjceAmJi9gKZYAzkT25MIrT42ZIe3bHilrd1yqittTPWrrM4sWDDeldnGsfU07DWJHyboNapYR-KZGImSmOYshJlzm1tT_Bjt3-RK3OBzYi90_wl0dyAl9D7wwDCzOD4MRGFpoMrws_OgVrcZQKcadvIsH8figPwN4mK1U_1mxuL08RWTu92xBcezEO4CdBaFTUbkYN66Y2vKSTyPCxg3fLtg1mvlzU1-Wgm2xZIiPiarQHt6Uq7v9ftgzwdUBQM1AYLvUVhCN6XkkR9OU3p0OXiqEDjAxcg
      
  4. From the Tools tab, click Clear. Then click List Tools.

    Verify that you cannot see any tools. Bob’s JWT token does not contain the sub=alice claim that is required to access the add_issue_comment tool. Because no other matching condition is found in the RBAC rules that you defined in the TrafficPolicy, access to all tools is denied.

Cleanup

You can remove the resources that you created in this guide.
  kubectl delete Backend github-mcp-backend -n gloo-system
kubectl delete BackendTLSPolicy github-mcp-backend-tls -n gloo-system
kubectl delete HTTPRoute mcp-github -n gloo-system
kubectl delete GlooTrafficPolicy jwt -n gloo-system
kubectl delete TrafficPolicy jwt-rbac -n gloo-system