apps/docs/content/guides/functions/examples/mcp-server-mcp-lite.mdx
The Model Context Protocol (MCP) enables Large Language Models (LLMs) to interact with external tools and data sources. With mcp-lite, you can build lightweight MCP servers that run on Supabase Edge Functions, giving your AI assistants the ability to execute custom tools at the edge.
This guide shows you how to scaffold, develop, and deploy an MCP server using mcp-lite on Supabase Edge Functions.
mcp-lite is a lightweight, zero-dependency TypeScript framework for building MCP servers. It works everywhere the Fetch API is available, including Node, Bun, Cloudflare Workers, Deno, and Supabase Edge Functions.
This combination offers several advantages:
You need:
Starting with [email protected], you can scaffold a complete MCP server that runs on Supabase Edge Functions:
npm create mcp-lite@latest
When prompted, select Supabase Edge Functions (MCP server) from the template options.
The template creates a focused structure for Edge Functions development:
my-mcp-server/
├── supabase/
│ ├── config.toml # Minimal Supabase config (Edge Functions only)
│ └── functions/
│ └── mcp-server/
│ ├── index.ts # MCP server implementation
│ └── deno.json # Deno imports and configuration
├── package.json
└── tsconfig.json
The template includes a minimal config.toml that runs only Edge Functions - no database, storage, or Studio UI. This keeps your local setup lightweight:
# Minimal config for running only Edge Functions (no DB, storage, or studio)
project_id = "starter-mcp-supabase"
[api]
enabled = true
port = 54321
[edge_runtime]
enabled = true
policy = "per_worker"
deno_version = 2
You can always add more services as needed.
The template uses a specific pattern required by Supabase Edge Functions:
// Root handler - matches the function name
const app = new Hono()
// MCP protocol handler
const mcpApp = new Hono()
mcpApp.get('/', (c) => {
return c.json({
message: 'MCP Server on Supabase Edge Functions',
endpoints: {
mcp: '/mcp',
health: '/health',
},
})
})
mcpApp.all('/mcp', async (c) => {
const response = await httpHandler(c.req.raw)
return response
})
// Mount at /mcp-server (the function name)
app.route('/mcp-server', mcpApp)
This is required because Supabase routes all requests to /<function-name>/*. The outer app handles the function-level routing, while mcpApp handles your actual MCP endpoints.
The template uses Deno's import maps in deno.json to manage dependencies:
{
"compilerOptions": {
"lib": ["deno.window", "deno.ns"],
"strict": true
},
"imports": {
"hono": "npm:hono@^4.6.14",
"mcp-lite": "npm:[email protected]",
"zod": "npm:zod@^4.1.12"
}
}
This gives you npm package access while staying in the Deno ecosystem.
Navigate to your project directory and start Supabase services:
supabase start
In a separate terminal, serve your MCP function locally:
supabase functions serve --no-verify-jwt mcp-server
Or use the npm script (which runs the same command):
npm run dev
Your MCP server is available at:
http://localhost:54321/functions/v1/mcp-server/mcp
Test the MCP server by adding it to your Claude Code, Claude Desktop, Cursor, or your preferred MCP client.
Using Claude Code:
claude mcp add my-mcp-server -t http http://localhost:54321/functions/v1/mcp-server/mcp
You can also test it using the MCP inspector:
npx @modelcontextprotocol/inspector
Then add the MCP endpoint URL in the inspector UI.
The MCP server setup is straightforward:
import { McpServer, StreamableHttpTransport } from 'mcp-lite'
import { z } from 'zod'
// Create MCP server instance
const mcp = new McpServer({
name: 'starter-mcp-supabase-server',
version: '1.0.0',
schemaAdapter: (schema) => z.toJSONSchema(schema as z.ZodType),
})
// Define a tool
mcp.tool('sum', {
description: 'Adds two numbers together',
inputSchema: z.object({
a: z.number(),
b: z.number(),
}),
handler: (args: { a: number; b: number }) => ({
content: [{ type: 'text', text: String(args.a + args.b) }],
}),
})
// Bind to HTTP transport
const transport = new StreamableHttpTransport()
const httpHandler = transport.bind(mcp)
Extend your MCP server by adding tools directly to the mcp instance. Here's an example of adding a database search tool:
mcp.tool('searchDatabase', {
description: 'Search your Supabase database',
inputSchema: z.object({
table: z.string(),
query: z.string(),
}),
handler: async (args) => {
// Access Supabase client here
// const { data } = await supabase.from(args.table).select('*')
return {
content: [{ type: 'text', text: `Searching ${args.table}...` }],
}
},
})
You can add tools that:
When ready, deploy to Supabase's global edge network:
supabase functions deploy --no-verify-jwt mcp-server
Or use the npm script:
npm run deploy
Your MCP server will be live at:
https://your-project-ref.supabase.co/functions/v1/mcp-server/mcp
The template uses --no-verify-jwt for quick development. This means authentication is not enforced by Supabase's JWT layer.
For production, you should implement authentication at the MCP server level following the MCP Authorization specification. This gives you control over who can access your MCP tools.
</Admonition>When deploying MCP servers:
For more security guidance, see the MCP security guide.
With your MCP server running on Supabase Edge Functions, you can: