MCP do Supabase: como limitar o que o agente pode fazer no seu banco

configuração de segurança do MCP do Supabase limitando permissões de escrita do agente no banco
Resposta rápida

O MCP do Supabase é um servidor remoto em https://mcp.supabase.com/mcp, e a segurança dele é configurada por parâmetros na própria URL. Sem opt-in, o read_only vale false: o cliente MCP pode executar SQL destrutivo, tipo DROP TABLE e DELETE FROM. Para limitar, você trava o projeto com project_ref, liga read_only=true (que roda tudo como usuário Postgres de leitura e desabilita as ferramentas de escrita) e recorta os grupos em features. O próprio Supabase recomenda apontar o MCP para um projeto de desenvolvimento, com dados não produtivos ou ofuscados, nunca para produção

Fala aí, beleza? O servidor MCP do Supabase aceita escrita por padrão

O parâmetro read_only tem valor padrão false, então, sem opt-in explícito, o cliente MCP pode executar SQL destrutivo no seu banco: DROP TABLE, DELETE FROM, o pacote completo

Isso não é boato de thread de Twitter, está aberto como issue de segurança no repositório do projeto, com o título Default-unsafe configuration allows destructive operations without opt-in

Este post NÃO é sobre instalar

É sobre recortar o que o agente alcança antes de você clicar em aprovar a conexão

O que você precisa ter em mãos antes:

Antes de montar a URL, junta essas quatro coisas

  • O Project ID do projeto: ele aparece nas configurações do projeto e é exatamente o valor que vai no parâmetro project_ref
  • A decisão de QUAL projeto conectar: a documentação oficial do Supabase orienta usar o servidor MCP com um projeto de desenvolvimento, e garantir que esse ambiente tenha dados não produtivos ou ofuscados
  • A noção do que é a service_role: as chaves de serviço contornam o Row Level Security por design, e a documentação diz que elas nunca devem ser usadas no navegador nem expostas a clientes
  • O cliente MCP que vai consumir isso: pode ser o Claude Code via transporte HTTP, ou o servidor local servido pelo Supabase CLI, que fica em http://localhost:54321/mcp para desenvolvimento

Repara que a configuração de segurança aqui não mora num painel de permissões

Ela mora em parâmetros de query na URL do servidor, e isso é ótimo: dá pra ler a linha inteira e saber o que o agente pode fazer 🙂

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 114 aulas
  • 4 projetos
  • 9h 18min

Como limitar o MCP do Supabase passo a passo:

A ordem importa, porque cada parâmetro fecha uma porta diferente

  1. Trave o escopo com project_ref

Sem isso, o servidor enxerga sua conta inteira

Com o project_ref, ele fica restrito a um único projeto, e as ferramentas de nível de conta somem: list_projects e list_organizations deixam de ficar disponíveis

https://mcp.supabase.com/mcp?project_ref=abc123

O erro comum deste passo: procurar um campo chamado "project ref" no painel e não achar

Ele aparece como Project ID nas configurações do projeto

  1. Ligue o read_only=true

Esse é o parâmetro que muda o jogo de verdade

Com ele ligado, o servidor entra em modo somente leitura e executa todas as queries como um usuário Postgres de leitura

Na prática, o execute_sql passa a rodar como esse usuário read-only, e insert, update e delete ficam bloqueados

Junto disso, as ferramentas que alteram estado ficam desabilitadas: apply_migration, create_project, pause_project, restore_project, deploy_edge_function, create_branch, delete_branch, merge_branch, reset_branch, rebase_branch e update_storage_config

O erro comum deste passo (e é o mais recorrente de todos): assumir que o modo somente leitura é o padrão

Não é

Se o parâmetro não está na URL, o servidor aceita escrita

  1. Escolha os grupos em features

O parâmetro features define quais grupos de ferramentas ficam ativos

Os grupos são: account, database, docs (a base de conhecimento), debugging, development, functions (edge functions), branching (plano pago) e storage

Todos vêm habilitados por padrão, exceto storage

Ou seja: se você não declarar nada, tu leva quase tudo junto

Declarar features é o jeito de dizer "só isso aqui, obrigado"

  1. Junte tudo numa URL só

Os parâmetros são combináveis, então a configuração final é uma linha

https://mcp.supabase.com/mcp?project_ref=abc123&read_only=true&features=database,docs,debugging

Lê essa URL em voz alta antes de aprovar: um projeto, somente leitura, três grupos

O erro comum deste passo: copiar a URL de exemplo de um tutorial e esquecer de trocar o project_ref pelo seu

  1. Registre no Claude Code

A documentação do Supabase traz o comando de instalação via transporte HTTP

claude mcp add --scope project --transport http supabase "https://mcp.supabase.com/mcp?features=docs,account,database,debugging,development,functions,branching"

Esse comando é o da doc, com os grupos abertos

Se a ideia é restringir, a URL que vai entre aspas é a SUA, aquela do passo 4, com project_ref e read_only dentro

A alternativa equivalente é declarar o servidor no arquivo .mcp.json, usando "type": "http" e a mesma URL

  1. Autentique pelo navegador

O servidor hospedado usa dynamic client registration com OAuth 2.1, ou seja, login pelo navegador

Não é token pessoal colado dentro de arquivo

O Personal Access Token segue existindo como alternativa manual, mas para dois casos específicos: ambientes de CI, onde o fluxo de navegador não rola, e clientes MCP que não suportam registro dinâmico

O que esses limites não resolvem:

Agora a parte que a maioria dos tutoriais pula

Configurar bem os parâmetros reduz o estrago possível, mas não fecha a categoria de risco inteira

O sintoma:

