Let execute_sql run as a project role you choose
Maintainers usually reply within 1 day
@barryroodt is already working on this.
Since Nov 9, 2026.
Assessment
This issue has not been assessed yet.
Description
The gap
execute_sql runs in one of two modes today: as postgres, or read-only with --read-only. An agent that needs some writes, say inserting into a drafts table but never deleting, has only the destructive-SQL confirmation between it and everything else.
That confirmation reads query text, and #523, #531 and #532 show the limits: a MERGE ... WHEN MATCHED THEN DELETE or a comment-prefixed UPDATE runs without a prompt, while an INSERT whose text holds ; drop asks for one (and in an unattended run, times out and loses the write). The thread on #532 notes that classifier coverage is still being decided, and #426 adds a parser, which will narrow the gap but can't close it for every statement Postgres accepts.
The idea
Let execute_sql run as a Postgres role the project owner creates for the agent, for example --db-role drafts_agent. The owner gives that role exactly the grants and RLS policies the agent needs. Then the database decides: the MERGE ... DELETE fails with permission denied for table films whatever the classifier thinks, and confirmations stay as a UX layer for the writes the role is allowed to make.
It would sit between the two modes that exist now, and fits with the least-privilege requests in #239 and #255.
One constraint
It can't be SET ROLE prepended to the query. The session would still be postgres, so the agent's own SQL could run RESET ROLE and get every privilege back. It needs a login that is only that role, the way read-only mode runs as a separate user rather than downgrading a postgres session.
The Management API already issues short-lived logins through POST /v1/projects/{ref}/cli/login-role (read_only, password, TTL). A variant that issues a login holding only a named project role, used by /database/query when a role is given, might be one way to build it. You'll know the internals far better than I do, so take that only as a pointer.
Context
I run an MCP server where agents are Postgres roles that can't write certain columns, and checking those roles by hand was error-prone, so I wrote a small checker: counsel guard. It reads what a role can actually reach. On the supabase/postgres 17.11 image, a role that was granted service_role can read and delete every decrypted secret in Vault, which is the kind of thing a scoped --db-role would let people rule out up front.
Happy to help test this, or to write up the role setup for the docs, if it's useful.
- Dominant language
- TypeScript
- Stars
- 3k
- Forks
- 432
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 52
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from supabase/mcp
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
postgrestRequest returns PostgREST error responses as successful resultsPossibly taken @irisfield claimed this 4 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
execute_sql runs MERGE ... WHEN MATCHED THEN DELETE without the destructive confirmationPossibly taken @barryroodt claimed this 5 days ago. OpenMCP
Difficulty 3/5 1-2 days Newbie friendliness 69/100
supabase/mcp#532 · 4 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
list_tables: schemas says it defaults to all schemas but defaults to ["public"], so the RLS advisory silently reports on a partial databasePossibly taken @PranshulSoni claimed this 75 days ago. Openbug MCP
Difficulty 4/5 3-5 days Newbie friendliness 55/100
supabase/mcp#395 · 4 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Feature MCP
Difficulty 3/5 1-2 days Newbie friendliness 65/100
supabase/mcp#361 · 3 comments ·
Maintainers usually reply within 1 day
Similar issues
-
Wallet functions throws TypeError when the wallet has no account IDPossibly taken @Medhansh-741 claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
hiero-ledger/hiero-sdk-js#4781 · 1 comment ·
Maintainers usually reply within 1 day
-
good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
dataforgoodfr/mediterranean-rescue#91 ·
Maintainers usually reply within 1 day
-
transformer-directives: `@apply` drops a utility whose CSS is a substring of an earlier one'sPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
Add: KRT TVOpenapproved check:passed streams:add
Difficulty 1/5 Under an hour Newbie friendliness 65/100
iptv-org/iptv#58647 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
milind-soni/OpenMausBot#5829 ·
Maintainers usually reply within 1 day