What did you do?
Ran the client-side OAuth flow (auth.AuthorizationCodeHandler, and likewise extauth.ClientCredentialsHandler) against an authorization server whose token response contains "scope": "".
What did you see?
authutil.ScopesFromToken returns an empty, non-nil slice for "scope": "" (or whitespace only), because it returns strings.Fields(scope) directly. Both handlers treat only nil as "scope absent, so the requested scopes were granted" (RFC 6749 section 5.1):
if tokenScopes := authutil.ScopesFromToken(tok); tokenScopes == nil {
h.grantedScopes[issuer] = requestedScopes
} else {
h.grantedScopes[issuer] = tokenScopes
}
So the handler records that nothing was granted. On the next step-up authorization, UnionScopes(granted, challenged) requests only the newly challenged scopes, and the new token drops the permissions granted in earlier rounds, which is what the SEP-2350 accumulation is meant to prevent.
What did you expect to see?
An empty scope names no scope-token (RFC 6749 section 3.3), so it should be treated like an absent one: ScopesFromToken returns nil and the handler keeps the requested scopes.
What version of the Go MCP SDK are you using?
v1.8.0, and main at d04a013.
What version of Go are you using (go version)?
go1.25.3 windows/amd64 (also reproduced with the go1.26 toolchain).
I have a fix with tests in #1308.
What did you do?
Ran the client-side OAuth flow (
auth.AuthorizationCodeHandler, and likewiseextauth.ClientCredentialsHandler) against an authorization server whose token response contains"scope": "".What did you see?
authutil.ScopesFromTokenreturns an empty, non-nil slice for"scope": ""(or whitespace only), because it returnsstrings.Fields(scope)directly. Both handlers treat onlynilas "scope absent, so the requested scopes were granted" (RFC 6749 section 5.1):So the handler records that nothing was granted. On the next step-up authorization,
UnionScopes(granted, challenged)requests only the newly challenged scopes, and the new token drops the permissions granted in earlier rounds, which is what the SEP-2350 accumulation is meant to prevent.What did you expect to see?
An empty
scopenames no scope-token (RFC 6749 section 3.3), so it should be treated like an absent one:ScopesFromTokenreturnsniland the handler keeps the requested scopes.What version of the Go MCP SDK are you using?
v1.8.0, and
mainat d04a013.What version of Go are you using (
go version)?go1.25.3 windows/amd64 (also reproduced with the go1.26 toolchain).
I have a fix with tests in #1308.