Supabase MCP Server

by Sentry01
Verified
# Supabase MCP Server Implementation Plan This document outlines the plan for creating a Model Context Protocol (MCP) server that connects to Supabase, allowing AI assistants like GitHub Copilot to interact with your Supabase database. ## Table of Contents - [Overview](#overview) - [Prerequisites](#prerequisites) - [Implementation Steps](#implementation-steps) - [Server Architecture](#server-architecture) - [Configuration](#configuration) - [Security Considerations](#security-considerations) - [Installation Guide](#installation-guide) - [Usage Examples](#usage-examples) - [Troubleshooting](#troubleshooting) ## Overview The Supabase MCP server will act as a bridge between AI assistants (like GitHub Copilot) and your Supabase database. This allows the AI to: 1. Understand your database schema 2. Know about tables and relationships 3. Assist with query writing 4. Provide context-aware suggestions related to your data model ## Prerequisites - Node.js 18+ installed - npm or yarn package manager - Supabase project with admin API key - VS Code with Copilot/MCP support - Git ## Implementation Steps ### 1. Create Server Package ```bash mkdir mcp-server-supabase cd mcp-server-supabase npm init -y ``` ### 2. Install Dependencies ```bash npm install @supabase/supabase-js @modelcontextprotocol/server dotenv ``` ### 3. Basic Server Structure Create these files: - `src/index.js` - Main entry point - `src/supabase-client.js` - Supabase connection handling - `src/schema-provider.js` - Database schema extraction - `src/query-handler.js` - Safe query execution - `.env.example` - Environment variable template - `config.js` - Configuration management ### 4. Server Implementation Details #### src/index.js This file will initialize the MCP server and connect the components: ```javascript const { MCPServer } = require('@modelcontextprotocol/server'); const { getSupabaseClient } = require('./supabase-client'); const { SchemaProvider } = require('./schema-provider'); const { QueryHandler } = require('./query-handler'); const config = require('./config'); async function main() { try { // Initialize Supabase client const supabaseClient = getSupabaseClient(config.supabase.url, config.supabase.key); // Create providers const schemaProvider = new SchemaProvider(supabaseClient); const queryHandler = new QueryHandler(supabaseClient, config.security.allowedQueries); // Initialize MCP server const server = new MCPServer({ name: 'mcp-server-supabase', version: '1.0.0', }); // Register handlers server.registerHandler('getSchema', async () => { return await schemaProvider.getFullSchema(); }); server.registerHandler('getTableInfo', async (params) => { return await schemaProvider.getTableInfo(params.tableName); }); server.registerHandler('executeQuery', async (params) => { return await queryHandler.execute(params.query, params.params); }); // Start the server await server.start(); console.log('MCP Supabase server is running'); } catch (error) { console.error('Failed to start MCP server:', error); process.exit(1); } } main(); ``` #### src/supabase-client.js ```javascript const { createClient } = require('@supabase/supabase-js'); function getSupabaseClient(url, apiKey) { if (!url || !apiKey) { throw new Error('Supabase URL and API key must be provided'); } return createClient(url, apiKey, { auth: { persistSession: false }, }); } module.exports = { getSupabaseClient }; ``` #### src/schema-provider.js ```javascript class SchemaProvider { constructor(supabaseClient) { this.supabase = supabaseClient; } async getFullSchema() { // Query Supabase for full database schema const { data, error } = await this.supabase .rpc('get_schema_information', {}); if (error) throw new Error(`Failed to get schema: ${error.message}`); return data; } async getTableInfo(tableName) { // Get detailed information about a specific table const { data, error } = await this.supabase .rpc('get_table_information', { table_name: tableName }); if (error) throw new Error(`Failed to get table info: ${error.message}`); return data; } } module.exports = { SchemaProvider }; ``` #### src/query-handler.js ```javascript class QueryHandler { constructor(supabaseClient, allowedQueryTypes = ['SELECT']) { this.supabase = supabaseClient; this.allowedQueryTypes = allowedQueryTypes; } validateQuery(queryString) { // Basic SQL injection prevention and query type validation const normalizedQuery = queryString.trim().toUpperCase(); // Check if the query starts with allowed query types const isAllowed = this.allowedQueryTypes.some( type => normalizedQuery.startsWith(type) ); if (!isAllowed) { throw new Error(`Query type not allowed. Allowed types: ${this.allowedQueryTypes.join(', ')}`); } return true; } async execute(queryString, params = {}) { // Validate query before execution this.validateQuery(queryString); // Execute the query through Supabase const { data, error } = await this.supabase .rpc('execute_query', { query_string: queryString, query_params: params }); if (error) throw new Error(`Query execution failed: ${error.message}`); return data; } } module.exports = { QueryHandler }; ``` #### config.js ```javascript require('dotenv').config(); module.exports = { supabase: { url: process.env.SUPABASE_URL, key: process.env.SUPABASE_SERVICE_KEY, }, server: { port: process.env.PORT || 3000, }, security: { allowedQueries: process.env.ALLOWED_QUERY_TYPES ? process.env.ALLOWED_QUERY_TYPES.split(',') : ['SELECT'], } }; ``` #### .env.example ``` SUPABASE_URL=https://your-project-ref.supabase.co SUPABASE_SERVICE_KEY=your-service-key PORT=3000 ALLOWED_QUERY_TYPES=SELECT ``` ### 5. Supabase Database Functions You'll need to create these stored procedures in Supabase: 1. `get_schema_information()` - Returns database schema 2. `get_table_information(table_name TEXT)` - Returns info about specific table 3. `execute_query(query_string TEXT, query_params JSONB)` - Safely executes queries ## Server Architecture ``` ┌─────────────────────┐ ┌───────────────────┐ │ │ │ │ │ VS Code + Copilot │◄────►│ MCP Protocol │ │ │ │ │ └─────────────────────┘ └─────────┬─────────┘ │ ▼ ┌─────────────────────┐ │ │ │ Supabase MCP Server │ │ │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ │ │ Supabase Database │ │ │ └─────────────────────┘ ``` ## Configuration Add the Supabase MCP server to your VS Code `settings.json`: ```json "mcp": { "inputs": [], "servers": { // ...existing servers... "mcp-server-supabase": { "command": "node", "args": [ "/path/to/mcp-server-supabase/src/index.js" ], "env": { "SUPABASE_URL": "https://your-project-ref.supabase.co", "SUPABASE_SERVICE_KEY": "your-service-key", "ALLOWED_QUERY_TYPES": "SELECT" } } } } ``` ## Security Considerations 1. **API Key Management**: - Use a scoped API key with minimum required permissions - Store API keys securely, never commit to version control - Consider using a key rotation strategy 2. **Query Restrictions**: - Default to SELECT-only for safety - Consider implementing a query allowlist approach - Add rate limiting to prevent abuse 3. **Data Protection**: - Avoid exposing PII or sensitive data - Implement row-level security in Supabase - Consider adding data masking for sensitive fields ## Installation Guide ### Local Development 1. Clone the repository ```bash git clone https://github.com/yourusername/mcp-server-supabase.git cd mcp-server-supabase ``` 2. Install dependencies ```bash npm install ``` 3. Create `.env` file from example ```bash cp .env.example .env ``` 4. Edit `.env` with your Supabase credentials 5. Start the server ```bash node src/index.js ``` ### VS Code Integration 1. Update your VS Code `settings.json` with the server configuration 2. Restart VS Code 3. Verify the server is running in the VS Code MCP panel ## Usage Examples Once integrated, you can use the Supabase MCP server in various ways: 1. **Schema exploration:** ``` What tables do I have in my Supabase database? ``` 2. **Table information:** ``` What columns are in the users table? ``` 3. **Query assistance:** ``` Help me write a query to get all users who signed up in the last 7 days ``` ## Troubleshooting **Server won't start** - Check your Node.js version (should be 18+) - Verify your Supabase credentials - Check for error logs in the terminal **Schema not loading** - Verify your Supabase service key has necessary permissions - Check that the database functions are properly created **VS Code can't connect** - Check that the server path in settings.json is correct - Restart VS Code after configuration changes - Verify the server process is running