diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
index ae10e996a5301..05951f0b0cabd 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
@@ -496,7 +496,7 @@ export const gettingstarted: NavMenuConstant = {
},
{
name: 'Deploy MCP servers',
- url: '/guides/getting-started/byom' as `/${string}`,
+ url: '/guides/getting-started/byo-mcp' as `/${string}`,
},
],
},
diff --git a/apps/docs/content/_partials/universal_links_apple.mdx b/apps/docs/content/_partials/universal_links_apple.mdx
new file mode 100644
index 0000000000000..ef9ada6753b17
--- /dev/null
+++ b/apps/docs/content/_partials/universal_links_apple.mdx
@@ -0,0 +1,44 @@
+### Universal links
+
+For a better user experience, you can use **Universal Links** instead of custom URL schemes. Universal Links allow your app to open directly from web links without showing a browser redirect prompt.
+
+To enable Universal Links, you need to:
+
+1. **Configure Associated Domains** in your Xcode project:
+
+ - Add your domain to the Associated Domains capability
+ - Format: `applinks:yourdomain.com`
+
+2. **Host the Apple App Site Association (AASA) file** on your own infrastructure:
+ - The file must be accessible at `https://yourdomain.com/.well-known/apple-app-site-association` or `https://yourdomain.com/apple-app-site-association`
+ - The file must be served with `Content-Type: application/json` (or `text/json`)
+ - The file must be accessible over HTTPS without redirects
+ - The file should not have a file extension
+
+
+
+Supabase does not currently support hosting the AASA file. You must host this file on your own
+infrastructure following [Apple's best
+practices](https://developer.apple.com/documentation/xcode/supporting-associated-domains).
+
+
+
+The AASA file format should look like this:
+
+```json
+{
+ "applinks": {
+ "apps": [],
+ "details": [
+ {
+ "appID": "TEAM_ID.BUNDLE_ID",
+ "paths": ["*"]
+ }
+ ]
+ }
+}
+```
+
+Replace `TEAM_ID` with your Apple Developer Team ID and `BUNDLE_ID` with your app's bundle identifier.
+
+For detailed setup instructions, see [Apple's documentation on supporting associated domains](https://developer.apple.com/documentation/xcode/supporting-associated-domains).
diff --git a/apps/docs/content/guides/auth/native-mobile-deep-linking.mdx b/apps/docs/content/guides/auth/native-mobile-deep-linking.mdx
index 6d2155e9e64b3..797a8094bc417 100644
--- a/apps/docs/content/guides/auth/native-mobile-deep-linking.mdx
+++ b/apps/docs/content/guides/auth/native-mobile-deep-linking.mdx
@@ -191,6 +191,8 @@ With Deep Linking, you can configure this redirect to open a specific page. This
For more info: https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app
+ <$Partial path="universal_links_apple.mdx" />
+
@@ -343,6 +345,8 @@ With Deep Linking, you can configure this redirect to open a specific page. This
```
+ <$Partial path="universal_links_apple.mdx" />
+
$Show>
<$Show if="sdk:kotlin">
diff --git a/apps/docs/content/guides/auth/oauth-server/getting-started.mdx b/apps/docs/content/guides/auth/oauth-server/getting-started.mdx
index fbcdbcd1694e9..e9033142c1fd3 100644
--- a/apps/docs/content/guides/auth/oauth-server/getting-started.mdx
+++ b/apps/docs/content/guides/auth/oauth-server/getting-started.mdx
@@ -540,7 +540,7 @@ Response:
-For complete API documentation, see the [OAuth Admin API reference](/todo).
+For complete API documentation, see the [OAuth Admin API reference](/docs/reference/javascript/auth-admin-oauth-admin).
diff --git a/apps/docs/content/guides/auth/oauth-server/mcp-authentication.mdx b/apps/docs/content/guides/auth/oauth-server/mcp-authentication.mdx
index 4e5406357f750..592d9eff3e4fe 100644
--- a/apps/docs/content/guides/auth/oauth-server/mcp-authentication.mdx
+++ b/apps/docs/content/guides/auth/oauth-server/mcp-authentication.mdx
@@ -79,7 +79,7 @@ When building your own MCP server, integrate with Supabase Auth to authenticate
**Looking for an easier way to build MCP servers?**
-[FastMCP](https://gofastmcp.com) provides a streamlined way to build MCP servers with built-in Supabase Auth integration. FastMCP handles OAuth configuration, token management, and authentication flows automatically, letting you focus on building your AI agent's functionality. Check out their [Supabase integration guide](https://gofastmcp.com/todo) to get started quickly.
+[FastMCP](https://gofastmcp.com) provides a streamlined way to build MCP servers with built-in Supabase Auth integration. FastMCP handles OAuth configuration, token management, and authentication flows automatically, letting you focus on building your AI agent's functionality. Check out their [Supabase integration guide](https://gofastmcp.com/integrations/supabase) to get started quickly.
diff --git a/apps/docs/content/guides/getting-started/byom.mdx b/apps/docs/content/guides/getting-started/byo-mcp.mdx
similarity index 62%
rename from apps/docs/content/guides/getting-started/byom.mdx
rename to apps/docs/content/guides/getting-started/byo-mcp.mdx
index 69e6de4d4c24e..60251952cc0f0 100644
--- a/apps/docs/content/guides/getting-started/byom.mdx
+++ b/apps/docs/content/guides/getting-started/byo-mcp.mdx
@@ -1,13 +1,16 @@
---
-id: 'ai-tools-byom'
+id: 'ai-tools-byo-mcp'
title: 'Deploy MCP servers'
description: 'Build and deploy remote MCP servers on Supabase Edge Functions'
-subtitle: 'Deploy custom MCP servers on Supabase Edge Functions'
---
-Deploy your [Model Context Protocol](https://modelcontextprotocol.io/specification/2025-11-25) (MCP) servers on Supabase take advantage of features like [Edge Functions](/docs/guides/functions), [OAuth](/docs/guides/auth/oauth-server), and scaling for AI applications.
+Build and deploy [Model Context Protocol](https://modelcontextprotocol.io/specification/2025-11-25) (MCP) servers on Supabase using [Edge Functions](/docs/guides/functions).
-- Get started with [deploying](#deploy-your-mcp-server) MCP servers on Supabase
+
+
+This guide covers MCP servers that do not require authentication. Auth support for MCP on Edge Functions is coming soon.
+
+
## Deploy your MCP server
@@ -34,17 +37,16 @@ supabase init
Create a new Edge Function for your MCP server:
```bash
-supabase functions new simple-mcp-server
+supabase functions new mcp
```
-Create a `deno.json` file in `supabase/functions/simple-mcp-server/` with the required dependencies:
+Create a `deno.json` file in `supabase/functions/mcp/` with the required dependencies:
```json
{
"imports": {
"@hono/mcp": "npm:@hono/mcp@^0.1.1",
"@modelcontextprotocol/sdk": "npm:@modelcontextprotocol/sdk@^1.24.3",
- "@modelcontextprotocol/sdk/": "npm:/@modelcontextprotocol/sdk@^1.24.3/",
"hono": "npm:hono@^4.9.2",
"zod": "npm:zod@^4.1.13"
}
@@ -57,7 +59,7 @@ This tutorial uses the [official MCP TypeScript SDK](https://github.com/modelcon
-Replace the contents of `supabase/functions/simple-mcp-server/index.ts` with:
+Replace the contents of `supabase/functions/mcp/index.ts` with:
```ts
// Setup type definitions for built-in Supabase Runtime APIs
@@ -68,14 +70,13 @@ import { StreamableHTTPTransport } from '@hono/mcp'
import { Hono } from 'hono'
import { z } from 'zod'
-// Change this to your function name
-const functionName = 'simple-mcp-server'
-const app = new Hono().basePath(`/${functionName}`)
+// Create Hono app
+const app = new Hono()
// Create your MCP server
const server = new McpServer({
- name: 'simple-mcp-server',
- version: '1.0.0',
+ name: 'mcp',
+ version: '0.1.0',
})
// Register a simple addition tool
@@ -91,8 +92,8 @@ server.registerTool(
})
)
-// Handle MCP requests
-app.all('/mcp', async (c) => {
+// Handle MCP requests at the root path
+app.all('/', async (c) => {
const transport = new StreamableHTTPTransport()
await server.connect(transport)
return transport.handleRequest(c)
@@ -101,52 +102,6 @@ app.all('/mcp', async (c) => {
Deno.serve(app.fetch)
```
-### Understanding the code
-
-The MCP server implementation uses several key components:
-
-**Hono routing**: Supabase Edge Functions route all requests to `//*`. The Hono app uses `basePath` to handle this:
-
-```ts
-const functionName = 'simple-mcp-server'
-const app = new Hono().basePath(`/${functionName}`)
-```
-
-**MCP server setup**: The `McpServer` class from the official SDK handles the MCP protocol:
-
-```ts
-const server = new McpServer({
- name: 'simple-mcp-server',
- version: '1.0.0',
-})
-```
-
-**Tool registration**: Tools are registered with a name, metadata, input schema (using Zod), and a handler function:
-
-```ts
-server.registerTool(
- 'add',
- {
- title: 'Addition Tool',
- description: 'Add two numbers together',
- inputSchema: { a: z.number(), b: z.number() },
- },
- ({ a, b }) => ({
- content: [{ type: 'text', text: String(a + b) }],
- })
-)
-```
-
-**HTTP transport**: The `StreamableHTTPTransport` from `@hono/mcp` connects your MCP server to HTTP requests:
-
-```ts
-app.all('/mcp', async (c) => {
- const transport = new StreamableHTTPTransport()
- await server.connect(transport)
- return transport.handleRequest(c)
-})
-```
-
### Local development
Start the Supabase local development stack:
@@ -158,18 +113,18 @@ supabase start
In a separate terminal, serve your function:
```bash
-supabase functions serve --no-verify-jwt simple-mcp-server
+supabase functions serve --no-verify-jwt mcp
```
Your MCP server is now running at:
```
-http://localhost:54321/functions/v1/simple-mcp-server/mcp
+http://localhost:54321/functions/v1/mcp
```
-The `--no-verify-jwt` flag disables JWT verification at the Edge Function layer. This is required because MCP authentication is handled by the MCP server itself, not by Supabase's standard JWT validation.
+The `--no-verify-jwt` flag disables JWT verification at the Edge Function layer so your MCP server can accept unauthenticated requests. Authenticated MCP support is coming soon.
@@ -181,7 +136,7 @@ Test your server with the official [MCP Inspector](https://github.com/modelconte
npx -y @modelcontextprotocol/inspector
```
-Enter your MCP endpoint URL in the inspector UI to explore available tools and test them interactively.
+Use the local endpoint `http://localhost:54321/functions/v1/mcp` in the inspector UI to explore available tools and test them interactively.
### Deploy to production
@@ -189,13 +144,13 @@ When you're ready to deploy, link your project and deploy the function:
```bash
supabase link --project-ref
-supabase functions deploy --no-verify-jwt simple-mcp-server
+supabase functions deploy --no-verify-jwt mcp
```
Your MCP server will be available at:
```
-https://.supabase.co/functions/v1/simple-mcp-server/mcp
+https://.supabase.co/functions/v1/mcp
```
Update your MCP client configuration to use the production URL.
@@ -240,14 +195,6 @@ server.registerTool(
)
```
-## Add authentication
-
-
-
-MCP authentication is not yet supported on Edge Functions. For now, MCP servers deployed on Supabase Edge Functions are publicly accessible.
-
-
-
## Examples
You can find ready-to-use MCP server implementations here:
diff --git a/apps/docs/content/guides/local-development.mdx b/apps/docs/content/guides/local-development.mdx
index 8545ceb17685a..872f486567e2e 100644
--- a/apps/docs/content/guides/local-development.mdx
+++ b/apps/docs/content/guides/local-development.mdx
@@ -114,6 +114,19 @@ As a prerequisite, you must install a container runtime compatible with Docker A
4. View your local Supabase instance at [http://localhost:54323](http://localhost:54323).
+
+
+If your local development machine is connected to an untrusted public network, you should create a separate docker network and bind to 127.0.0.1 before starting the local development stack. This restricts network access to only your localhost machine.
+
+```sh
+docker network create -o 'com.docker.network.bridge.host_binding_ipv4=127.0.0.1' local-network
+npx supabase start --network-id local-network
+```
+
+You should never expose your local development stack publicly.
+
+
+
## Local development
Local development with Supabase allows you to work on your projects in a self-contained environment on your local machine. Working locally has several advantages:
diff --git a/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/deno.json b/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/deno.json
index 7233c5f1d1a70..a56b7f4e018dc 100644
--- a/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/deno.json
+++ b/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/deno.json
@@ -1,9 +1,8 @@
{
"imports": {
"@hono/mcp": "npm:@hono/mcp@^0.1.1",
- "@modelcontextprotocol/sdk": "npm:/@modelcontextprotocol/sdk@^1.17.3",
- "@modelcontextprotocol/sdk/": "npm:/@modelcontextprotocol/sdk@^1.17.3/",
+ "@modelcontextprotocol/sdk": "npm:/@modelcontextprotocol/sdk@^1.24.3",
"hono": "npm:hono@^4.9.2",
- "zod": "npm:zod@^3.25.76"
+ "zod": "npm:zod@^4.1.13"
}
}
diff --git a/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/index.ts b/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/index.ts
index 7676f61ad25f0..e5cc7c7e178ea 100644
--- a/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/index.ts
+++ b/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/index.ts
@@ -6,14 +6,13 @@ import { StreamableHTTPTransport } from "@hono/mcp";
import { Hono } from "hono";
import { z } from "zod";
-// Change this to your function name
-const functionName = "simple-mcp-server";
-const app = new Hono().basePath(`/${functionName}`);
+// Create Hono app
+const app = new Hono();
// Create your MCP server
const server = new McpServer({
- name: "simple-mcp-server",
- version: "1.0.0",
+ name: "mcp",
+ version: "0.1.0",
});
// Register a simple addition tool
@@ -25,8 +24,8 @@ server.registerTool("add", {
content: [{ type: "text", text: String(a + b) }],
}));
-// Handle MCP requests
-app.all("/mcp", async (c) => {
+// Handle MCP requests at the root path
+app.all("/", async (c) => {
const transport = new StreamableHTTPTransport();
await server.connect(transport);
return transport.handleRequest(c);