- RLS policies are enabled and correct on every table a tool can query
- No tool uses the service role key; each one gets the signed-in user's client
- Business rules such as approval checks live in shared functions, not in the tool
- With verify_jwt = false, the auth middleware runs before every MCP handler
- Users approve each MCP client on a consent page hosted on your own site
- Each tool returns only the fields the agent needs; read-only tools say so
Graphic: Vibecode Beratung · Based on the sources below
Your customers already work in ChatGPT and Claude. A new option from Supabase lets them use your app from there too: you give the app its own MCP server, and their agent can call your app’s actions as tools. For a founder, that sounds like a cheap new channel. For whoever answers for security, it is a new entry point into your production data.
The good news is that the design Supabase announced at Supabase Select reuses protections your app should already have. The bad news is the same: if those protections are weak, an agent will find the gaps faster than a human user would. This article lists what to check before you switch it on, ranked by severity.
How the setup works
Supabase ships an MCP Server block that you install from its Library. It copies an Edge Function into supabase/functions/mcp, with an MCP handler, authentication middleware and a whoami tool that reports the caller’s identity. Each tool lives in its own file and is registered in tools/index.ts. The code is yours to change.
The flow runs like this. The customer’s agent starts with your server’s URL. The middleware points it to your project’s OAuth server. The user signs in through your app, approves the client on your consent page, and Supabase Auth issues an access token for that user. Every later tool call carries that token, and each tool receives a Supabase client acting as that user.
Your RLS policies become the agent’s permissions (SEV-1)
Because queries run with the user’s identity, Postgres applies row level security to every tool call. Supabase puts it plainly: your RLS policies decide what each agent can reach.
That makes RLS the first thing to review. A table without RLS, or with a policy that is too broad, is now reachable from any MCP client a user has approved. If your app was built with Lovable or Bolt, work through the common RLS mistakes before you write a single tool.
Imagine a SaaS founder whose invoices table has a policy that only checks whether a user is logged in. In the web app, the interface only ever asks for the user’s own invoices, so nobody notices. A tool that lists invoices has no such interface in front of it.
Keep the service role key out of tools (SEV-1)
The Supabase helpers give each tool a client for the signed-in user, so a tool can be a plain query with no service role key. Check that it stays that way. A coding agent asked to “fix a permission error” in a tool might reach for the service role key, which skips RLS entirely. If that key has ever appeared in client code, follow the steps for exposed API keys as well.
Authentication and consent (SEV-1 to SEV-2)
To connect external agents, Supabase asks you to configure asymmetric signing keys, turn on its OAuth 2.1 server and enable dynamic client registration. Users approve access through an OAuth Consent block in your frontend, and the Auth Site URL must point to the site that hosts that page.
One detail deserves a second look. The Edge Function sets verify_jwt = false, because discovery requests arrive without a token. That is by design, but it means the middleware is now the only gate. Check that withOAuthProtectedResource() and withSupabase({ auth: 'user' }) run before every handler, and that no tool is registered outside that pipeline.
Business rules belong in shared code (SEV-2)
A tool can run a query, call a database function, invoke an Edge Function or use an existing API. Supabase advises keeping business rules in the code the tool calls. Its example is an expense that needs an approval check: the MCP tool should call the same function the app uses for that check. If the rule lives only in your React frontend, the agent path will skip it.
Also decide what each tool returns. Supabase’s example tool selects only id and title, limits results to 20 rows and marks itself with readOnlyHint. Narrow outputs like that limit what leaks if a policy is wrong.
What this means for your project
An MCP server does not add a new security model. It exposes the one you have. If your RLS, key handling and server-side checks are solid, the step is small. If they were generated quickly and never reviewed, fix them first and add tools afterward. Run through the production readiness checklist before you invite agents in.
Planning to open your app to AI agents and unsure whether the foundations hold? Book a free intro call and we will tell you honestly whether a production-readiness review makes sense first.
Frequently asked questions
What does an MCP server for a Supabase app do?
It exposes your app's actions as tools through the Model Context Protocol. Your customers can then use those actions from ChatGPT, Claude or another MCP client after signing in with their existing account.
Does an MCP tool in Supabase bypass row level security?
Not in the setup Supabase describes. Each tool call runs with the signed-in user's Supabase client, so Postgres applies the table's RLS policies. That protection is only as good as the policies you already have.
Why does the Supabase MCP function set verify_jwt to false?
Discovery requests from MCP clients arrive without a token, so the built-in JWT check is turned off. The function's own middleware then verifies the token and sends an OAuth challenge when a request has none.
Where should business rules live when agents call my app?
In the code the tool calls, such as a database function or your existing application API. Supabase's example is an expense approval check: the MCP tool should call the same function the app uses.