C1 Identity & least privilege
Minimal 0.30 / 1.00
The server acts with whatever Supabase personal access token it is given, and that token reaches every organization and project the user belongs to, with full management rights. By default nothing narrows it: all projects are reachable, account-level tools (create, pause, restore projects) are on, and SQL runs read-write. An operator can pin the server to one project with --project-ref, which removes the project parameter from most tools, but the pin does not cover every path. The token itself is never narrowed or exchanged.
C2 Approval gates
Minimal 0.33 / 1.00
As a tool server, Supabase MCP leaves approval to the MCP host and its main contribution is risk signalling. All 36 tools carry readOnly/destructive hints, and the SQL, migration, deploy, branch and storage-config tools are marked destructive, but execute_sql mixes reads and writes in one tool and there is no dry-run. The server has its own confirmation step for destructive SQL and paid resources, bound to the exact query, but the stdio CLI never turns it on, and the confirmation logic does not cover every path. A wrongly approved call can drop or delete production data irreversibly.
C3 Tool & action scoping
Minimal 0.33 / 1.00
Most tools are narrow and typed (strict zod schemas, region enums, ISO timestamps, injected project ids), and unknown arguments are rejected centrally. But the tools that matter most are raw passthroughs: execute_sql and apply_migration send any SQL the model writes, deploy_edge_function uploads arbitrary code, query_logs takes arbitrary log SQL, and search_docs any GraphQL. The default tool set includes all of these against every project in the account. Tool groups can be selected with --features and writes disabled with --read-only, but neither is the default.
C4 Code-execution isolation
Minimal 0.47 / 1.00
The code-execution surface is remote: SQL sent to the project's Postgres through the Management API, and edge-function code deployed to Supabase's runtime. Nothing runs on the machine hosting the MCP server, but by default the SQL runs read-write directly on the target (often production) database with no read-only session or restricted role. An opt-in --read-only flag asks the API to run SQL in read-only mode and blocks the write tools. Deployed functions are public endpoints with full network egress, and the model may set verify_jwt to false.
C5 Untrusted input blast radius
Minimal 0.25 / 1.00
Database rows, logs and notebook cells can contain attacker-written text, and the server wraps those results in a random-ID boundary with a note telling the model not to follow instructions inside it. That is spotlighting, a weak defence, and it is missing on other sources such as table and column comments, edge-function source, migrations and advisors. Results are plain text with no structured provenance, and the server's own instructions tell the model to run an npx install command. In the default configuration the same session reads untrusted rows, holds the whole account, and can run destructive SQL or deploy a public function that sends data anywhere, with no human required by the server.
C6 Memory, context & configuration integrity
N/A · full credit 1.00 / 1.00
The server keeps no memory and loads no workspace files: configuration comes from CLI flags and two environment variables, and nothing the model writes is read back as instructions by the server. Data written into a database can of course be read in a later session, but that is untrusted input (C5), not server memory.
C7 Third-party extensions
N/A · full credit 1.00 / 1.00
The server loads or launches no third-party code at runtime: no plugins, no child processes, no dynamic imports. Its tools call the Supabase Management API and the Supabase docs API only. Note that its instructions suggest the host model install a Supabase agent skill via npx, which is outside the server's own runtime.
C8 Secrets & sensitive-data protection
Minimal 0.33 / 1.00
The access token comes from a CLI flag or environment variable, is attached only as a request header, and is never logged or returned to the model; errors are reduced to name and message. The API-key tool deliberately returns only client-safe anon/publishable keys. There is no telemetry. But nothing redacts sensitive data in SQL results, and the token is a long-lived, account-wide credential, so a leak (or a model reading secrets stored in the database) has a large blast radius. An opt-in URL flow keeps new edge-function secret values out of the model entirely.
C9 Audit & traceability
Minimal 0.28 / 1.00
In the default stdio configuration the server records nothing about the tool calls it makes. The library offers an onToolCall callback that receives the tool name, arguments, annotations and result, but the CLI never sets it, and failures in it are swallowed. The local --http mode prints one line per request with the method, tool name and client, without arguments. There is no tamper-evident audit trail; any record of what happened lives in Supabase's own platform logs, which this repo does not control.
C10 Limits & kill switch
Minimal 0.33 / 1.00
The server bounds very little of its own work. get_logs uses fixed queries with a 100-row limit, and the logs API caps windows at 24 hours, but execute_sql has no row or size cap, no API call has a timeout, and there are no rate limits on SQL, deploys, or creating paid projects and branches. Stopping the stdio process ends the session, but work already submitted to Supabase (migrations, branch creation, deploys) continues server-side. In --http mode a client disconnect closes the handler.