From 50302662f787cedd900dafbb3e528fb3c4fc4fb2 Mon Sep 17 00:00:00 2001 From: Pedro Rodrigues <44656907+Rodriguespn@users.noreply.github.com> Date: Fri, 12 Dec 2025 11:50:57 +0000 Subject: [PATCH] docs(update): address review comments for MCP server guide (#41274) * docs: improve BYOM guide for MCP server deployment and OAuth integration * fix rebase * fix pnpm.lock * docs: clarify MCP guide and example naming * fix pnpm-lock * docs: remove basePath from MCP tutorial and example - Remove misleading comment about Edge Functions routing - Remove basePath as it's not needed - Edge Functions automatically strip /functions/v1/ prefix - Simplify code to just use const app = new Hono() * docs: clarify --no-verify-jwt flag and authentication options - Explain that omitting --no-verify-jwt enables JWT verification at Edge Function layer - Clarify this provides basic protection for internal servers but not full MCP auth - Update authentication section to be consistent - Add tip in deployment section about omitting the flag * fiox format * PR feedback * chore: restore pnpm-lock.yaml from master --- .../NavigationMenu.constants.ts | 2 +- .../getting-started/{byom.mdx => byo-mcp.mdx} | 97 +++++-------------- .../functions/mcp/simple-mcp-server/deno.json | 5 +- .../functions/mcp/simple-mcp-server/index.ts | 13 ++- 4 files changed, 31 insertions(+), 86 deletions(-) rename apps/docs/content/guides/getting-started/{byom.mdx => byo-mcp.mdx} (62%) diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index ae10e996a53..05951f0b0ca 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/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 69e6de4d4c2..60251952cc0 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/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/deno.json b/examples/edge-functions/supabase/functions/mcp/simple-mcp-server/deno.json index 7233c5f1d1a..a56b7f4e018 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 7676f61ad25..e5cc7c7e178 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);