mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
docs(byo-mcp): how to use with custom domains (#51085)
## Problem As part of my investigation of this [issue](https://linear.app/supabase/issue/AI-1263/test-byo-mcp-with-custom-domains) I realized that, in order for byo-mcp to work with custom domains, there's a tweak needed, and I'm documenting it here. The long term use to fix it lives [here](https://linear.app/supabase/issue/FDBKIN-20212/use-custom-domain-in-oidc-and-oauth-well-known-discovery-endpoints). With that one in place, we could remove the clarification and the experience would be much much simpler. Fixes AI-1263 ## Solution I'm documenting for now, and will follow up if something else needs a change. ## Review instructions Provide a clear numbered procedure that the PR reviewer can walk through. 1. Visit `docs/guides/ai-tools/byo-mcp` and read the added text. 2. See if it all makes sense. 3. Ask @raulb if something's not clear or confusing. ## Checklist Check all before review: - [x] I have read [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) - [x] If I wrote a new docs topic or edited an existing topic, I used the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs [style guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added guidance for configuring MCP authorization metadata with a custom domain, including setting the authorization server to the Supabase Auth project issuer and checking it against the advertised metadata. * Clarified that the resource URL continues to use the domain requested by the client, and that leaving the issuer setting unset locally retains the default. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4344fdea3d
commit
11488801f7
2 files changed
+32
No files matched your search
@@ -343,6 +343,37 @@ Every client that implements the MCP authorization specification discovers your
|
||||
|
||||
Users can review and revoke connected clients through the [OAuth grant management](/docs/guides/auth/oauth-server/oauth-flows#managing-user-grants) endpoints. The [Headless App block](/library/docs/tanstack/headless-app) ships an `/agents` page that does this.
|
||||
|
||||
## Use a custom domain
|
||||
|
||||
With a [custom domain](/docs/guides/platform/custom-domains) active, clients can reach your MCP server at `https://api.example.com/functions/v1/mcp`. Supabase Auth keeps its issuer on the project domain, `https://<your-project-ref>.supabase.co/auth/v1`. `withOAuthProtectedResource()` builds the Auth URL from the domain the request arrived on, so on the custom domain it advertises `https://api.example.com/auth/v1`. That doesn't match the issuer, and MCP clients that validate the Auth metadata stop at discovery.
|
||||
|
||||
If your clients can use the project URL, `https://<your-project-ref>.supabase.co/functions/v1/mcp` needs no changes. To serve MCP on the custom domain too, set the Auth server explicitly:
|
||||
|
||||
1. Point `authorizationServer` at an environment variable instead of letting it default to the request's domain:
|
||||
|
||||
```ts
|
||||
[
|
||||
withOAuthProtectedResource({ authorizationServer: Deno.env.get('MCP_AUTH_ISSUER') }),
|
||||
withSupabase<Database>({ auth: 'user' }),
|
||||
],
|
||||
```
|
||||
|
||||
2. Store the issuer as a secret, and redeploy:
|
||||
|
||||
```bash
|
||||
supabase secrets set MCP_AUTH_ISSUER=https://<your-project-ref>.supabase.co/auth/v1
|
||||
supabase functions deploy mcp
|
||||
```
|
||||
|
||||
Leave `MCP_AUTH_ISSUER` unset locally. An unset value falls back to the default, which is correct on the local stack. The `resource` URL still follows the domain each client uses, so the project URL and the custom domain both keep working.
|
||||
|
||||
To confirm the fix, compare `authorization_servers` from the resource metadata with `issuer` from Auth's discovery document. They must match:
|
||||
|
||||
```bash
|
||||
curl https://api.example.com/functions/v1/mcp/oauth-protected-resource
|
||||
curl https://<your-project-ref>.supabase.co/auth/v1/.well-known/oauth-authorization-server
|
||||
```
|
||||
|
||||
## Run it outside Edge Functions
|
||||
|
||||
The same pipeline mounts in any runtime that speaks `Request` in, `Response` out: a Next.js route handler, a SvelteKit endpoint, Cloudflare Workers, or a plain Node, Bun, or Deno server. Off Edge Functions there are no forwarded headers to derive the public URLs from, so pass them explicitly:
|
||||
|
||||
@@ -102,6 +102,7 @@ Before you activate your domain, prepare your applications and integrations for
|
||||
- Supabase Auth will use the custom domain immediately once activated.
|
||||
- OAuth flows will advertise the custom domain as a callback URL.
|
||||
- SAML will use the custom domain instead. This means that the `EntityID` of your project has changed, and this may cause SAML with existing identity providers to stop working.
|
||||
- MCP servers that use Supabase Auth need `authorizationServer` set explicitly to the project Auth issuer, not the custom domain. See [Use a custom domain](/docs/guides/ai-tools/byo-mcp#use-a-custom-domain) in the BYO-MCP guide.
|
||||
|
||||
To prevent issues for your users, follow these steps:
|
||||
|
||||
|
||||
Reference in new issue
Block a user