Skip to main content

What is a scope?

If you've heard "OAuth scope" and nodded along without really getting it, this page is for you. By the end you'll understand what a scope is, why it exists, and how AuthSec uses scopes to decide whether a request gets through.

Start with the problem

You're building an MCP server. It does several things — let's say it talks to GitHub on a user's behalf:

  • Reads the user's repositories.
  • Reads the user's pull requests.
  • Comments on pull requests.
  • Merges pull requests.

A user, Alice, points an AI client at your server. The AI client wants to call merge_pr. Should it be allowed?

You could just say: "Alice authenticated. Whatever the AI client does is what Alice does." But that's reckless. Alice trusts the AI client to read her PRs; she didn't necessarily agree to let it merge them at 3 AM unsupervised. A leaked or compromised AI client could nuke her repository.

What you actually want is: "Alice authenticated, AND she explicitly agreed that this specific AI client can merge PRs."

That "AND she explicitly agreed" part — that's what a scope captures.

The definition

A scope is a named permission that a user explicitly grants to a specific AI client.

Three things in that sentence matter:

  1. Named — it's a string. repo.read, pr.merge, notes.write. The name is human-readable and stable; it shows up on the consent screen the user sees.
  2. A permission — it represents something the AI client is allowed to do (or to ask the server about). Permissions are coarse-grained by design: one scope can cover many tool calls.
  3. The user explicitly grants it to a specific AI client — when the user logs into AuthSec, they see exactly which scopes the AI client is asking for, in plain English, and they click approve or deny. The token the AI client gets carries only the scopes the user approved.

That last bit is what makes scopes more than just "permissions" — they're a consent receipt.

A scope's lifecycle, end to end

Watch what happens when Alice connects an AI client to your MCP server.

  1. You define the scopes on the AuthSec Application page. Let's say you declare four:

    • repo.read — read the user's repos and PRs.
    • pr.comment — comment on PRs.
    • pr.merge — merge PRs.
    • repo.admin — destructive things (delete the repo, force-push to main).
  2. You map each tool to one or more scopes.

    • list_repos requires repo.read.
    • read_pr requires repo.read.
    • comment_pr requires pr.comment.
    • merge_pr requires pr.merge.
    • delete_repo requires repo.admin.
  3. Alice points an AI client at your server. The AI client says to AuthSec: "I want to be able to call list_repos and read_pr and comment_pr and merge_pr. Please get me a token with repo.read pr.comment pr.merge."

  4. AuthSec shows Alice a consent screen listing those three scopes with their human-readable descriptions:

    • "Read your repositories and pull requests"repo.read
    • "Comment on your pull requests"pr.comment
    • "Merge your pull requests"pr.merge

    Alice approves all three but you could imagine her unchecking the merge one. Whatever she approves goes into the token.

  5. The AI client gets a token carrying scope: "repo.read pr.comment pr.merge".

  6. The AI client calls merge_pr with that token. Your MCP server's AuthSec SDK checks: the tool requires pr.merge, the token has pr.merge → allowed.

  7. The AI client calls delete_repo with the same token. The SDK checks: the tool requires repo.admin, the token does not have repo.admin → denied, 403 with scope_insufficient.

    Alice never agreed to that. The token can't do it.

That's the whole loop. The scope is the unit of agreement between Alice and the AI client; the SDK enforces it on every call.

Why scopes — and not just "the user has access"

Scopes solve a real problem: the same user might trust different AI clients differently.

  • Alice trusts Claude Desktop on her laptop to do everything.
  • Alice trusts a public agent she's evaluating to only read her PRs.
  • Alice trusts a CI bot to comment on PRs but never merge them.

Without scopes, there's only one trust level per user: full. With scopes, the same user can grant different access to different AI clients, and revoke any one of them without losing the others.

This is why OAuth tokens carry scopes and not just "is the user authorized." The token is a bounded delegation of the user's authority to one specific client.

How AuthSec uses scopes

The pieces fit together like this:

  • You define the scopes on the Application detail page (or via the define-scopes lifecycle step). Each scope has an ID (repo.read) and a human description ("Read your repositories").
  • You map tools to scopes on the Tools tab. Each tool says "you need at least one of these scopes to call me."
  • You bind scopes to roles via the access policy. Roles like "Free User" get repo.read; "Pro User" gets repo.read pr.merge; "Admin" gets everything.
  • At runtime, when a user authenticates, AuthSec figures out their effective scopes (union of their role bindings, intersected with what the AI client asked for and what the Application supports) and bakes them into the token.
  • The AuthSec SDK on your server checks the token's scopes against the tool's required scopes on every request. Match → run. No match → 403.

You configure all of this once. The SDK enforces it forever.

What a scope is not

A few common confusions worth heading off:

  • A scope is not a role. A role is a bundle of scopes assigned to a user. Pro User is a role; repo.read is a scope. Users get roles; AI clients get tokens with scopes.

  • A scope is not a permission on a specific record. Scopes are coarse — repo.read lets you read any repo the user has access to. Per-record access (Alice can read repo A but not repo B) is handled by your application logic, not by the scope. Scopes answer "can this AI client do this kind of thing?"; your app answers "on this particular record?"

  • A scope is not the same as an API endpoint. Mapping one scope per endpoint creates a permission matrix nobody will manage. Map one scope per intent — "comment on PRs" — not one per HTTP route.

  • A scope is not an ACL. ACLs change per-record at runtime; scopes are fixed at consent time and baked into the token until it expires. Use scopes for "can the AI client do this", ACLs for "on whose data".

Picking your scopes

This is the part where the rubber meets the road. Done well, scope design saves you from a migration in 6 months. Done badly, you end up with mcp.full everywhere.

See Scope design for MCP tools for the decision tree, the matrix, and the naming conventions that wear well.