fix: accumulate OAuth scopes across 401/403 for progressive authorization#1604
fix: accumulate OAuth scopes across 401/403 for progressive authorization#1604giulio-leone wants to merge 1 commit intomodelcontextprotocol:mainfrom
Conversation
|
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
… authorization Replace scope overwrite with union-based accumulation in StreamableHTTPClientTransport. Both the 401 and 403 (insufficient_scope) handlers now merge new scopes with previously-granted scopes, preventing the infinite re-authorization loop described in modelcontextprotocol#1582. Adds mergeScopes() helper that computes the set union of space-delimited OAuth scope strings per RFC 6749 §3.3. Closes modelcontextprotocol#1582
|
Friendly ping — CI is green and this is ready for review. Happy to address any feedback. Thanks! |
|
All CI checks pass. Ready for review. |
pcarleton
left a comment
There was a problem hiding this comment.
This LGTM, we'll need a changeset before we merge. We may also want to backport this to v1.
Summary
Fixes #1582
The
StreamableHTTPClientTransportoverwrites_scopeon each 401/403 response instead of accumulating scopes. This causes an infinite re-authorization loop when an MCP server uses per-operation scopes (progressive/step-up authorization):initializesucceeds with scopeinittools/listreturns 403 →_scope = "mcp:tools:read"(init lost)mcp:tools:readbut notinitinitfails →_scope = "init"(read lost)Changes
mergeScopes()helper: Computes the set-union of space-delimited OAuth scope strings per RFC 6749 §3.3this._scope = mergeScopes(this._scope, scope)this._scope = mergeScopes(this._scope, scope)Test
Added
accumulates scopes across multiple 403 responses for progressive authorizationtest that verifies:mcp:tools:readmcp:tools:read mcp:tools:writeAll 253 client tests pass (2 consecutive clean runs).