Supabase MCP Server
Connect your Supabase projects to Cursor, Claude, Windsurf, and other AI assistants.
The Model Context Protocol (MCP) standardizes how Large Language Models (LLMs) talk to external services like Supabase. It connects AI assistants directly with your Supabase project and allows them to perform tasks like managing tables, fetching config, and querying data. See the full list of tools.
Configuration options and tools
See the Supabase MCP Server docs for the full list of available tools and configuration options.
The docs also feature an interactive URL builder to populate configuration options for you.
Usage with AI SDK's MCP Client
The @supabase/mcp-server-supabase package exports createToolSchemas() to populate input and output schemas for Vercel AI SDK's MCP client. This allows Supabase MCP tools to be treated as static tools with client-side validation and inferred TypeScript types for their inputs and outputs.
import { createToolSchemas } from '@supabase/mcp-server-supabase';
import { createMCPClient } from '@ai-sdk/mcp';
import { streamText } from 'ai';
const mcpClient = await createMCPClient({
transport: {
type: 'http',
url: 'https://mcp.supabase.com/mcp',
},
});
const tools = await mcpClient.tools({
schemas: createToolSchemas(),
});
const result = streamText({ model, tools, prompt: '...' });
for (const step of await result.steps) {
for (const toolResult of step.staticToolResults) {
if (toolResult.toolName === 'get_project_url') {
toolResult.input; // { project_id: string }
toolResult.output; // { url: string }
}
}
}
createToolSchemas() accepts similar filtering options as the MCP server's URL parameters:
features: Restrict to specific feature groups (e.g. ['database', 'docs']). Defaults to all default feature groups.
projectScoped: When true, omits project_id from tool input schemas and excludes account-level tools — use when connecting to a server configured with project_ref. Defaults to false.
readOnly: When true, excludes mutating tools — use when connecting to a server configured with read_only=true. Defaults to false.
const mcpClient = await createMCPClient({
transport: {
type: 'http',
url: 'https://mcp.supabase.com/mcp?project_ref=<project-ref>&read_only=true&features=database,docs',
},
});
const tools = await mcpClient.tools({
schemas: createToolSchemas({
features: ['database', 'docs'],
projectScoped: true,
readOnly: true,
}),
});
[!NOTE]
This server does not send structuredContent in MCP tool results. AI SDK falls back to parsing JSON from content text.
For more information, see Schema Definition and Typed Tool Outputs in the AI SDK docs.
Self-hosting the MCP endpoint
The @supabase/mcp-server-supabase package exports createSupabaseMcpHandler() to serve the tools over HTTP from your own endpoint. It accepts the same SupabaseMcpServerOptions as createSupabaseMcpServer(), most importantly platform.
The handler speaks the current protocol revision only. It is created with legacy: 'reject', so a client that only speaks the 2025-era protocol receives an HTTP 400 instead of being served.
When platform carries a per-request credential, create the handler per request and close it when the response finishes. The handler closes over the platform you supply, so a shared one serves every request with that platform.
A long-lived handler is fine when the platform is meant to be shared, a service-account token for example. Create it once and close() it at shutdown rather than per response, since close() tears down the subscription router and refuses later requests.
import { createServer } from 'node:http';
import { toNodeHandler } from '@modelcontextprotocol/node';
import { createSupabaseMcpHandler } from '@supabase/mcp-server-supabase';
import { createSupabaseApiPlatform } from '@supabase/mcp-server-supabase/platform/api';
const server = createServer((req, res) => {
const accessToken = getAccessTokenFromRequest(req); // your own auth
const handler = createSupabaseMcpHandler({
platform: createSupabaseApiPlatform({ accessToken }),
});
// `close()` aborts in-flight exchanges, so close on `res` finishing rather
// than when the handler resolves, which would cut streaming responses short.
res.on('close', () => {
handler.close().catch((error) => console.error(error));
});
toNodeHandler(handler)(req, res).catch((error) => console.error(error));
});
toNodeHandler comes from @modelcontextprotocol/node, which is not a dependency of this package. Install it alongside.
Other MCP servers
@supabase/mcp-server-postgrest
The PostgREST MCP server allows you to connect your own users to your app via REST API. See more details on its project README.
Resources
For developers
See CONTRIBUTING for details on how to contribute to this project.
License
This project is licensed under Apache 2.0. See the LICENSE file for details.