MCPwell

Home › Security › Least-privilege tokens

Least-Privilege Tokens for MCP

Two specification pages cover this. Security best practices has the scope-minimization section and the token-passthrough section. Authorization has audience binding, the resource parameter, and the rule against passing a client token through to an upstream API. This page does not list the OAuth scopes of GitHub, Notion, Stripe, or any other vendor. Those vendors' scope names are not in the protocol specification, and this check did not read a token.

Audience

The authorization specification says an MCP server must validate access tokens and must validate that they were issued for that server, following RFC 8707. If validation fails, the response is HTTP 401. Clients must send the resource parameter on both the authorization request and the token request, and the value must identify the MCP server the client intends to use. Clients must not send the server a token issued by some other authorization server. Servers must not accept or transit any other tokens.

The security best practices forbid token passthrough: a server must not accept a token that was not explicitly issued for it, and must not rely on a token that was meant for a downstream API. The risks that document names are bypassing the server's own limits, losing a clear client identity in the logs, and letting one stolen token reach every service that will accept it.

How small a scope

The scope-minimization section says a broad scope granted up front, such as a wildcard, makes a stolen token more useful and makes revocation clumsier. The model it describes is a small initial scope for low-risk discovery or read operations, then a narrower challenge, using WWW-Authenticate scope, when a privileged operation is actually attempted. The server should accept a token that has a smaller scope than the client asked for. The authorization server may issue a subset of the requested scopes.

The common mistakes that section lists are: publishing every scope in scopes_supported, using a wildcard or an omnibus scope, bundling unrelated privileges to avoid later prompts, returning the whole scope catalog on every challenge, changing what a scope means without a version, and treating the scopes written on the token as enough without the server checking the operation.

The authorization specification also says authorization servers should issue short-lived access tokens, and that clients and servers must store tokens securely. Access tokens must be sent in the Authorization header, not in the query string.

What a fact sheet can say

The Auth line on a fact sheet is only the credential the registry entry declares: a secret header, a secret environment variable, or neither. It is not this page's checklist, and it is not a vendor scope list. Servers whose public URL returned HTTP 401 on 2026-10-17 are listed on the badge page as not verified. That status means the unauthenticated initialize failed. It does not name the scopes a signed-in session would have.

Related: checklist, prompt injection, GitHub, Notion, Stripe. Those three fact sheets record a 401 from the read-only check. They do not record a scope list.

FAQ

Does this page list GitHub, Notion, or Stripe scopes?

No. Those scope names are not in the MCP specification. The fact sheets for those servers record the registry entry and, for the 2026-10-17 check, HTTP 401 with no credential.

What does the specification say to do with a token meant for another API?

Do not accept it at the MCP server, and do not pass it through to a downstream API. A call upstream needs its own token, issued for that API.

What is the scope pattern the security best practices describe?

A small initial scope, then a specific challenge when a privileged operation is attempted. The document says not to publish wildcard scopes as the set clients should request up front.