Atlas / MCP servers / henkdz / Self-Hosted Supabase

Self-Hosted SupabaseBLOCK

mcp/henkdz/self-hosted-supabase

An MCP Server for your Self Hosted Supabase

Verdict
BLOCK
Grade
D
Trust score
64 /100
Exposed tools
43 35r · 7w · 1d
Transport
stdio · streamable-http
License
—
Stars
138
01

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 (authenticated or service_role role).
  • Privileged tools require a service_role JWT (HTTP mode) or direct database/service-key access (stdio mode).

Schema & Migrations

Read from source at commit a1c289448a6eOBSERVED · 2026-10-07
02

Connect

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-code
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]
claude-desktop
{
  "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}"
      }
    }
  }
}
03

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.

ToolRiskDescription
apply_migrationwriteApplies a SQL migration script and records it in the supabase_migrations.schema_migrations table within a transaction.
create_auth_userwriteCreates a new user directly in auth.users. WARNING: Requires plain password, insecure. Use with extreme caution.
delete_auth_userdestructiveDeletes a user from auth.users by their ID. Requires service_role key and direct DB connection.
execute_sqlwriteExecutes an arbitrary SQL query against the database. SECURITY: Requires service_role key or direct database connection.
explain_queryreadGets 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_typesreadGenerates TypeScript types from the database schema using the Supabase CLI (
get_advisorsreadGets 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_userreadRetrieves details for a specific user from auth.users by their ID.
get_cron_job_historyreadGets execution history for pg_cron jobs including status and timing. Requires pg_cron to be installed.
get_database_connectionsreadRetrieves information about active database connections from pg_stat_activity.
get_database_statsreadRetrieves statistics about database activity and the background writer from pg_stat_database and pg_stat_bgwriter.
get_edge_function_detailsreadGets 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_definitionreadGets the full source code definition of a database function. Use argument_types if there are overloaded functions with the same name.
get_index_statsreadGets detailed statistics for a specific index including usage counts and size.
get_logsreadGets 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_urlreadReturns the configured Supabase project URL for this server.
get_rls_statusreadChecks if Row Level Security (RLS) is enabled on tables and shows the number of policies. Can filter by schema and/or table.
get_storage_configreadGets storage configuration for Supabase Storage buckets. Returns bucket settings including file size limits, allowed MIME types, and public/private status.
get_trigger_definitionwriteGets the full definition of a trigger, optionally including its function source code.
get_vector_index_statsreadGets usage statistics and size information for pgvector indexes.
list_auth_usersreadLists users from the auth.users table.
list_available_extensionsreadLists all PostgreSQL extensions available for installation, including those already installed.
list_constraintsreadLists all constraints (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, EXCLUDE) in the database. Can filter by schema, table, and type.
list_cron_jobsreadLists all scheduled cron jobs from pg_cron extension. Returns empty array if pg_cron is not installed.
list_database_functionsreadLists 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_logsreadLists execution logs for edge functions from the function_edge_logs table.
list_edge_functionsreadLists all deployed Supabase Edge Functions. Returns empty array if edge functions are not available or none are deployed.
list_extensionsreadLists all installed PostgreSQL extensions in the database.
list_foreign_keysreadLists all foreign key relationships in the database. Can filter by schema and/or table.
list_indexesreadLists all indexes in the database with their definitions and sizes. Can filter by schema and/or table.
list_migrationsreadLists applied database migrations recorded in supabase_migrations.schema_migrations table.
list_realtime_publicationsreadLists PostgreSQL publications, often used by Supabase Realtime.
list_rls_policiesreadLists all Row Level Security (RLS) policies in the database. Can filter by schema and/or table name.
list_storage_bucketsreadLists all storage buckets in the project.
list_storage_objectsreadLists objects within a specific storage bucket, optionally filtering by prefix.
list_table_columnsreadLists all columns for a table with detailed metadata including types, defaults, and constraints.
list_tablesreadLists all accessible tables in the connected database, grouped by schema.
list_triggersreadLists all triggers on tables. Can filter by schema and/or table name.
list_vector_indexesreadLists all pgvector indexes (ivfflat, hnsw) in the database. Returns empty array if pgvector is not installed or no vector indexes exist.
rebuild_hookswriteAttempts to restart the pg_net worker. Requires the pg_net extension to be installed and available.
update_auth_userwriteUpdates fields for a user in auth.users. WARNING: Password handling is insecure. Requires service_role key and direct DB connection.
update_storage_configwriteUpdates storage configuration for a Supabase Storage bucket. Can modify file size limits, allowed MIME types, and public/private status.
verify_jwt_secretreadChecks if the Supabase JWT secret is configured for this server.
04

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.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (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)

HIGHHard-coded secrets · secret.db_uri · CWE-798, CWE-321
smithery.yaml:57
databaseUrl: postgresql://postgres:password@localhost:5432/postgres
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
src/server/http-server.ts:144
`http://127.0.0.1:${this.options.port}`,
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
README.md:246
--db-url postgresql://postgres:password@localhost:5432/postgres \
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
README.md:256
# export DATABASE_URL=postgresql://postgres:password@localhost:5432/postgres
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
README.md:272
--db-url postgresql://postgres:password@db:5432/postgres
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
README.md:309
"<your-db-url>", // e.g., "postgresql://postgres:password@host:port/postgres"
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
delete_auth_user
Why it matters. 1 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.codacy.yml
.codacy.yml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.no_license · CWE-1104
Why it matters. no LICENSE file and no repo licence
Fix. add a licence
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/client/client.test.ts:13
import { SelfhostedSupabaseClient } from '../../client/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/client/client.test.ts:14
import type { SelfhostedSupabaseClientOptions } from '../../types/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/helpers/mocks.ts:6
import type { SelfhostedSupabaseClient } from '../../client/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/helpers/mocks.ts:7
import type { ToolContext } from '../../tools/types.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/helpers/mocks.ts:8
import type { SqlExecutionResult, SqlSuccessResponse, SqlErrorResponse } from '../../types/index.js';
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:541
- "http://127.0.0.1:3000"
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@modelcontextprotocol/sdk, @supabase/supabase-js, commander, express, jsonwebtoken, pg, zod, @types/bun
Why it matters. 13 dependency range(s) float
Fix. pin exact versions or ship a lockfile
INFOPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
README.md:215
- `service_role`: Full access (all tools including privileged ones).
INFOPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
README.md:589
- `service_role`: Full access to all tools (regular + privileged)
INFOPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
<tool:list_database_functions>:1
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.

Audited 2026-10-07 · audit v0.4.1 · source sha a1c289448a6efull audit observations/trust-audit/mcp-server/henkdz__self-hosted-supabase.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-07a1c289448a6eBLOCKD64first audit
06

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.

Advertisement