Skip to content

fix(mcp): advertise Clerk as OAuth issuer - #3050

Merged
fahreddinozcan merged 3 commits into
masterfrom
ctx7-2010-use-clerk-oauth-issuer
Aug 20, 2026
Merged

fix(mcp): advertise Clerk as OAuth issuer#3050
fahreddinozcan merged 3 commits into
masterfrom
ctx7-2010-use-clerk-oauth-issuer

Conversation

@fahreddinozcan

@fahreddinozcan fahreddinozcan commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • advertise Clerk as the first authorization server for ordinary OAuth
  • keep Context7 as a separate authorization server for enterprise-managed id-jag
  • stop coupling the interactive OAuth issuer to the enterprise token issuer
  • add integration coverage for the protected-resource metadata order
  • document the independent user-OAuth and enterprise issuer environment variables

Root cause

The MCP protected-resource metadata advertised https://context7.com, while the actual authorization response is produced by Clerk with iss=https://clerk.context7.com. RFC 9207-aware clients correctly reject that response because the discovered and returned issuers differ.

Clerk is now advertised directly for authorization-code flows, making discovery metadata and the final response use the same issuer. Context7 remains listed for its independent enterprise id-jag exchange.

No Clerk proxy URL or primary-domain change is required.

Compatibility

  • existing Context7 token and registration compatibility endpoints remain available
  • existing access and refresh tokens are not invalidated
  • clients that cached Context7 as the issuer and need to authorize again must clear/recreate that local OAuth registration so they rediscover Clerk; migrating Clerk records cannot change a client's cached issuer

Rollout dependency

Deploy and configure upstash/context7app#963 first:

  1. deploy the Context7-hosted Clerk consent page
  2. set Clerk's production OAuth consent location to https://context7.com/oauth/authorize
  3. verify normal sign-in and session refresh
  4. deploy this PR
  5. verify a fresh Claude Code registration, consent, token exchange, and MCP tool call

Validation

  • pnpm --filter @upstash/context7-mcp typecheck
  • pnpm --filter @upstash/context7-mcp lint
  • pnpm --filter @upstash/context7-mcp test — 77 tests passed
  • targeted Prettier check

@linear-code

linear-code Bot commented Aug 18, 2026

Copy link
Copy Markdown

CTX7-2010

@fahreddinozcan
fahreddinozcan marked this pull request as ready for review August 18, 2026 18:20
@enesgules

Copy link
Copy Markdown
Collaborator

Approved. The change is correct: validateJWT already accepted Clerk-issued tokens (packages/mcp/src/lib/jwt.ts), so only discovery was wrong. The integration test uses getDefaultEnvironment(), which removes stray env vars, so the assertion stays stable.

Nitpicks only, none of them blocking:

1. .env.example is now incomplete

Line 7 still lists only AUTH_SERVER_URL. Add OAUTH_AUTH_SERVER_URL and EMA_ISSUER so a new developer sees the two independent knobs.

2. Local development behavior changes quietly

A developer who keeps AUTH_SERVER_URL=http://localhost:3000 now gets EMA on localhost, but user OAuth on production Clerk. Before this PR, both used localhost. Please record this in the EMA_ISSUER comment in constants.ts.

3. Confirm how id-jag clients select their server

EMA_ISSUER is now the second entry of authorization_servers. An enterprise client must read every entry and select the server that advertises authorization_grant_profiles_supported. If any client uses authorization_servers[0], it will now go to Clerk. Worth one check before step 4 of the rollout.

4. Pre-existing, not caused by this PR

mcp.context7.com/.well-known/oauth-authorization-server proxies Clerk's document. That document contains issuer: https://clerk.context7.com, but the client received it from mcp.context7.com. RFC 8414 section 3.3 lets a strict client refuse it. This is the same class of defect this PR fixes, one layer down. A 308 redirect to Clerk is safer than a proxy, but that can be a separate PR.

@fahreddinozcan
fahreddinozcan merged commit 7d877a4 into master Aug 20, 2026
2 checks passed
@fahreddinozcan
fahreddinozcan deleted the ctx7-2010-use-clerk-oauth-issuer branch August 20, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants