# 18.7 Permission per tool (/building-ai-workers/securing-connectors/permission-per-tool)

---
type: Document
title: "18.7 Permission per tool"
description: "Roles become scopes, each tool needs its scopes, and a missing scope gets a 403 and a chance to step up."
status: stable
order: 318.07
ksor:
  owner: team:panaversity
  audience: [ public ]
  approval:
    by: process:panaversity
    at: 2026-11-02T18:20:57Z
chapter: "18"
part: III
expert_status: builder-only
concepts: [ "18.7" ]
objectives:
  - { id: CCDV-F.D7.S4, label: supporting }
  - { id: CCDV-F.D8.S2, label: supporting }
last_verified: 2026-11-02
sources:
  - id: mcp-authorization
    title: "Authorization, MCP specification 2026-07-28 (MCP, accessed 2026-11-02)"
    resource: https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization
generated:
  at: 2026-11-02T18:20:57Z
  by: process:panaversity
trust_tier: unverified
build_id: sha256:e1fbcb7d9a8f8b9b7cb96875022325c02c9ba4be94cef13b301cbd39a9edad85
dirty: true
ksor_version: 0.0.60
---

**In everyday life.** In an office building, a cleaner's badge opens every corridor but no office. A manager's opens her team's offices. A visiting auditor's opens the records room, and only during the audit. The badges are the same kind of card. What each opens depends on who holds it.

**What you will learn.** How what a person is in a company becomes permissions in a token, and what happens when a tool needs more than the token carries.

**Why it matters.** An outside checker should read invoices without seeing vendor bank details. Permission per tool is how one connector does both.

**One request, start to finish.** Brightline hires an outside auditor, Grace: someone from another firm who checks the accounts. She may read invoices, purchase orders and policies, but not vendor details, which include bank account endings and the AP team's private notes.

1. **Grace signs in and picks Brightline.** Her role in Brightline is `auditor`. The sign-in server turns that into one permission, `ap:read`.
2. **She asks about an invoice.** `get_purchase_order` needs `ap:read`. It runs.
3. **She asks about a vendor.** `find_vendor` also needs `ap:vendors.read`. The connector answers **403**, "you may not do this", and names every permission the call needs.
4. **Her app asks for more.** It goes back to the sign-in server, asking for both permissions. The sign-in server checks her role and does not grant `ap:vendors.read`.
5. **She gets a clear answer.** The app shows that her role does not allow vendor details. She asks Ana if she needs them.

### What is the difference between a role and a scope?

Two words that are easy to mix up:

- A role is what a person is inside one company: `owner`, `admin`, `member` or `auditor`. Role names are written in code type, so "a `member`" means the role, not just anyone in the company. A role belongs to a membership, and the company's `owner` or `admin` sets it. `owner` and `admin` can also add and remove people. `member` and `auditor` cannot.
- A scope is one named permission a token carries. Each tool in the connector needs one or more scopes.

The sign-in server turns a role into scopes when it makes a token. The connector never sees roles, only scopes. So it asks one question per call: "does this token carry every scope this tool needs?"

Brightline's mapping:

| Role | Scopes |
| --- | --- |
| `owner`, `admin`, `member` | `ap:read`, `ap:vendors.read` |
| `auditor` | `ap:read` |

| Tool | Scope it needs |
| --- | --- |
| `list_open_invoices`, `get_purchase_order`, `search_policy` | `ap:read` |
| `find_vendor` | `ap:read` and `ap:vendors.read` |

Every call needs `ap:read`, and `find_vendor` also needs `ap:vendors.read`.

### How does an app ask for more?

An app first asks for the scopes the connector's 401 names, the minimum for ordinary use, here `ap:read`. When a call needs more, the connector answers 403 and **should** list every scope that call needs, all at once, so the app asks only once. An app acting for a person **should** then **step up**: ask the sign-in server again for its old scopes plus the new ones, and retry. Ana, an `owner`, sees one more consent screen, approves, and continues. Grace, an `auditor`, is not granted the extra scope, and the app gives up instead of asking again and again.

Remember the two refusals as a pair: 401 means the token is missing, wrong or expired. 403 means a good token without the right permission.

**Read-only today.** Every Brightline tool reads. When Chapter 23 adds the first tool that acts, such as `schedule_payment`, it gets its own scope, `ap:pay`, which no role has until someone decides who may move money.

**At work.** The builder adds the `auditor` role to `docs/auth-spec.md` with Ana, as a manager: who may see vendor bank endings? Ana says everyone except auditors. The builder asks Claude Code for a test where an auditor's token calls `find_vendor` and must get 403 naming both scopes.

**The operating rule:** give each tool the scopes it needs, map each role to the fewest scopes it needs, ask for the minimum first, and answer a missing scope with a 403 that names every scope the call needs.

*The standards behind this concept: the MCP authorization specification's scope and step-up rules.[^mcp-authorization] Field guide [F4](field-guide-securing-connectors.md#f4-the-sign-in-in-detail) shows the exact 403.*

![Three columns joined by arrows. Left, roles: owner, admin, member, auditor. Middle, scopes: ap:read and ap:vendors.read, and a greyed future ap:pay that no role has. Right, tools: list_open_invoices, get_purchase_order and search_policy need ap:read. find_vendor also needs ap:vendors.read. Below, a step-up loop: a token with ap:read calls find_vendor, gets 403 naming ap:read and ap:vendors.read, the app asks the sign-in server again, and an owner or member is granted it while an auditor is not.](img/chapter-18-roles-scopes.png)

*Figure 18.10. Roles become scopes at the sign-in server. Every tool needs `ap:read`, and `find_vendor` also needs `ap:vendors.read`. A missing scope gets a 403 and a chance to step up.*

[^mcp-authorization]: Authorization, MCP specification 2026-07-28, MCP.