Dado privado sai do banco sem ninguém ter pedido

Ninguém digitou "me mostra a tabela de tokens"

O agente fez isso sozinho, obedecendo instrução que ele leu em algum lugar

A causa:

Em julho de 2025, pesquisadores da General Analysis demonstraram publicamente o cenário

Um ticket de suporte contendo instruções escondidas leva o agente a fazer SELECT numa tabela privada (integration_tokens) e devolver o conteúdo dentro do próprio ticket

O detalhe que faz a coisa funcionar: o agente operava com service_role, que por design ignora o RLS

Isso é prompt injection, e é um problema de quem lê o conteúdo, não de quem configurou a URL

Quanto mais autonomia você dá, mais superfície aparece, e isso vale pra qualquer setup de deixar o agente rodando tarefas sozinho, não só pra banco

E o que o Supabase diz sobre isso?

A posição pública deles é clara em dois pontos: o MCP não faz bypass de proteções de banco como Row Level Security, que seguem aplicadas, e não há incidente reportado de cliente Supabase com vazamento de dados via MCP

As camadas que eles citam são modo somente leitura, escopo por projeto, grupos de features e encapsulamento dos resultados de query

E aqui está a parte honesta: o próprio Supabase afirma que essas medidas reduzem o risco mas não eliminam, e que "guardrails sozinhos não bastam"

Prompt injection segue como preocupação número um mesmo em modo somente leitura

Como prevenir:

  • Não usar service_role no agente, já que ela ignora o RLS por design
  • Apontar o MCP para projeto de desenvolvimento, com dados não produtivos ou ofuscados
  • Manter escrita fora do escopo com read_only=true, pra que uma instrução injetada no máximo leia, nunca altere

Tome cuidado com o raciocínio de que "é só leitura, então tá tranquilo"

Leitura é exatamente o vetor da demonstração acima

Qual configuração usar em cada cenário?

Cada contexto pede um recorte diferente, se liga

Cenário Servidor Configuração
Explorar schema e documentação num projeto de dev https://mcp.supabase.com/mcp project_ref fixo, read_only=true, features enxuto (ex: database,docs,debugging)
Desenvolvimento local com o Supabase CLI http://localhost:54321/mcp Servidor local, sem depender do projeto hospedado
CI ou cliente MCP sem registro dinâmico https://mcp.supabase.com/mcp PAT como alternativa manual, já que o fluxo de navegador não é possível
Produção Nenhum A documentação orienta usar o MCP com projeto de desenvolvimento, não com produção

O primeiro cenário é o que mais aparece no dia a dia: você quer que o modelo entenda o schema e consulte a base de conhecimento, e ponto

Para isso, escrita não serve pra nada, então read_only=true não te custa NADA em capacidade útil

O segundo é o caso do desenvolvimento local: o servidor MCP fica em http://localhost:54321/mcp, servido pelo próprio Supabase CLI, sem depender do projeto hospedado

O terceiro é a exceção que a doc reconhece, não a regra

E o quarto tem resposta pronta: produção é o cenário que a documentação orienta evitar

Se você já convive com agentes que agem nas pull requests, o raciocínio é o mesmo aqui: definir o alcance antes é mais barato que auditar depois

Conclusão

Em 03/02/2026 o servidor MCP do Supabase entrou na lista de connectors oficiais do Claude, o que permite executar SQL, alterar schema, fazer deploy de edge functions e gerenciar branches dentro da conversa

É mto massa em termos de conveniência

E é justamente por isso que revisar o escopo virou urgente: quanto mais fácil conectar, mais gente conecta sem olhar a URL

Próximo passo concreto, leva uns dois minutos: abre a URL do seu servidor MCP, confere se project_ref e read_only estão lá, e recorta features pro mínimo que o seu uso exige

Se a URL estiver limpa demais, ela provavelmente está permissiva demais 😀

até o próximo post!

Perguntas frequentes

O MCP do Supabase é seguro para conectar num projeto de produção?

A recomendação oficial do Supabase é não fazer isso. A documentação orienta usar o servidor MCP com um projeto de desenvolvimento, garantindo que esse ambiente tenha dados não produtivos ou ofuscados.

Como faço para o agente só ler meu banco, sem poder escrever nada?

Adiciona read_only=true na URL do servidor MCP do Supabase. Com isso, o execute_sql passa a rodar como um usuário Postgres somente leitura, e insert, update e delete ficam bloqueados.

O que muda quando eu coloco o project_ref na URL do MCP?

O servidor deixa de enxergar sua conta inteira e fica restrito a um único projeto. As ferramentas de nível de conta, como list_projects e list_organizations, deixam de ficar disponíveis.

O MCP do Supabase consegue burlar o RLS (Row Level Security)?

A posição pública do Supabase é que o MCP não faz bypass do RLS, que segue aplicado normalmente. O ponto de atenção é outro: a chave service_role ignora o RLS por design, e é ela que aparece no caso de vazamento demonstrado pela General Analysis.

Preciso gerar um token pessoal (PAT) para autenticar o MCP do Supabase?

Não como regra. O servidor hospedado usa dynamic client registration com OAuth 2.1, ou seja, login pelo navegador. O Personal Access Token continua existindo como alternativa manual, mas só para ambientes de CI ou clientes MCP sem suporte a registro dinâmico.

Quais ferramentas ficam desabilitadas no modo read_only do MCP do Supabase?

Ficam fora do ar as ferramentas que alteram estado: apply_migration, create_project, pause_project, restore_project, deploy_edge_function, create_branch, delete_branch, merge_branch, reset_branch, rebase_branch e update_storage_config. O execute_sql continua ativo, mas rodando como usuário Postgres de leitura.



Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares