> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/agentgateway/agentgateway/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP context

> CEL reference for the mcp context object — tools, prompts, and resources available for MCP authorization rules.

# MCP context

The `mcp` context object is available in CEL expressions when processing Model Context Protocol (MCP) requests. It identifies which MCP resource — a tool, prompt, or resource — is being accessed, and which backend target it belongs to.

<Note>
  The `mcp` object is only present when the request is an MCP request. Exactly one of `mcp.tool`, `mcp.prompt`, or `mcp.resource` will be set, depending on the type of MCP operation being performed.
</Note>

## `mcp.tool`

Present when the MCP request is invoking a tool (for example, `tools/call` or `tools/list`).

<ParamField path="mcp.tool.target" type="string">
  The name of the MCP backend target that provides the tool. This corresponds to the `name` field of the target in your Agentgateway configuration.

  ```cel theme={null}
  mcp.tool.target == "my-mcp-server"
  ```
</ParamField>

<ParamField path="mcp.tool.name" type="string">
  The name of the tool being invoked.

  ```cel theme={null}
  mcp.tool.name == "read_file"
  mcp.tool.name in ["read_file", "list_files", "get_info"]
  mcp.tool.name.startsWith("read_")
  ```
</ParamField>

## `mcp.prompt`

Present when the MCP request is accessing a prompt (for example, `prompts/get` or `prompts/list`).

<ParamField path="mcp.prompt.target" type="string">
  The name of the MCP backend target that provides the prompt.

  ```cel theme={null}
  mcp.prompt.target == "my-mcp-server"
  ```
</ParamField>

<ParamField path="mcp.prompt.name" type="string">
  The name of the prompt being accessed.

  ```cel theme={null}
  mcp.prompt.name == "summarize"
  mcp.prompt.name in ["summarize", "translate"]
  ```
</ParamField>

## `mcp.resource`

Present when the MCP request is accessing a resource (for example, `resources/read` or `resources/list`).

<ParamField path="mcp.resource.target" type="string">
  The name of the MCP backend target that provides the resource.

  ```cel theme={null}
  mcp.resource.target == "my-mcp-server"
  ```
</ParamField>

<ParamField path="mcp.resource.name" type="string">
  The name or URI of the resource being accessed.

  ```cel theme={null}
  mcp.resource.name == "config.json"
  mcp.resource.name.startsWith("public/")
  ```
</ParamField>

***

## Using MCP context in authorization rules

MCP authorization rules are CEL expressions configured under `mcpAuthorization.rules`. A request is allowed if **any** rule evaluates to `true`.

```yaml theme={null}
policies:
  mcpAuthorization:
    rules:
      # Allow anyone to call the 'echo' tool
      - 'mcp.tool.name == "echo"'
      # Only test-user can call 'add'
      - 'jwt.sub == "test-user" && mcp.tool.name == "add"'
      # Any user with a specific nested JWT claim can call 'printEnv'
      - 'mcp.tool.name == "printEnv" && jwt.nested.key == "value"'
```

***

## Examples

<AccordionGroup>
  <Accordion title="Allow access to specific tools">
    Allow a caller to invoke only a safe subset of tools:

    ```cel theme={null}
    mcp.tool.name in ["read_file", "list_files", "get_info"]
    ```
  </Accordion>

  <Accordion title="Restrict by backend target">
    Only allow access to tools on a specific MCP server:

    ```cel theme={null}
    mcp.tool.target == "trusted-server"
    ```

    Combine target and tool name for fine-grained control:

    ```cel theme={null}
    mcp.tool.target == "trusted-server" && mcp.tool.name == "read_file"
    ```
  </Accordion>

  <Accordion title="Allow access to public resources only">
    Allow any caller to read resources under a `public/` prefix:

    ```cel theme={null}
    mcp.resource.name.startsWith("public/")
    ```
  </Accordion>

  <Accordion title="Combine MCP context with JWT claims">
    Admins can call any tool; other users can only call read-only tools:

    ```cel theme={null}
    jwt.role == "admin" || mcp.tool.name.startsWith("read_")
    ```

    Allow a specific user to call a specific tool:

    ```cel theme={null}
    jwt.sub == "test-user" && mcp.tool.name == "add"
    ```

    Allow tool access based on a custom JWT claim:

    ```cel theme={null}
    mcp.tool.name == "printEnv" && jwt.nested.key == "value"
    ```
  </Accordion>

  <Accordion title="Allow a prompt for verified users">
    Only allow a named prompt for users with a verified identity:

    ```cel theme={null}
    mcp.prompt.name == "summarize" && has(jwt.sub)
    ```
  </Accordion>

  <Accordion title="Read-only access pattern">
    Allow read-only operations across tools and resources, deny writes:

    ```cel theme={null}
    mcp.tool.name in ["read_file", "list_files"] ||
    mcp.resource.name.startsWith("public/")
    ```
  </Accordion>

  <Accordion title="Restrict by source IP and MCP tool">
    Allow a sensitive tool only from internal networks:

    ```cel theme={null}
    cidr("10.0.0.0/8").containsIP(source.address) && mcp.tool.name == "execute_query"
    ```
  </Accordion>
</AccordionGroup>

***

## Real-world authorization configuration

The following example is taken from the Agentgateway authorization example. It shows how to configure multiple MCP authorization rules that combine `mcp` and `jwt` context:

```yaml theme={null}
policies:
  jwtAuth:
    issuer: agentgateway.dev
    audiences:
      - test.agentgateway.dev
    jwks:
      file: ./manifests/jwt/pub-key
  mcpAuthorization:
    rules:
      # Allow anyone to call 'echo'
      - 'mcp.tool.name == "echo"'
      # Only the test-user can call 'add'
      - 'jwt.sub == "test-user" && mcp.tool.name == "add"'
      # Any user with the claim nested.key == "value" can call 'printEnv'
      - 'mcp.tool.name == "printEnv" && jwt.nested.key == "value"'
```

<Tip>
  Rules are evaluated in order and a request is allowed as soon as any rule matches. Put the most permissive rules (like open tools) first and more restrictive rules last for clarity.
</Tip>
