Define scopes
A scope is the string that ends up in a token's scope claim. When your MCP server validates a token, it checks whether the right scope is present before allowing a tool call. The Protect tab is where you define which scopes exist.
What the UI does
The Protect tab shows the current scope set for this resource server. Three default scopes are seeded on registration:
rs-<id>:tools:readrs-<id>:tools:writers-<id>:admin
You can Add custom scopes, Edit display names and descriptions, or Delete scopes that aren't used. Scope IDs (the strings) are immutable once created — to "rename" a scope, create a new one and migrate mappings.
Naming convention
The seeded pattern is <rs-prefix>:<resource>:<verb>:
rs-<uuid>namespaces the scope to this specific resource server. Tokens with this scope are bound to this server'saud; another server's SDK will reject them.- The middle segment (
toolshere) is the resource class. As your surface grows, add more —repos,issues,users, etc. - The verb at the end is the action level.
readvswriteis the floor; you can go finer.
The convention is just convention — the backend treats scope IDs as opaque strings. But picking something stable matters: scope IDs surface in tokens, audit logs, and your customers' OAuth client configurations. Renames are migrations.
For the design tradeoffs of read/write vs per-tool vs per-operation, see Scope design for MCP tools.
Where scopes come from at runtime
When a user authorizes an OAuth client, they're shown a consent screen listing the scopes the client is asking for. The user grants some subset; that subset is what gets baked into the access token's scope claim.
The Go SDK validates tokens against this claim. If your echo_write tool is mapped to rs-xyz:tools:write and the caller's token only has rs-xyz:tools:read, the SDK returns 403 insufficient_scope.
Adding a custom scope
Click Add scope on the Protect tab → pick a scope ID (e.g. rs-xyz:repos:admin) and a display name (what the consent screen shows users).
Custom scopes start unmapped. To make them functional, you need to map at least one tool to them on the Tools tab.
Deleting a scope
The UI shows a delete button only if no tools are currently mapped to that scope. If you've mapped tools, unmap them first.
Deleting a scope that's referenced in an active access policy (e.g. the default role grants it) emits a scope_deleted drift event — visible on the Monitor tab — so you'll see the impact in audit logs.
Auto-suggested scopes from the SDK
If you publish a manifest from the Go SDK with ToolScopeSuggestions populated, AuthSec stores those suggestions as suggested_scopes on each mcp_tools row. They show up in the UI as "SDK suggested: ..." hints when you're mapping. Suggestions never override admin choices — they're hints, not policy.
What changes after activation
Once the application is launched (state = ready), deleting or modifying a scope that's actively in use shows up as a drift event in the Monitor tab. Existing access tokens issued before the change keep their scope claim until they expire; the next token issuance uses the new policy.
Related
- Map tools to scopes — the next step
- Scope design for MCP tools — design tradeoffs
- Monitor drift and runtime — drift events on scope changes