[BUG] Step-up authorization not working for scope elevation in MCP TypeScript SDK
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
File: packages/client/src/client/auth.ts in modelcontextprotocol/typescript-sdk
The MCP client fails to obtain elevated scopes during step-up authorization (403 insufficient_scope) because the authInternal() function refreshes tokens without requesting the new scopes.
What Actually Happens (if refresh_token exists)
- ✅ Client makes request with token
- ✅ Server returns
403 insufficient_scopewithscope="products:write" - ✅ Client calls
auth(authProvider, { scope: "products:write", ... }) - ❌ Auth function refreshes token WITHOUT passing new scopes
- ❌ Gets same token back with original scopes (missing
products:write) - ❌ Retry fails with same 403
- ✅ Infinite loop protection aborts: "Server returned 403 after trying upscoping"
The Bug
Location
File: packages/client/src/client/auth.ts
Function: authInternal() at lines 560-573
Problem
- Missing
scopeparameter: Line 563-570 doesn't pass thescopeparameter torefreshAuthorization(), so it refreshes with the same scopes as the original token - No fallback to user consent: If refresh succeeds but doesn't grant new scopes, the function never falls through to start a new OAuth flow (lines 584-595)
What Actually Happens (if refresh_token is not there)
- ✅ Client makes request with token
- ✅ Server returns
403 insufficient_scopewithscope="products:write" - ✅ Client calls
auth(authProvider, { scope: "products:write", ... }) - ✅ Client invokes
pkceflow and sends redirect url - ❌ Auth Client provider disabled redirect_url, and doesn't show to user to consent for step-up authz
- ❌ Retry fails with 401 (token expired)
What Should Happen?
- Client makes request with token
- Server returns
403 Forbiddenwith:
``http``
WWW-Authenticate: Bearer error="insufficient_scope",
scope="products:write"
- Client detects insufficient scope and calls
auth()with elevated scopes - Auth function should either:
- Refresh token WITH new scopes, OR
- Start new OAuth PKCE flow for user consent
- Auth client provider enables redirect and shows to user for consent
- Client gets new token with elevated permissions
- Request succeeds
Error Messages/Logs
below are logs (by having 403 from mcp server)
### refresh token as null, to trigger auth flow
2026-02-24T17:06:42.643Z [DEBUG] MCP server "dev-mcp-server-1": Found client info
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Returning tokens
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Token length: 90
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Has refresh token: false
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Expires in: 2835s
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Saving code verifier
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Authorization URL: https://masked-server/mcp/oauth2/authorize?response_typ
e=code&client_id=oacli_U2TpyjRx44Ascs&code_challenge=%5BREDACTED%5D&code_challenge_method=S256&redirect_uri=http%3A%2F%2Flocalhost%3A3118%2
Fcallback&state=%5BREDACTED%5D&scope=product:write&resource=https%3A%2F%2Fmasked_resource%2F
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Scopes in URL: product:write
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Captured scopes from authorization URL: product:write
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Redirection handling is disabled, skipping redirect
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": HTTP connection dropped after 764s uptime
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Connection error: Unauthorized
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Tool 'create_product' failed after 0s: Unauthorized
2026-02-24T17:06:42.644Z [DEBUG] MCP server "dev-mcp-server-1": Tool call returned 401 Unauthorized - token may have expired
2026-02-24T17:06:42.644Z [DEBUG] mcp__dev-mcp-server-1__create_product tool error (773ms): MCP server "dev-mcp-server-1" requires re-authorization (tok
en expired)
Steps to Reproduce
Have an mcp tool in mcp server to return
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope",
scope="products:write",
resource_metadata="https://your-mcp-server.example.com/.well-known/oauth-protected-resource"
Content-Type: application/json
{
"error": "insufficient_scope",
"error_description": "Additional permissions required"
}
Required Header Components
- Status Code: 403 Forbidden (NOT 401)
- WWW-Authenticate Header with:
- error="insufficient_scope" (REQUIRED - triggers step-up flow)
- scope="products:write" (REQUIRED - tells client what scopes to request)
- resource_metadata="..." (OPTIONAL - helps client discover auth server)
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.39
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
MCP Spec Compliance
According to the MCP Authorization Spec (https://modelcontextprotocol.io/specification/draft/basic/authorization#step-up-authorization-flow):
When a client makes a request with an access token with insufficient scope during runtime operations, the server SHOULD respond with: -HTTP 403 Forbiddenstatus code -WWW-Authenticateheader witherror="insufficient_scope"-scopeparameter specifying the minimum scopes needed
Clients SHOULD respond to these errors by requesting a new access token with an increased set of scopes (from user) via a step-up authorization flow.
Current implementation violates this by not actually requesting elevated scopes during the step-up flow.
4 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This will be resolved in the next release. Would love your confirmation that it's working as expected!
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.