All guidesSupabase RLS and keys
On this page

Supabase change

Supabase

Supabase personal access token scopes: how do I give an agent or CI a token for one project with only the permissions it needs?

By Ohad Krispin, founder of VibeRaven · LinkedIn

Since scoping became generally available on September 28, 2026 (Supabase's post is from October 26), every personal access token you create in the Dashboard is scoped by default: you choose organizations or projects, Read or Read-write for each permission, and an expiry up to one year out, and a scoped token starts with sbp_fc. For a coding agent that only reads one project, scope it to that project, start from the No access preset rather than Read-only (which includes API key secrets), and turn on Database Read, which covers execute_sql for read-only queries, list_tables and generate_typescript_types in the Supabase MCP server. A token never has more access than your own role, its scope cannot be edited after creation, your old full-access tokens keep working with a Legacy badge, and the browser flow of supabase login still creates a full-access token today, so pass a scoped one with supabase login --token or SUPABASE_ACCESS_TOKEN. Checked against Supabase's post and docs on 2026-10-28.

Build a token for one agent

On the access tokens page, choose the resources (the Dashboard recommends a project-level scope), the permissions and the expiry. The review screen expands each permission into the Management API endpoints and MCP tools it covers, and shows a Low, Medium or High risk banner for the mix of reach and write access. Copy the value before you close the page: it is shown once.

Which permission each Supabase MCP tool needs

From the permission table in the Personal Access Tokens docs. Each tool checks before it runs and returns a tool error when the permission is missing. With Database Read, a SQL write through execute_sql returns a Postgres permission error rather than a 403.

execute_sql, list_tables, list_extensions,
  generate_typescript_types          Database (Read)
list_migrations                      Migrations (Read)
apply_migration                      Migrations (Read-write)
get_logs, query_logs                 Logs (Read)
get_advisors                         Advisors (Read)
list_edge_functions, get_edge_function  Edge Functions (Read)
deploy_edge_function                 Edge Functions (Read-write)
get_project, get_project_url         Project Settings (Read)
get_publishable_keys                 API Keys (Read)
list_projects                        Projects (account-wide) (Read)
create_branch, merge_branch          Development or Production Branches (Read-write)
search_docs                          always available

A 403 with missing_permissions

When a Management API request lacks a permission, the 403 names it in a missing_permissions field. Check that your own role has that permission, then create a replacement token that includes it: scope and permissions are fixed at creation. A request for a project outside the token's scope gets a plain 403 with no field.

export SUPABASE_ACCESS_TOKEN="sbp_fc..."

# Database Read covers this endpoint
curl "https://api.supabase.com/v1/projects/your-project-ref/types/typescript" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"

# needs Project Settings Read: HTTP 403 without it
curl -i "https://api.supabase.com/v1/projects/your-project-ref" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"

Scoped tokens with the Supabase CLI and in CI

Create the token in the Dashboard and pass it with supabase login --token, or set SUPABASE_ACCESS_TOKEN, which overrides any saved token and is the one to use in CI. supabase link needs Project Settings, API Keys and API Key Secrets, all Read. Database commands that connect with SUPABASE_DB_PASSWORD, such as supabase db push, are not limited by the token at all, so the database password is the real limit on what CI can change there.

supabase login --token sbp_fc...

# CI
export SUPABASE_ACCESS_TOKEN="sbp_fc..."
supabase link --project-ref your-project-ref

A token follows your own role

Every request checks both the token's scope and your current role. If you leave an organization or lose a permission, the token loses it too, and gets it back if your access returns; the token's detail view marks resources you can no longer reach. The Dashboard lets you add a permission your role lacks, but the token cannot use it until your role has it.

Find tokens committed to the repo

Personal access tokens start with sbp_, and scoped ones with sbp_fc. Search the repo and its history for both; a token found there should be deleted in the Dashboard and replaced with a scoped one.

grep -rn "sbp_" --exclude-dir=node_modules --exclude-dir=.git .
git log -p --all -S "sbp_" --oneline

Checklist

Replace a full-access token

  1. 01List the tools that hold a Supabase token: coding agents, MCP configs, CI secrets, deploy scripts.
  2. 02For each one, create a token scoped to its project, with only the permissions its job needs and an expiry that matches it.
  3. 03Start an agent from the No access preset and add Database Read; add Migrations Read-write only if it applies migrations.
  4. 04Swap the new value into the tool or CI secret, run its usual job once, and read any missing_permissions in a 403.
  5. 05Delete the old token in the Dashboard once nothing uses it.

Related

Sources

Official docs behind this checklist

FAQ

FAQ for builders before launch

Do my existing Supabase access tokens stop working?

No. Existing tokens keep working until they expire or you delete them; full-access ones show a Legacy badge, and Create legacy token is still there.

Can I change the scope of a token later?

No. Scope and permissions are fixed at creation, so create a replacement token and swap it in.

Why not use the Read-only preset for an agent?

Because Read-only includes secrets such as API keys. Supabase suggests starting from No access and turning on Database Read.