Skip to content
API Reference
Coming soon: fine-grain authorization is not yet generally available.
Admin
Unified Access Gateway

Fine-Grain Authorization

Write Policies that permit or deny individual MCP tool calls through a Unified Access Gateway

Fine-grain authorization lets you govern a Unified Access Gateway at the level of individual MCP tool calls. On every tool call the gateway forwards, Keycard evaluates your Zone’s active Access Policies to verify that the specific action is allowed, and you can configure different permissions for different sets of users. For example, permit read-only tools to everyone while restricting write or delete tools to a smaller cohort.

The gateway checks the MCP method and tool name against your Policies before forwarding the request to the upstream MCP server. A denial blocks the call before it ever reaches the upstream, and every decision is recorded in the audit log.

MCP activity maps onto Cedar actions as follows:

MCP activityCedar action
Tool call (tools/call)Keycard::Action::"mcp::tools/call::<tool-name>"
Prompt (prompts/get)Keycard::Action::"mcp::prompts/get::<prompt-name>"
Resource (resources/read)Keycard::Action::"mcp::resources/read::<resource-uri>"
Discovery (tools/list, prompts/list, resources/list, resources/templates/list)Actions in the Keycard::ActionGroup::"MCPProtocol" group
  1. Identify the tools to gate

    Reference each upstream MCP server’s documentation for the tool names it exposes. To construct the Cedar action for a tool, prepend mcp::tools/call:: to the tool name exactly as the upstream publishes it. For example, a tool named create_event becomes:

    Keycard::Action::"mcp::tools/call::create_event"

    Use the bare tool name from the upstream, not the <upstream>__ prefixed name shown in the gateway’s aggregated tool list, which is presentation only. Prompts and MCP resources follow the same pattern with the mcp::prompts/get:: and mcp::resources/read:: prefixes, as shown in the mapping table above.

  2. Permit sign-in and discovery

    Users need to sign in to the gateway and list its tools before any tool is called. Permit the gateway endpoint itself, and the MCPProtocol action group on each upstream. The group contains the discovery actions (mcp::tools/list, mcp::prompts/list, mcp::resources/list, and mcp::resources/templates/list). Establishing an MCP session (initialize) is handled by the gateway itself and is not gated by Policies.

    To find the identifiers, open the gateway’s Application details page in Keycard Console (Applications -> your gateway): the gateway’s own identifier is the MCP Access URL on the Application settings page, and the upstream identifiers are the MCP URLs of the Resources listed under Dependencies.

    @id("gateway-signin")
    @description("Allow users to sign in to and authorize the gateway")
    permit (
    principal is Keycard::User,
    action,
    resource
    ) when {
    resource.identifier == "https://<gateway-name>.<zone-id>.mcp.gateway.context/mcp"
    };
    @id("gateway-mcp-protocol")
    @description("Tool, prompt, and resource discovery on the upstreams")
    permit (
    principal is Keycard::User,
    action in Keycard::ActionGroup::"MCPProtocol",
    resource
    ) when {
    ["https://<first-upstream-mcp-url>/mcp",
    "https://<second-upstream-mcp-url>/mcp"].contains(resource.identifier)
    };
  3. Permit the baseline tools for all users

    Enumerate the read-only tools every authenticated user may call. For example, on a calendar upstream:

    @id("calendar-events-read")
    @description("Read-only event tools for all users")
    permit (
    principal is Keycard::User,
    action in
    [Keycard::Action::"mcp::tools/call::list_events",
    Keycard::Action::"mcp::tools/call::get_event",
    Keycard::Action::"mcp::tools/call::search_events"],
    resource
    ) when {
    resource.identifier == "https://<upstream-mcp-url>/mcp"
    };

    Tool calls that no Policy permits are denied: fine-grain authorization is default-deny, like every other Keycard enforcement point.

  4. Restrict sensitive tools to identity provider groups

    Gate mutating and destructive tools on the groups claim your identity provider issues, using context.subject_claims:

    @id("calendar-events-write")
    @description("Event mutations granted to Calendar Writers")
    permit (
    principal is Keycard::User,
    action in
    [Keycard::Action::"mcp::tools/call::create_event",
    Keycard::Action::"mcp::tools/call::update_event"],
    resource
    ) when {
    resource.identifier == "https://<upstream-mcp-url>/mcp" &&
    context has subject_claims &&
    context.subject_claims has groups &&
    context.subject_claims.groups.contains("Calendar Writers")
    };
    @id("calendar-events-delete")
    @description("Event deletion granted to Calendar Admins")
    permit (
    principal is Keycard::User,
    action == Keycard::Action::"mcp::tools/call::delete_event",
    resource
    ) when {
    resource.identifier == "https://<upstream-mcp-url>/mcp" &&
    context has subject_claims &&
    context.subject_claims has groups &&
    context.subject_claims.groups.contains("Calendar Admins")
    };
  5. Cover prompts and resources (optional)

    Upstream MCP prompts and resources are governed the same way, under the mcp::prompts/get:: and mcp::resources/read:: action prefixes:

    @id("prompts-code-review")
    @description("The code_review prompt template for Engineering")
    permit (
    principal is Keycard::User,
    action == Keycard::Action::"mcp::prompts/get::code_review",
    resource
    ) when {
    resource.identifier == "https://<upstream-mcp-url>/mcp" &&
    context has subject_claims &&
    context.subject_claims has groups &&
    context.subject_claims.groups.contains("Engineering")
    };
  6. Activate the Policies

    Activate the Policies in your Zone through your usual workflow on the Console -> Policies page. Changes take effect on the next tool call. There is nothing to deploy or restart on the gateway.

Sign in to the gateway as a user in one of the permitted groups and call a permitted tool; it succeeds as before. Then call a tool your Policies do not permit. The call is denied before reaching the upstream, and the client receives a policy error instead of a tool result.

Check Console -> Audit Log for both decisions. Every evaluation is logged with the user, the upstream, the tool name, and the Policy outcome, so denied calls carry the context of what was denied and why.

  • A tool call is denied that a Policy should allow. Confirm the action uses the bare tool name (mcp::tools/call::create_event), not the prefixed name from the aggregated tool list (calendar__create_event), and that resource.identifier matches the upstream MCP server URL exactly.
  • A group-gated Policy never matches. Verify your identity provider issues the groups claim and that the user is a member. The Policy’s context has subject_claims guards only prevent evaluation errors; a missing claim means the Policy silently does not match.
  • A user sees no tools from an upstream at all. Tool listing is gated by the MCPProtocol action group. Check the user is permitted that group on the upstream, then have them reconnect.