Skip to main content
Glama
portdev0

Supabase MCP Server

by portdev0
server.py8.74 kB
""" Supabase MCP Server - A Model Context Protocol server for Supabase database operations. This server provides tools for interacting with a Supabase database, including: - Reading rows from tables - Creating records in tables - Updating records in tables - Deleting records from tables Environment variables: - SUPABASE_URL: The URL of your Supabase project - SUPABASE_SERVICE_KEY: The service role key for your Supabase project """ import os from typing import Dict, List, Any, Optional, Union from contextlib import asynccontextmanager from collections.abc import AsyncIterator from dataclasses import dataclass from dotenv import load_dotenv from supabase import create_client, Client from mcp.server.fastmcp import FastMCP, Context # Load environment variables load_dotenv() # Create a dataclass for our application context @dataclass class SupabaseContext: """Context for the Supabase MCP server.""" client: Client @asynccontextmanager async def supabase_lifespan(server: FastMCP) -> AsyncIterator[SupabaseContext]: """ Manages the Supabase client lifecycle. Args: server: The FastMCP server instance Yields: SupabaseContext: The context containing the Supabase client """ # Get environment variables supabase_url = os.getenv("SUPABASE_URL") supabase_key = os.getenv("SUPABASE_SERVICE_KEY") if not supabase_url or not supabase_key: raise ValueError( "Missing environment variables. Please set SUPABASE_URL and SUPABASE_SERVICE_KEY." ) # Initialize Supabase client supabase_client = create_client(supabase_url, supabase_key) try: yield SupabaseContext(client=supabase_client) finally: # No explicit cleanup needed for Supabase client pass # Create the MCP server mcp = FastMCP( "Supabase Database", description="MCP server for interacting with Supabase databases", lifespan=supabase_lifespan ) @mcp.tool() def read_table_rows( ctx: Context, table_name: str, columns: str = "*", filters: Optional[Dict[str, Any]] = None, limit: Optional[int] = None, order_by: Optional[str] = None, ascending: bool = True ) -> List[Dict[str, Any]]: """ Read rows from a Supabase table with optional filtering, ordering, and limiting. Use this tool to query data from a specific table in the Supabase database. You can select specific columns, filter rows based on conditions, limit the number of results, and order the results. Args: ctx: The MCP context table_name: Name of the table to read from columns: Comma-separated list of columns to select (default: "*" for all columns) filters: Dictionary of column-value pairs to filter rows (default: None) limit: Maximum number of rows to return (default: None) order_by: Column to order results by (default: None) ascending: Whether to sort in ascending order (default: True) Returns: List of dictionaries, each representing a row from the table Example: To get all users: read_table_rows(table_name="users") To get specific columns: read_table_rows(table_name="users", columns="id,name,email") To filter rows: read_table_rows(table_name="users", filters={"is_active": True}) To limit results: read_table_rows(table_name="users", limit=10) To order results: read_table_rows(table_name="users", order_by="created_at", ascending=False) """ supabase = ctx.request_context.lifespan_context.client # Start building the query query = supabase.table(table_name).select(columns) # Apply filters if provided if filters: for column, value in filters.items(): query = query.eq(column, value) # Apply ordering if provided if order_by: order_method = "order" if ascending else "order" query = getattr(query, order_method)(order_by, ascending=ascending) # Apply limit if provided if limit: query = query.limit(limit) # Execute the query response = query.execute() # Return the data return response.data @mcp.tool() def create_table_records( ctx: Context, table_name: str, records: Union[Dict[str, Any], List[Dict[str, Any]]] ) -> Dict[str, Any]: """ Create one or multiple records in a Supabase table. Use this tool to insert new data into a specific table in the Supabase database. You can insert a single record or multiple records at once. Args: ctx: The MCP context table_name: Name of the table to insert records into records: A dictionary for a single record or a list of dictionaries for multiple records Returns: Dictionary containing the created records and metadata Example: To create a single record: create_table_records( table_name="users", records={"name": "John Doe", "email": "john@example.com"} ) To create multiple records: create_table_records( table_name="users", records=[ {"name": "John Doe", "email": "john@example.com"}, {"name": "Jane Smith", "email": "jane@example.com"} ] ) """ supabase = ctx.request_context.lifespan_context.client # Insert the records response = supabase.table(table_name).insert(records).execute() # Return the response return { "data": response.data, "count": len(response.data) if response.data else 0, "status": "success" if response.data else "error" } @mcp.tool() def update_table_records( ctx: Context, table_name: str, updates: Dict[str, Any], filters: Dict[str, Any] ) -> Dict[str, Any]: """ Update records in a Supabase table that match the specified filters. Use this tool to modify existing data in a specific table in the Supabase database. You provide the new values and filter conditions to identify which records to update. Args: ctx: The MCP context table_name: Name of the table to update records in updates: Dictionary of column-value pairs with the new values filters: Dictionary of column-value pairs to filter which rows to update Returns: Dictionary containing the updated records and metadata Example: To update all active users' status: update_table_records( table_name="users", updates={"status": "premium"}, filters={"is_active": True} ) """ supabase = ctx.request_context.lifespan_context.client # Start building the query query = supabase.table(table_name).update(updates) # Apply filters for column, value in filters.items(): query = query.eq(column, value) # Execute the query response = query.execute() # Return the response return { "data": response.data, "count": len(response.data) if response.data else 0, "status": "success" if response.data else "error" } @mcp.tool() def delete_table_records( ctx: Context, table_name: str, filters: Dict[str, Any] ) -> Dict[str, Any]: """ Delete records from a Supabase table that match the specified filters. Use this tool to remove data from a specific table in the Supabase database. You provide filter conditions to identify which records to delete. Args: ctx: The MCP context table_name: Name of the table to delete records from filters: Dictionary of column-value pairs to filter which rows to delete Returns: Dictionary containing the deleted records and metadata Example: To delete inactive users: delete_table_records( table_name="users", filters={"is_active": False} ) """ supabase = ctx.request_context.lifespan_context.client # Start building the query query = supabase.table(table_name).delete() # Apply filters for column, value in filters.items(): query = query.eq(column, value) # Execute the query response = query.execute() # Return the response return { "data": response.data, "count": len(response.data) if response.data else 0, "status": "success" if response.data else "error" } if __name__ == "__main__": # Run the server with stdio transport mcp.run()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/portdev0/supabase-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server