reader can list tools, agent-bot can call them, admin can do everything.
No auth configured? Nothing changes. With no keys set,
granted_scopes is None and every method is allowed. Scoped keys are 100% opt-in — existing setups keep working untouched.Quick Start
Serve with the keys file
How It Works
Each method has a required scope. The transport resolves the caller’s key togranted_scopes and the server checks it before running the handler.
| Step | What happens |
|---|---|
| Lookup | Transport matches the Bearer key to an APIKeyAuth entry |
| Resolve | The key’s scopes become granted_scopes |
| Check | The method’s required scope is compared against granted_scopes |
| Allow / Deny | Match → run handler; miss → -32001 insufficient_scope |
When no key store is configured,
granted_scopes is None and the check is skipped — allow all.Two Ways to Configure
Pick the shortest path for your setup.A) Single key (wildcard)
--api-key is wrapped as a single key with wildcard (*) scope, so it satisfies every method — the scalar path and the multi-key path share the same enforcement.
B) Multiple scoped keys
keys.json
| Field | Type | Description |
|---|---|---|
key | string | The Bearer token the client sends |
scopes | string[] | Scopes this key grants. "*" satisfies every requirement |
Scopes and Methods
Each MCP method maps to a required scope inOPERATION_SCOPES.
| Method | Required scope |
|---|---|
tools/list | tools:read |
tools/call | tools:call |
resources/list | resources:read |
resources/read | resources:read |
resources/subscribe | resources:subscribe |
prompts/list | prompts:read |
prompts/get | prompts:read |
sampling/createMessage | sampling:create |
tasks/create | tasks:write |
tasks/get | tasks:read |
tasks/list | tasks:read |
tasks/cancel | tasks:write |
| Scope | Grants |
|---|---|
tools:read | Read tool definitions |
tools:call | Execute tools |
resources:read | Read resources |
resources:subscribe | Subscribe to resource changes |
prompts:read | Read prompts |
prompts:execute | Execute prompts |
sampling:create | Create sampling requests |
tasks:read | Read tasks |
tasks:write | Create and manage tasks |
admin | Administrative access (implies all) |
* | Wildcard — satisfies every requirement |
Scopes are hierarchical:
tools:call implies tools:read, resources:subscribe implies resources:read, tasks:write implies tasks:read, and admin implies everything.Error Response
A request without the required scope returns a JSON-RPC error with code-32001.
scope="…" to know exactly which grant to request next.
Common Patterns
Match a key’s scopes to what each client actually needs.- Read-only monitor
- Agent caller
- Admin
- Rotate a key
A monitoring bot that only lists tools and reads status — no execution.
Best Practices
Grant the narrowest scopes that work
Grant the narrowest scopes that work
Start from
tools:read and add only what a client needs. Reserve * and admin for maintenance keys, not day-to-day clients.One key per client role
One key per client role
Give each bot or service its own key so you can rotate or revoke it without affecting others. Name keys by role (
reader, agent-bot, admin).Rotate without downtime
Rotate without downtime
Add the replacement key alongside the old one, point clients at the new key, then delete the old entry. No restart of clients is forced mid-rotation.
Keep the keys file out of version control
Keep the keys file out of version control
Treat
keys.json like any secret — store it outside the repo and restrict file permissions. Never commit real keys.Related
PraisonAI MCP Server
Run PraisonAI as an MCP server over STDIO or HTTP Stream.
MCP Authentication
API key and OAuth options for securing MCP.

