feat: add --oauth login for the --http local entry - #404
Conversation
3ba6f78 to
41dbecd
Compare
commit: |
41dbecd to
6a4af2c
Compare
Coverage Report for CI Build 33917889096Warning No base build found for commit Coverage: 94.402%Details
Uncovered Changes
Coverage RegressionsRequires a base build to compare against. How to fix this → Coverage Stats
💛 - Coveralls |
6a4af2c to
d2ff583
Compare
oauth4webapi ^3.5.3 handles discovery, dynamic client registration, PKCE, the authorization-code exchange and refresh. The token stores, the loopback callback server, the single-flight refresh, the loopback-only HTTPS rule, the S256 check and revocation stay in-repo. Test fixtures now answer registration with 201 and carry token_type on every token response, as the library requires.
d2ff583 to
1661479
Compare
The previous test used a constant token, so hoisting await tokenSource() to startup (breaking every request after the first refresh) would still pass.
# Conflicts: # CONTRIBUTING.md # packages/mcp-server-supabase/src/cli.ts # packages/mcp-server-supabase/src/transports/local-http-entry.test.ts # packages/mcp-server-supabase/src/transports/local-http-entry.ts
| }, | ||
| "dependencies": { | ||
| "@mjackson/multipart-parser": "^0.10.1", | ||
| "@modelcontextprotocol/client": "catalog:", |
There was a problem hiding this comment.
Note @modelcontextprotocol/client becomes a runtime dep with my changes so --oauth can use the SDK's auth() flow. Platform already has it at the same catalog version as a devDependency of mgmt-api, so the next bump will pull it (plus some small transitives) into the image as install weight. Platform doesn't reach the code that uses it though.
|
Pushed changes to trim this PR, though might be good to check the @modelcontextprotocol/client dep decision w/ platform team in case they object. We already get a nice DX boost from #401 alone so not the end of the world if we don't get OAuth in near term. Tested w/ |
What kind of change does this PR introduce?
Feature:
--oauthsign-in for the local--httpentry.What is the current behavior?
Stacked on #401. The
--httpentry takes a PAT per request from the client'sAuthorizationheader, so every user still has to mint and store a PAT.What is the new behavior?
--http --oauthsigns the user in with Supabase OAuth in the browser; the entry acts as an OAuth client to the Supabase authorization server, the same flow MCP Inspector uses (metadata, dynamic client registration, PKCE, loopback callback on127.0.0.1:3112); the protocol core is oauth4webapi. No platform change.--oauth-store fileopts into~/.supabase/mcp-oauth.json(mode 0600) and--logoutrevokes the tokens and deletes it..mcp.jsonsnippet has noheaders; the entry attaches the token to every Management API call itself.Originas well asHost; browser origins get 403.CONTRIBUTING.mdrecommends--http --oauthfor local development, with PAT mode as the alternative.How to Review
CLI flags
packages/mcp-server-supabase/src/cli.ts--oauth,--oauth-store,--oauth-callback-port,--logout;--oauthwithout--httpexits 1.OAuth client
packages/mcp-server-supabase/src/transports/oauth-client.tsEntry integration
packages/mcp-server-supabase/src/transports/local-http-entry.tsaccessTokenoption, the Origin check, the headerless banner, and the per-process principal.Tests
packages/mcp-server-supabase/src/transports/oauth-client.test.ts,packages/mcp-server-supabase/src/transports/local-http-entry.test.tsDocs
CONTRIBUTING.md--http --oauthsteps, the residual risk note, and the storage tool limitation.Review questions
--logoutrevoke) what we want?Verification
Commands on
55e16f6(thetestjob runs once this PR retargetsmain):packages/mcp-utilstsup --clean: okpnpm --filter @supabase/mcp-server-supabase test src/transports: 38/38 passpnpm --filter @supabase/mcp-server-supabase typecheck: cleanpnpm --filter @supabase/mcp-server-supabase build: oknode dist/cli.js --version: 0.11.0pnpm test:packed-platform-consumer: 3/3 passpnpm exec biome ci .: cleanpnpm install --frozen-lockfile: okSUPABASE_MCP_NO_BROWSER=1 node packages/mcp-server-supabase/dist/cli.js --http --oauth --port 0 --api-url http://127.0.0.1:9: exits 1 without contacting a real hostHow to test:
npx https://pkg.pr.new/@supabase/mcp-server-supabase@55e16f6 --http --oauth(add--api-url https://api.supabase.greenfor staging). Local alternative:pnpm build, thennode packages/mcp-server-supabase/dist/cli.js --http --oauth..mcp.json.list_projectsworks;get_storage_configreturns the platform's 401 message.Verified by Barry on 2026-09-03 on staging at d2ff583 (hand-rolled OAuth client): OAuth login, project list, $0 project created directly, branch cost dialog shown in Claude Code 2.1.258. The oauth4webapi head (55e16f6; 1661479 plus one test-only commit) has not had a staging run yet; that run is the only test against the real registration and token endpoints.
Additional context
packages/mcp-server-supabase/src/transports/oauth-client.ts.packages/mcp-server-supabase/src/transports/oauth-client.ts.127.0.0.1:<port>gets the signed-in user's scopes. Residual named inCONTRIBUTING.md.packages/mcp-server-supabase/src/transports/oauth-client.ts.resourceparameter; the platform AS only accepts the hosted MCP URL there.packages/mcp-server-supabase/src/transports/oauth-client.ts.packages/mcp-server-supabase/src/transports/oauth-client.ts.requestState.packages/mcp-server-supabase/src/transports/local-http-entry.ts.get_storage_config/update_storage_configreturn 401 under an OAuth token because the platform storage handlers lack@RequiredScope; the hosted server has the same gap.checkjob is red from upstream management-API types drift; it fails onmaintoo.feat/local-http-entry(feat: add --http local HTTP entry to mcp-server-supabase #401); the CItestjob runs after this retargetsmain.Part of AI-1166