Grant the scopes each tool declares
This check verifies that the token from a sign-in holds every scope that your protected tools declare they need.
Check id tool_scopes (tool scopes). Results:
Why it matters
Section titled “Why it matters”A tool can declare the scopes it needs, for example "securitySchemes": [{"type": "oauth2", "scopes": ["orders:read"]}]. If the token lacks one of them, the server refuses the call, and the
user has to sign in again before the tool works.
- ChatGPT reads the declared scopes so the consent screen shows the permissions it will request (OpenAI: Triggering authentication UI).
- Claude requests the scopes in your
401challenge’sscopeparameter, or the protected resource metadata’sscopes_supportedwhen there is none (Claude: PKCE and requested scopes). When a call later fails with403 insufficient_scope, it asks the user to sign in again with more scope, a step-up (Claude: Ask for more scope with 403). - The MCP authorization specification lets the challenge’s scopes differ from
scopes_supportedand asks clients to request more scope incrementally through step-up (Scope selection strategy).
Every missing scope is one more sign-in for your users in the middle of a task, or a tool that never works when the authorization server will not grant the scope.
What MCP Tower checks
Section titled “What MCP Tower checks”- Which scopes MCP Tower requests. The first sign-in asks for the scope in your
401challenge plus everyoauth2scope declared by the tools it saw without a token. With neither, it falls back toscopes_supportedin your protected resource metadata. This starts from the same sources as Claude and adds the declared scopes, so one sign-in covers every tool an agent can see. - Which scopes were granted. MCP Tower reads the
scopefield of the token response. When the authorization server leaves it out, the requested scopes count as granted, as RFC 6749 §5.1 allows. - What each tool needs. For each tool whose sign-in is required or optional, MCP Tower collects
the
oauth2scopes fromsecuritySchemes(top level, or in_meta) and fromauthorization.scopes. Tools declaring no scopes need nothing beyond the token. - A signed-in scan in which every required scope was granted is
pass. Any missing scope iswarn, and the tool shows “Needs scope” in the tool list. Without a successful signed-in scan the check isskipped.
Tools that appear only after sign-in are a common cause: their scopes were unknown when the first sign-in started. See hidden tools.
Results
Section titled “Results”| Status | Message | Meaning | Fix |
|---|---|---|---|
| pass | Every protected tool’s declared scopes were granted. | Every protected tool can be called with the token. | |
| warn | Some tools need scopes the token was not granted: <tool>: <scope>; …. | Those tools will be refused until the user signs in with the missing scopes. | Sign in with the scopes |
| skipped | Needs a signed-in scan. | No token, or the signed-in pass failed; see token accepted. |
The next step for the warning is: “Sign in again with scopes <scopes>. If they are still missing,
the provider did not grant them: check that the client is allowed to request them.” <scopes>
lists every missing scope, separated by commas.
How to fix
Section titled “How to fix”The scopes were not requested
Section titled “The scopes were not requested”- On the server’s page, select Sign in again with these scopes. MCP Tower starts a new sign-in with the scopes of the current token plus the missing ones, and the new token replaces the old one.
- Scan again. If the warning is gone, the authorization server grants the scopes, and agents get them too once they ask for them.
- To spare your users that second sign-in, make the scopes known before sign-in: list the tools
anonymously with their
securitySchemes, or put the scopes in your401challenge.
A tool declaration that tells agents what to request:
{ "name": "get_order", "description": "Look up one of your orders.", "inputSchema": { "type": "object", "properties": { "id": { "type": "string" } } }, "securitySchemes": [{ "type": "oauth2", "scopes": ["orders:read"] }]}The authorization server grants fewer scopes
Section titled “The authorization server grants fewer scopes”If the warning stays after Sign in again with these scopes, the scopes were requested and the authorization server left them out of the token.
- Check that every declared scope exists on the authorization server, spelled exactly as in
securitySchemes. - Allow the client to request them. Clients that register themselves with CIMD or DCR often get a default scope set, so allow the scopes for those clients, not only for clients you created.
- Check the consent screen: a user who unticks a scope gets a token without it.
- Add every scope your tools declare to
scopes_supportedin the authorization server metadata.
Check it yourself
Section titled “Check it yourself”List the tools and their declared scopes without a token:
curl -s https://mcp.example.com/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H 'MCP-Protocol-Version: 2025-11-25' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \ | jq '.result.tools[] | {name, scopes: [(.securitySchemes // ._meta.securitySchemes // [])[] | select(.type == "oauth2") | .scopes[]]}'Then compare them with the scope field of the token response from a sign-in that requested them:
{ "access_token": "<access-token>", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "<refresh-token>", "scope": "mcp:tools orders:read inventory:write"}The problem is fixed when every scope from the first command appears in scope. Then select Scan
again on the server’s page.
References
Section titled “References”- MCP authorization
2026-07-28: Scope selection strategy and step-up authorization flow - RFC 6749 §3.3: access token scope,
and §5.1: the
scopefield of the token response - SEP-1488:
securitySchemesin tool metadata (draft) - OpenAI: Triggering authentication UI
- Claude: PKCE and requested scopes and Ask for more scope with 403