A remote MCP server should define a small set of scopes that match real permission boundaries, such as read versus write, and ask for only what a session needs. You advertise those scopes in your Protected Resource Metadata (`scopes_supported`). When a call needs more than the token carries, you return `403` with `error="insufficient_scope"` (RFC 6750 §3.1), which the MCP authorization spec uses as the trigger for step-up authorization. Users then get asked for broader access only when a tool actually needs it.
Designing the scope set
Map scopes to decisions a user would actually make, not to individual endpoints. The names below are illustrative, not a standard:
| Risk group | Example scope (illustrative) | Tools it unlocks |
|---|---|---|
| Read-only | `files:read` | list, search, fetch |
| Write | `files:write` | create, update |
| Destructive | `files:delete` | delete, purge |
The MCP spec describes `scopes_supported` as "intended to represent the minimal set of scopes necessary" for basic functionality, with more scopes "requested incrementally through the step-up authorization flow" (spec 2026-07-28, Authorization). Advertise the baseline there, and keep destructive scopes for step-up.
Where scopes show up
- PRM lists `scopes_supported` for the resource. Protected Resource Metadata in plain English covers the discovery side.
- The `WWW-Authenticate` challenge on a `401` or `403` can carry a `scope` parameter. Per the spec, clients prefer that value over `scopes_supported` when choosing what to request.
- The authorization server has to actually issue those scope strings. If your AS and PRM disagree, consent screens and enforcement drift apart.
The insufficient_scope response
When a valid token lacks a needed scope, the spec's example looks like this:
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope",
scope="files:read files:write",
resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"Keep `401` for a missing or invalid token and `403 insufficient_scope` for a valid token without enough permission. If you mix them up, clients loop on re-login instead of stepping up.
Pitfalls
- One scope per tool. That makes for long consent prompts and brittle configs. Group tools by risk instead.
- One god scope. That's simpler, but every connected client can then do everything.
- Enforcing only at connect time. Check scope on every tool call, because tokens get reused.
- PRM and AS lists that drift apart. Clients will request scopes your AS never grants.
- Audience checks skipped. Scope says what a token may do. Audience says which server it's for. See token audience and resource mismatch.
How to check it
Mint a token with only the read scope and call a write tool. You should get `403` with `insufficient_scope` and the needed scope in the challenge. Repeat with the write scope and confirm the call succeeds. Then run through the MCP auth checklist for the rest of the flow.
Where the kit fits
The MCP Starter Kit ($27) is built for teams putting OAuth-protected remote MCP servers in front of Cursor and Claude Connect. Soft path: start at /free; Cheat Sheet for the skim checklist mindset; kit when you want the auth-ready layout.
Soft next step
Write down your read, write, and destructive tool groups, then confirm PRM, your AS, and your 403 challenges all use the same scope strings. Soft ladder: /free, then the MCP Starter Kit ($27). Related: OAuth pillar.