How to Connect Cursor to Supabase with MCP
Step-by-step guide to connecting Cursor to your Supabase database using a managed MCP server. Schema-aware answers in chat and Composer, real query results, no local install.
You're already in Cursor. Your Supabase project is somewhere else — Auth, Storage, Postgres, the SQL editor you open when you need a count. Every time the AI needs a real answer from those rows, you're querying in the dashboard, copying the output, and pasting it into chat.
Cursor speaks MCP (same protocol Claude Desktop uses). Connect Supabase once and the agent can inspect schema and run queries from the editor, next to the code that uses those tables.
This walkthrough gets Cursor talking to Supabase in a few minutes. For why live queries beat copy-paste, see Ask Cursor About Your Database. Using Claude instead? MCP Server for Supabase. New to MCP? What is an MCP server.
What This Actually Unlocks
With Supabase wired in, Cursor stops inventing your columns:
- "Look at
profilesandsubscriptions. Which users signed up in the last 14 days and still have no active subscription?" — it joins the tables and returns the rows. - "Our RLS policy on
ordersassumes every row has auser_id. Are there any nulls?" - "This Edge Function writes to
events. Do the columns it references match the live table, or would this fail at runtime?" - "How many rows are in
auth.usersvs publicprofiles? List profiles with no matching auth user."
You stop being the clipboard between the SQL editor and chat.
The Two Ways to Connect
Option 1 — Self-hosted. Run a local Postgres MCP server, drop your Supabase password or connection string into a JSON file on disk, restart Cursor when credentials rotate. Works for a solo laptop and a throwaway project. Gets awkward once a team needs the same access, or once a service role key has no business sitting in plaintext on every machine.
Option 2 — Managed gateway (Synra). Save credentials once in the dashboard. Synra encrypts them (AES-256), issues an MCP endpoint URL, and proxies every query. Default is read-only: INSERT, UPDATE, DELETE, and DROP are rejected at the gateway even if the agent tries them. Queries get logged. Nothing to install locally.
Longer comparison: self-hosted vs managed MCP server. Rest of this guide assumes the managed path.
Step 1 — Get Your Supabase Credentials
Two ways in: the API path (easiest in Synra's Supabase form) or the Postgres URI.
Option A — Project URL + service role key
- Open your Supabase project dashboard
- Go to Project Settings → API
- Copy the Project URL — looks like
https://xxxxxxxxxxxx.supabase.co - Copy the service_role key (under Project API keys) — not the
anonkey
The service role key bypasses Row Level Security, so questions like "show me everything in orders" actually work — and so does reading tables your anon key can't see. Treat it like a password. Synra encrypts it at rest; Cursor never gets the key itself.
Option B — Postgres connection string
- Go to Project Settings → Database
- Open Connection string → URI
- Copy the direct connection (port
5432), not the pooler on6543
The pooler is meant for serverless apps that open and close connections constantly. An MCP gateway holds a steadier session, so the direct URI is less flaky. In Synra, paste it under PostgreSQL rather than Supabase.
Both hit the same Postgres database. Most people use Option A with Synra's Supabase form; Option B is fine if you already keep Postgres URIs around.
Step 2 — Save the Connection in Synra
- Sign in at mcpserver.design (the 7-day free trial covers getting started)
- Go to Connections → Add new connection
- Pick Supabase (or PostgreSQL if you're using the URI from Option B)
- Paste your Project URL and service role key — or the Postgres URI
- Click Test connection so Synra can confirm a query actually runs
- Click Save
Credentials sit encrypted at rest (AES-256). The plaintext key stays in Synra's vault.
Want less than full service-role read access? Create a Postgres role with SELECT only on the tables Cursor should see, and use those credentials instead. Staging first covers how to climb from a throwaway project toward production.
Step 3 — Copy Your MCP Endpoint URL
After saving, head to the Endpoints tab. You'll see a URL that looks like this:
https://app.mcpserver.design/api/mcp/aB3xY7zQ9mNpLkRv2wTs
That trailing token is your auth. Anyone with the URL can read the database you connected, so don't paste it into a public gist. You can rotate it from the same screen if it leaks.
Step 4 — Add the MCP Server to Cursor
Cursor reads MCP config from ~/.cursor/mcp.json (every project) or .cursor/mcp.json in a specific project. Global is fine solo. Per-project is better for a team checking config into git — just don't commit the real token; use a secret or a local override.
Open the file (create it if it doesn't exist) and add:
{
"mcpServers": {
"synra-supabase": {
"url": "https://app.mcpserver.design/api/mcp/aB3xY7zQ9mNpLkRv2wTs"
}
}
}
Replace the URL with your own from Step 3, then save the file.
If you already have a Postgres or MySQL connector from another guide, keep both entries under mcpServers — Cursor will list each as a separate tool source.
On older Cursor versions that don't support the
"url"field directly, use a stdio bridge instead:{ "mcpServers": { "synra-supabase": { "command": "npx", "args": ["-y", "mcp-remote", "https://app.mcpserver.design/api/mcp/aB3xY7zQ9mNpLkRv2wTs"] } } }
mcp-remoteproxies a remote HTTP MCP server over stdio. Same result, one more moving part. Skip it if your Cursor build already accepts"url".
Step 5 — Restart Cursor and Verify
Quit Cursor fully (Cmd+Q on Mac, not just closing the window) and reopen it. Then:
- Open Cursor Settings → MCP (or Features → MCP in older builds)
- You should see
synra-supabaselisted with a green status indicator - Click it to see the tools it exposes — typically
list_tables,describe_table,query_table,execute_sql
If the entry shows a red status or "no tools found", jump to the troubleshooting section below.
What to Try First
Open Cursor's chat (Cmd+L). Try one of these to confirm it's working:
- "List the tables in my database."
- "What does the
profilestable look like? Show me the columns and types." - "How many users signed up in the last 7 days?"
If it's working, Cursor picks a tool, runs SQL, and comes back with real rows. After that, ask something you already know the answer to — then ask about subscription mix, stuck payments, or whether your TypeScript types still match the live table. When you ask for code that touches the DB, it often checks schema first instead of guessing names.
Security: What's Actually Happening
If this is a real project (not a toy), keep these in mind:
- Read-only by default. Synra blocks write statements at the gateway:
INSERT,UPDATE,DELETE,DROP,ALTER,TRUNCATE,CREATE,GRANT. An agent-generatedUPDATEdies before it reaches Supabase. You can turn writes on per connection in the dashboard if you really need them; leave the default alone otherwise. - Service role key never reaches Cursor. Cursor only sees the MCP endpoint URL. The key stays encrypted in Synra. Steal the laptop and you still don't have
mcp.jsonholding your Supabase secrets. - RLS is bypassed by the service role. Synra blocks destructive SQL and logs queries. It does not re-apply your RLS policies. Use a staging project or a dedicated read-only Postgres role when the data is sensitive.
- Every query is logged. Dashboard audit log: SQL, who triggered it, when, duration.
- The endpoint token rotates. Committed
mcp.jsonto a public repo? Regenerate the URL. The old one stops working immediately.
For production: start on staging (or a branch), prefer a SELECT-only role when you can, and don't share one endpoint across people who shouldn't see each other's queries.
Troubleshooting
Cursor doesn't list synra-supabase after restart.
The mcp.json file probably has a syntax error. Run cat ~/.cursor/mcp.json | jq . (or paste into jsonlint.com) to validate. The single most common mistake is a trailing comma after the URL line.
Status shows red, "Server transport closed" or similar.
Open the URL from your config in a browser. You should see a JSON response (something like {"jsonrpc":"2.0","error":{...}} is normal — the browser made a GET without the right MCP headers). If you get a 404 or a connection error, the endpoint URL is wrong — recopy it from Synra's Endpoints tab.
Tools list shows nothing, or queries return "credentials not configured". The connection in Synra is probably in a failed state. Go to Connections → click your Supabase entry → click Test connection. If the test fails, fix the credentials in Synra first, not in Cursor.
"Invalid API key" or empty table list after a successful test.
Confirm you pasted the service_role key, not the anon key. Anon is limited by RLS and often can't see the tables you're asking about from an MCP connector.
SSL / connection errors with the Postgres URI.
Use the direct connection string (port 5432) and include SSL as Supabase provides it. The pooler URI on 6543 is a common source of flaky MCP sessions — switch to direct and re-test.
Cursor's agent refuses to use the database tools.
In Cursor's chat, type @ and pick the MCP server explicitly the first time. Once it's seen the tool surface, the agent will use it automatically on subsequent prompts.
Frequently Asked Questions
Does this work with Cursor Composer / Agent mode? Composer and the autonomous agent use the same MCP tool surface as chat, so once the server is registered, every Cursor mode can use it.
Should I use the service role key or the anon key?
Use the service role key (or a dedicated Postgres role with SELECT on the tables you want). The anon key is meant for browser clients and is limited by Row Level Security — most analytics-style questions need broader read access than anon allows.
Does the service role key bypass Supabase RLS? Yes. That's the point for dashboard-style questions — and the reason to treat the key like a password. Synra encrypts it, blocks destructive SQL, and logs queries. Still don't point this at production until you've done the staging-first checklist.
Can I use the Postgres connection string instead of the API keys?
Yes. Supabase is PostgreSQL under the hood. Pick PostgreSQL in Synra and paste the direct connection URI (port 5432) from Project Settings → Database. Prefer that over the pooler on 6543 for this workflow. The general Postgres walkthrough is Connect Cursor to PostgreSQL.
Does Cursor's agent send my database contents to Anthropic / OpenAI? When Cursor uses the MCP tools, it sends query results back to the underlying model so it can reason over them — same as if you'd pasted them into chat manually. If that's not acceptable for your data, connect a sanitized staging project instead of production.
Can Cursor delete or change my Supabase data?
That depends on how the connector is configured — read-only is not a property of MCP itself. On Synra, INSERT, UPDATE, DELETE, DROP, ALTER, and TRUNCATE are blocked at the gateway before they reach your database, even if the model generates a destructive query. If you self-host a connector or wire one up with write-capable credentials, nothing in MCP stops that; you're responsible for that layer yourself.
That's the setup. Cursor can query Supabase without a local MCP process running on your machine.
The 7-day free trial at mcpserver.design covers one database connection — enough to see if the workflow sticks.
Related guides:
- Ask Cursor About Your Database — why live queries beat copy-pasting SQL results
- MCP Server for Supabase — same database, Claude Desktop instead of Cursor
- Connect Cursor to PostgreSQL — any Postgres host, not just Supabase
- Connect Cursor to MySQL — same Cursor setup, MySQL instead of Supabase
- Connect Cursor to SQL Server — same Cursor setup, SQL Server
- Staging First: AI Database Access Without Production — connect staging before prod
- MCP Troubleshooting — when Cursor can't see the tools
- Self-Hosted vs Managed MCP Server — tradeoffs of running your own vs Synra
- What is an MCP Server? — the foundational explainer