Self-Hosted SupabaseBLOCK
An MCP Server for your Self Hosted Supabase
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
[](https://opensource.org/licenses/MIT) [](https://smithery.ai/server/@HenkDz/selfhosted-supabase-mcp)
Overview
This project provides a Model Context Protocol (MCP) server designed specifically for interacting with self-hosted Supabase instances. It bridges the gap between MCP clients (like IDE extensions) and your local or privately hosted Supabase projects, enabling database introspection, management, and interaction directly from your development environment.
This server was built from scratch, drawing lessons from adapting the official Supabase cloud MCP server, to provide a minimal, focused implementation tailored for the self-hosted use case.
Purpose
The primary goal of this server is to enable developers using self-hosted Supabase installations to leverage MCP-based tools for tasks such as:
- Querying database schemas and data.
- Managing database migrations.
- Inspecting database statistics and connections.
- Managing authentication users.
- Interacting with Supabase Storage.
- Generating type definitions.
It avoids the complexities of the official cloud server related to multi-project management and cloud-specific APIs, offering a streamlined experience for single-project, self-hosted environments.
Features (Implemented Tools)
Tools are categorized by privilege level:
- Regular tools are accessible by any authenticated Supabase JWT (
authenticatedorservice_rolerole). - Privileged tools require a
service_roleJWT (HTTP mode) or direct database/service-key access (stdio mode).
Schema & Migrations
a1c289448a6eOBSERVED · 2026-10-07Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add self-hosted-supabase-mcp --env JWT_SECRET=${JWT_SECRET} --env SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY} --env SUPABASE_AUTH_JWT_SECRET=${SUPABASE_AUTH_JWT_SECRET} --env SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY} -- npx -y [email protected]{
"mcpServers": {
"self-hosted-supabase-mcp": {
"command": "npx",
"args": [
"-y",
"[email protected]"
],
"env": {
"JWT_SECRET": "${JWT_SECRET}",
"SUPABASE_ANON_KEY": "${SUPABASE_ANON_KEY}",
"SUPABASE_AUTH_JWT_SECRET": "${SUPABASE_AUTH_JWT_SECRET}",
"SUPABASE_SERVICE_ROLE_KEY": "${SUPABASE_SERVICE_ROLE_KEY}"
}
}
}
}Exposed tools (43)
35 read · 7 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
apply_migration | write | Applies a SQL migration script and records it in the supabase_migrations.schema_migrations table within a transaction. |
create_auth_user | write | Creates a new user directly in auth.users. WARNING: Requires plain password, insecure. Use with extreme caution. |
delete_auth_user | destructive | Deletes a user from auth.users by their ID. Requires service_role key and direct DB connection. |
execute_sql | write | Executes an arbitrary SQL query against the database. SECURITY: Requires service_role key or direct database connection. |
explain_query | read | Gets the execution plan for a SQL query. WARNING: With ANALYZE enabled, the query is actually executed which will modify data for write operations. |
generate_typescript_types | read | Generates TypeScript types from the database schema using the Supabase CLI ( |
get_advisors | read | Gets security or performance advisory notices for the database. Based on Supabase Splinter linting rules. Helps identify issues like missing RLS policies, unindexed foreign keys, and other common problems. |
get_auth_user | read | Retrieves details for a specific user from auth.users by their ID. |
get_cron_job_history | read | Gets execution history for pg_cron jobs including status and timing. Requires pg_cron to be installed. |
get_database_connections | read | Retrieves information about active database connections from pg_stat_activity. |
get_database_stats | read | Retrieves statistics about database activity and the background writer from pg_stat_database and pg_stat_bgwriter. |
get_edge_function_details | read | Gets detailed information about a specific Supabase Edge Function by ID or slug. Returns null if not found or edge functions are not available. |
get_function_definition | read | Gets the full source code definition of a database function. Use argument_types if there are overloaded functions with the same name. |
get_index_stats | read | Gets detailed statistics for a specific index including usage counts and size. |
get_logs | read | Gets logs for a Supabase service. Attempts to query the analytics stack first, then falls back to PostgreSQL CSV logs. Returns logs from the last 24 hours. Note: Log availability depends on your self-hosted installation configuration. |
get_project_url | read | Returns the configured Supabase project URL for this server. |
get_rls_status | read | Checks if Row Level Security (RLS) is enabled on tables and shows the number of policies. Can filter by schema and/or table. |
get_storage_config | read | Gets storage configuration for Supabase Storage buckets. Returns bucket settings including file size limits, allowed MIME types, and public/private status. |
get_trigger_definition | write | Gets the full definition of a trigger, optionally including its function source code. |
get_vector_index_stats | read | Gets usage statistics and size information for pgvector indexes. |
list_auth_users | read | Lists users from the auth.users table. |
list_available_extensions | read | Lists all PostgreSQL extensions available for installation, including those already installed. |
list_constraints | read | Lists all constraints (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, EXCLUDE) in the database. Can filter by schema, table, and type. |
list_cron_jobs | read | Lists all scheduled cron jobs from pg_cron extension. Returns empty array if pg_cron is not installed. |
list_database_functions | read | Lists all user-defined database functions (stored procedures). Can filter by schema, name pattern, or language. Identifies SECURITY DEFINER functions which may have elevated privileges. |
list_edge_function_logs | read | Lists execution logs for edge functions from the function_edge_logs table. |
list_edge_functions | read | Lists all deployed Supabase Edge Functions. Returns empty array if edge functions are not available or none are deployed. |
list_extensions | read | Lists all installed PostgreSQL extensions in the database. |
list_foreign_keys | read | Lists all foreign key relationships in the database. Can filter by schema and/or table. |
list_indexes | read | Lists all indexes in the database with their definitions and sizes. Can filter by schema and/or table. |
list_migrations | read | Lists applied database migrations recorded in supabase_migrations.schema_migrations table. |
list_realtime_publications | read | Lists PostgreSQL publications, often used by Supabase Realtime. |
list_rls_policies | read | Lists all Row Level Security (RLS) policies in the database. Can filter by schema and/or table name. |
list_storage_buckets | read | Lists all storage buckets in the project. |
list_storage_objects | read | Lists objects within a specific storage bucket, optionally filtering by prefix. |
list_table_columns | read | Lists all columns for a table with detailed metadata including types, defaults, and constraints. |
list_tables | read | Lists all accessible tables in the connected database, grouped by schema. |
list_triggers | read | Lists all triggers on tables. Can filter by schema and/or table name. |
list_vector_indexes | read | Lists all pgvector indexes (ivfflat, hnsw) in the database. Returns empty array if pgvector is not installed or no vector indexes exist. |
rebuild_hooks | write | Attempts to restart the pg_net worker. Requires the pg_net extension to be installed and available. |
update_auth_user | write | Updates fields for a user in auth.users. WARNING: Password handling is insecure. Requires service_role key and direct DB connection. |
update_storage_config | write | Updates storage configuration for a Supabase Storage bucket. Can modify file size limits, allowed MIME types, and public/private status. |
verify_jwt_secret | read | Checks if the Supabase JWT secret is configured for this server. |
Trust audit
BLOCKgrade D · trust 64/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- UNDECLARED (1 observation(s))
- Network
- declared (1 observation(s))
- Shell
- none-observed
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (19)
databaseUrl: postgresql://postgres:password@localhost:5432/postgres
`http://127.0.0.1:${this.options.port}`,--db-url postgresql://postgres:password@localhost:5432/postgres \
# export DATABASE_URL=postgresql://postgres:password@localhost:5432/postgres
--db-url postgresql://postgres:password@db:5432/postgres
"<your-db-url>", // e.g., "postgresql://postgres:password@host:port/postgres"
delete_auth_user
.codacy.yml
import { SelfhostedSupabaseClient } from '../../client/index.js';import type { SelfhostedSupabaseClientOptions } from '../../types/index.js';import type { SelfhostedSupabaseClient } from '../../client/index.js';import type { ToolContext } from '../../tools/types.js';import type { SqlExecutionResult, SqlSuccessResponse, SqlErrorResponse } from '../../types/index.js';- "http://127.0.0.1:3000"
@modelcontextprotocol/sdk, @supabase/supabase-js, commander, express, jsonwebtoken, pg, zod, @types/bun
- `service_role`: Full access (all tools including privileged ones).
- `service_role`: Full access to all tools (regular + privileged)
Lists all user-defined database functions (stored procedures). Can filter by schema, name pattern, or language. Identifies SECURITY DEFINER functions which may have elevated privileges.
Gates applied: no_behavioural_pass, no_license.
a1c289448a6efull audit observations/trust-audit/mcp-server/henkdz__self-hosted-supabase.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-07 | a1c289448a6e | BLOCK | D | 64 | first audit |
Questions
What is the Self-Hosted Supabase MCP server?
An MCP Server for your Self Hosted Supabase
What tools does Self-Hosted Supabase expose?
43 in total: 35 read-only, 7 that write, and 1 that can delete or overwrite (delete_auth_user). Every one is listed on this page with its risk.
Is Self-Hosted Supabase safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (64/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does Self-Hosted Supabase need?
It reads JWT_SECRET, SUPABASE_ANON_KEY, SUPABASE_AUTH_JWT_SECRET and SUPABASE_SERVICE_ROLE_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does Self-Hosted Supabase run?
It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as self-hosted-supabase-mcp at 1.2.0.
How current is this page?
The grade is for one exact copy of the source (a1c289448a6e), read on 2026-10-07. The repository is watched and re-audited when it changes.