Skip to content

Supabase MCP Server

Database Auth Required

The Supabase MCP server provides comprehensive database operations, project management, and real-time functionality for your Supabase projects directly through Claude.

This server enables full Supabase project management including:

  • Database schema creation and management
  • SQL query execution and migrations
  • User authentication and management
  • Project configuration and monitoring
  • Real-time subscriptions and Edge Functions
  • TypeScript type generation
Required Environment Variables
# Add to your environment file
SUPABASE_ACCESS_TOKEN=sb_your_access_token_here
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your_anon_key_here

Get your tokens from:

  1. Access Token: Supabase Account Settings
  2. Project URL & Keys: Your project’s Settings > API page
Project Operations
// List all projects
await listProjects()
// Get specific project details
await getProject({ id: "project-id" })
// Pause/restore projects
await pauseProject({ project_id: "project-id" })
await restoreProject({ project_id: "project-id" })
Edge Functions Management
// List all Edge Functions
await listEdgeFunctions({ project_id: "project-id" })
// Get function details
await getEdgeFunction({
project_id: "project-id",
function_slug: "hello-world"
})
// Deploy new Edge Function
await deployEdgeFunction({
project_id: "project-id",
name: "user-profile-handler",
files: [
{
name: "index.ts",
content: `
import { serve } from 'https://deno.land/[email protected]/http/server.ts'
serve(async (req: Request) => {
const { name } = await req.json()
return new Response(
JSON.stringify({ message: `Hello, ${name}!` }),
{ headers: { 'Content-Type': 'application/json' } }
)
})
`
}
]
})
Branch Management
// Create development branch
await createBranch({
project_id: "project-id",
name: "feature-branch",
confirm_cost_id: "cost-confirmation-id"
})
// List all branches
await listBranches({ project_id: "project-id" })
// Merge branch to production
await mergeBranch({ branch_id: "branch-id" })
// Reset branch to specific migration
await resetBranch({
branch_id: "branch-id",
migration_version: "20240101000000"
})

Create and manage database schemas:

Database Schema Creation
// Create a new table with RLS
await applyMigration({
project_id: "your-project-id",
name: "create_posts_table",
query: `
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
content TEXT,
author_id UUID REFERENCES auth.users(id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
published BOOLEAN DEFAULT false
);
-- Enable Row Level Security
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- Create policies
CREATE POLICY "Users can view published posts" ON posts
FOR SELECT USING (published = true);
CREATE POLICY "Users can manage their own posts" ON posts
FOR ALL USING (auth.uid() = author_id);
`
})
// Verify table creation
const tables = await listTables({
project_id: "your-project-id",
schemas: ["public"]
})
Row Level Security Policies
-- User can only read their own profile
CREATE POLICY "Users can view own profile" ON profiles
FOR SELECT USING (auth.uid() = user_id);
-- Admin users can read all data
CREATE POLICY "Admins can view all" ON profiles
FOR SELECT USING (
EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = auth.uid()
AND role = 'admin'
)
);
-- Public read, authenticated write
CREATE POLICY "Public read access" ON posts
FOR SELECT USING (published = true);
CREATE POLICY "Authenticated write access" ON posts
FOR INSERT WITH CHECK (auth.uid() IS NOT NULL);
Error Handling Patterns
try {
await executeSql({
project_id: "your-project-id",
query: "SELECT * FROM non_existent_table"
})
} catch (error) {
// Handle different error types
if (error.message.includes('relation "non_existent_table" does not exist')) {
console.log('Table not found - creating it first')
} else if (error.message.includes('permission denied')) {
console.log('Check RLS policies and user permissions')
} else {
console.log('Unexpected database error:', error.message)
}
}
astro-basics Integration Pattern
// Common workflow for astro-basics project
// 1. Get current project info
const project = await getProject({ id: process.env.SUPABASE_PROJECT_ID })
// 2. Check existing tables
const tables = await listTables({
project_id: project.id,
schemas: ["public"]
})
// 3. Apply new migrations if needed
await applyMigration({
project_id: project.id,
name: "add_comments_table",
query: commentTableSchema
})
// 4. Generate updated TypeScript types
const updatedTypes = await generateTypescriptTypes({
project_id: project.id
})
// 5. Update environment configuration
const apiUrl = await getProjectUrl({ project_id: project.id })
const anonKey = await getAnonKey({ project_id: project.id })
  • Rate Limits: Subject to Supabase API rate limits (typically 1000 requests/hour for free tier)
  • SQL Execution: Some operations require database owner permissions
  • Branch Operations: Development branches are a paid feature
  • Migration History: Cannot rollback migrations - use branches for testing

Authentication errors:

  • Verify your access token has the required permissions
  • Check project ID is correct
  • Ensure project is not paused

SQL execution errors:

  • Verify table and column names are correct
  • Check RLS policies if getting permission denied
  • Use qualified names (schema.table) when necessary

Type generation issues:

  • Ensure you have read permissions on all tables
  • Check for circular dependencies in foreign keys
  • Verify schema names are correct