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

# MCP Tool Approvals

> Add human-in-the-loop approval for sensitive MCP tools on the Gateway. Set validity windows and notify approvers via Email, Slack, PagerDuty or MS Teams.

Tool approval policies add human-in-the-loop control for sensitive MCP tools. When an agent or user calls a gated tool through the [MCP Gateway](/docs/ai-gateway/mcp/mcp-overview), the call is held, an approval request is created and designated approvers are notified. After a human approves, calls to that tool succeed for a configurable validity window - then a fresh approval is required.

<img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/policies-list.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=5c1d62a12904237ae8336b245cee5176" alt="AI Gateway Policies page showing MCP Tool Approval with the Policies tab, existing policies, and Add Approval Policy button" width="2266" height="652" data-path="images/docs/ai-gateway/mcp/tool-approval/policies-list.png" />

## When to use

Use tool approvals when a tool is too risky to run unattended - deleting records, sending external communications or mutating production infrastructure - but you still want agents to use it with a human in the loop.

For agent-turn pauses inside the Agent Harness (rather than Gateway policy), see [Human checkpoints](https://trueforge.dev/key-features/overview) in the TrueForge docs.

## How tool approvals work

1. **A gated `tools/call` arrives at the MCP Gateway.** The gateway matches the request against your tool approval policies by MCP server and tool name.
2. **An approval request is created.** The first call creates a request in `pending` state and notifies approvers through the policy's notification target. Repeated calls for the same tool and requester reuse that pending request.
3. **The caller gets an "approval pending" result.** The tool is not executed. The client can retry the same call later.
4. **Approvers are notified** with a link to the request.
5. **An approver approves or denies the request** from the TrueFoundry UI, optionally recording a reason.
6. **Approved calls flow through.** Once approved, the same call (same MCP server, tool, and requester) executes until the grant expires. Every result includes approval metadata in `_meta`.
7. **Grants expire.** After the validity window ends (**Once**, or a time-based duration), the grant lapses and the next call raises a new approval request. A denial does not permanently block the requester - the next call also raises a new request.

## Who can do what

| Action                                             | Who                                                                                              |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Create, update or delete tool approval policies    | Tenant administrators                                                                            |
| Approve or deny requests for a specific MCP server | Tenant administrators and collaborators on that MCP server with the **MCP Server Approver** role |

Tenant administrators can see every approval request in the tenant; MCP Server Approvers see requests for the servers they approve. To designate approvers, open the MCP server, go to **Collaborators** and add users or teams with the **MCP Server Approver** role. That role grants read access to the server plus the **Approve MCP Server Actions** permission - see [Manage User Roles & Permissions](/docs/platform/manage-user-roles-and-permissions#resource-level-roles-collaborators).

<img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/mcp-server-approver-collaborators.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=7a48eed2fed7be09070fc285be1ae708" alt="Update MCP Server drawer showing Collaborators with MCP Server Manager and MCP Server Approver roles" width="1740" height="1104" data-path="images/docs/ai-gateway/mcp/tool-approval/mcp-server-approver-collaborators.png" />

<Warning>
  If an MCP server referenced by a policy has no collaborators with the MCP Server Approver role, only tenant administrators can approve / deny requests.
</Warning>

## Create a tool approval policy

Each policy names the MCP servers it gates, the tool groups that require approval, the validity window for grants, and the notification target for approvers.

<Steps>
  <Step title="Open Tool Approval policies">
    Navigate to **AI Gateway → Policies → MCP Tool Approval** and create a new policy.
  </Step>

  <Step title="Pick tools that require approval">
    In **Pick specific tools that require approval**, select an MCP server and choose an [approval scope](#approval-scope): specific tool names, destructive tools only, or all tools. For each selected tool or group, set [approval validity](#approval-validity) (**Once** or a time-based duration).

    <img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/create-policy-pick-tools.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=634bf7b3577a294f26ac4b040dd26729" alt="New Approval Policy form showing calculator-r tools with multiply and divide selected, including Once and Time-based approval validity options" width="1364" height="1104" data-path="images/docs/ai-gateway/mcp/tool-approval/create-policy-pick-tools.png" />
  </Step>

  <Step title="Configure notifications">
    Choose a notification target so approvers are alerted when a request is raised.

    <img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/configure-notifications.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=f0c31ee8a24ff0ae25be931d55c3db4d" alt="Configure Notification Channel for Approvers with SlackBot selected and a Slack channel name configured" width="1726" height="1094" data-path="images/docs/ai-gateway/mcp/tool-approval/configure-notifications.png" />
  </Step>

  <Step title="Save and test">
    Save the policy, then call a gated tool through the MCP Gateway. Confirm callers receive the pending result and that approvers can approve or deny the request.
  </Step>
</Steps>

## Approval scope

Each tool group in a policy uses an `approval_scope` to decide which tools on the MCP server require approval:

| Scope                 | YAML value    | What it gates                                                       |
| --------------------- | ------------- | ------------------------------------------------------------------- |
| **Named tools**       | `named`       | Only the tools listed in `enabled_tools`                            |
| **Destructive tools** | `destructive` | Tools the MCP server marks as destructive (`destructiveHint: true`) |
| **All tools**         | `all`         | Every tool on the MCP server                                        |

When more than one scope could apply to the same tool, the gateway picks the **most specific** match, in this order:

**`named` > `destructive` > `all`**

So a named rule for `multiply` overrides a broader destructive or all-tools rule for that tool.

## Approval validity

After an approver approves a request, the grant stays valid according to `validity_mode`:

| UI option      | YAML                                          | Behavior                                                                               |
| -------------- | --------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Once**       | `type: count-based` with `count: 1`           | The approval covers a single execution. The next call needs a new approval.            |
| **Time-based** | `type: time-based` with `duration_in_minutes` | The approval covers calls for that many minutes (for example, 10 or 30), then expires. |

When multiple policies or tool groups gate the same tool, the **most restrictive** validity wins:

**Once > time-based 10 minutes > time-based 30 minutes**

Shorter (or single-use) grants always take precedence over longer ones.

## Review pending requests

Open **AI Gateway → Policies → MCP Tool Approval → Pending Requests** to approve or deny gated calls. Each request shows the tool, policy, requester, approvers, validity window, and tool arguments.

<img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/pending-requests.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=34760271be1352c5f8efd5244872fcd5" alt="Pending Requests tab listing divide and multiply approval requests with Approve and Deny actions" width="2186" height="1102" data-path="images/docs/ai-gateway/mcp/tool-approval/pending-requests.png" />

## What callers see

While a request is pending (or after it has been denied and re-raised), the gateway returns a successful JSON-RPC result whose content asks the caller to wait - the tool is **not** executed:

```json theme={"dark"}
{
  "content": [
    {
      "type": "text",
      "text": "Approval pending for request <request-id>. Awaiting human approval before execution. Reach out to user:alice@company.com."
    }
  ],
  "isError": false,
  "_meta": {
    "approval_status": "pending",
    "approval_request_id": "<request-id>",
    "reason": "Awaiting human approval before execution"
  }
}
```

<img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/try-tool-pending.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=7e48b5ae79e4483a9b8acc59ff7bd575" alt="Try Tool multiply playground showing approval_status pending and awaiting human approval message" width="1728" height="1108" data-path="images/docs/ai-gateway/mcp/tool-approval/try-tool-pending.png" />

<img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/try-tool-pending-divide.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=d6b256628f978099108c45b4eb587999" alt="Try Tool divide playground showing approval_status pending in the output panel" width="1342" height="1100" data-path="images/docs/ai-gateway/mcp/tool-approval/try-tool-pending-divide.png" />

Once approved, tool results pass through unchanged with approval metadata merged into `_meta`:

```json theme={"dark"}
"_meta": {
  "approval_status": "approved",
  "approval_request_id": "<request-id>"
}
```

Agents can inspect `_meta.approval_status` to distinguish a held call from a real tool result and retry later.

<img src="https://mintcdn.com/truefoundry/TDsZR66TsukTdJ05/images/docs/ai-gateway/mcp/tool-approval/try-tool-approved.png?fit=max&auto=format&n=TDsZR66TsukTdJ05&q=85&s=fcbb8cc257645fb1de4cebb75c2682fa" alt="Try Tool multiply playground showing approval_status approved and the multiplication result 103680" width="1354" height="1094" data-path="images/docs/ai-gateway/mcp/tool-approval/try-tool-approved.png" />

## Frequently asked questions

<AccordionGroup>
  <Accordion title="What happens when a grant expires?">
    The next call to the tool raises a fresh approval request and returns the "approval pending" result. Approvers are notified again, and the requester waits for a new decision.
  </Accordion>

  <Accordion title="Does denying a request block the user permanently?">
    No. A denial is recorded on that request, but the next call to the tool raises a new approval request. To durably block access to a tool, remove the user's access to the MCP server or disable the tool instead.
  </Accordion>

  <Accordion title="Are approvals shared between users?">
    No. Grants are scoped to the requester (user, virtual account or other identity) plus the specific MCP server and tool. Each requester needs their own approval.
  </Accordion>

  <Accordion title="Which requests does a policy affect?">
    Only MCP `tools/call` requests routed through the MCP Gateway for the servers and tools the policy names.
  </Accordion>

  <Accordion title="What counts as a destructive tool?">
    Tools the MCP server annotates with `destructiveHint: true`. Use `approval_scope: destructive` to require approval for all of them without listing each name.
  </Accordion>

  <Accordion title="What if two policies gate the same tool?">
    The most specific approval scope wins (`named` over `destructive` over `all`), and the most restrictive validity wins (**Once** over shorter time-based windows over longer ones).
  </Accordion>
</AccordionGroup>
