Repository navigation
Conversation
OAuth 2.1 section 3.2.3 requires token responses to carry Cache-Control: no-store, because they contain credentials. The header is set before any response is written, so error responses carry it as well.
MCP clients such as Claude, ChatGPT and Claude Code sign users in to an MCP server through its authorization server. This suite drives the full router the way they do (discovery, registration, authorize, consent, token and refresh) and checks each requirement the MCP authorization specification places on the authorization server, with a reference to the specification on every requirement. Known gaps carry a pending reference to their issue and proposed fix. Their tests are skipped while the gap exists, and fail once it is closed, so the marker is removed by the change that closes it.
This was referenced Nov 8, 2026
Author
shanurwan
marked this pull request as draft
November 10, 2026 13:31
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A test suite that checks the OAuth 2.1 server against what the MCP authorization specification requires of an authorization server. It drives the full router the way MCP clients (Claude, ChatGPT, Claude Code) do: discovery, registration, authorize, consent, token and refresh. Each of the 18 requirements cites the specification.
It also fixes one gap it found: token responses did not send
Cache-Control: no-store(OAuth 2.1 §3.2.3).Why
I run an MCP server (Counsel) behind this OAuth server, and Claude signs people in to it. It works, but every access token carries
aud: "authenticated"whateverresourcethe client asked for, so the server can't tell a token issued for it from one issued for another MCP server on the same project. I had to turn the audience check off. The MCP Python SDK warns thatvalidate_token_resourcebecomes the default in 3.0; servers built on it would then refuse every token from Supabase Auth. I wanted to know exactly which requirements hold today, and to know when that one is fixed.Several open PRs close MCP sign-in gaps (#2871, #2894, #2895). This gives them a shared definition of done. A known gap is a pending test that names its issue and PR. It is skipped while the gap exists, and fails with "now conforms; remove the pending marker" once it is closed, so the list stays accurate.
Results on master (with the fix)
client_id) for MCP clients #2850, feat(oauthserver): support Client ID Metadata Documents #2895)issin the authorization response (RFC 9207; SHOULD in MCP 2026-07-28; not filed yet)The open PRs, each merged onto this branch
AllowClientIDMetadataDocumentson: AS-05 passes.20261030120000_add_resource_to_sessionshas the same version as20261030120000_add_dedicated_scope_to_saml_providersfrom feat(saml): add dedicated_scope option for SAML providers #2893, merged on 6 Nov. Rebased on master, only one of them runs, sosessions.resourceis never created and new sessions fail ("column "resource" of relation "sessions" does not exist"). With the migration given a later timestamp, AS-13, AS-14 and AS-16 pass.On master, AS-14 also shows that a form-encoded token request for a different resource than the authorized one is accepted, because the check only reads JSON bodies. #2894 fixes this.
Not covered
Fetching Client ID Metadata Documents, DPoP, and the consent page itself, which each project builds.
Testing
Both pass locally against Postgres 15.