MCP nativo: seus dados como ferramentas
para Claude, Cursor e agentes
Agentes de IA são tão úteis quanto os dados que alcançam. O jeito comum de dar esse alcance — colar credenciais de banco em prompts e arquivos de configuração — é um incidente de segurança agendado. O Catcher Data expõe os seis produtos da plataforma como tools MCP tipadas, com autenticação, escopo e guarda-corpo pensados para agentes. Este post percorre o contrato do manifest, o ciclo de vida do token e as quatro camadas de defesa entre o agente e o dado.
O gap entre o agente e o dado
Todo time que coloca agentes de IA para trabalhar chega à mesma parede: o agente precisa consultar o banco, buscar na base de conhecimento, ler um objeto do storage. As soluções usuais são ruins em graus diferentes.
- Colar a connection string no prompt ou no config do agente. O agente ganha acesso total, sem escopo, sem revogação granular, com a credencial circulando em texto plano por logs e históricos de conversa.
- Escrever uma API intermediária para cada integração. Funciona, mas agora você mantém um microsserviço de cola por agente.
- Dar um navegador ao agente e deixá-lo raspar o dashboard. Frágil, lento, e quebra a cada mudança de layout.
O problema não é o agente; é a interface. Banco, busca e storage falam protocolos desenhados para aplicações, não para modelos. Faltava a camada que traduz "dados" para o vocabulário que um agente entende: ferramentas tipadas, com permissão explícita e verificada do lado do servidor.
MCP em dois parágrafos
O Model Context Protocol (MCP) é um protocolo aberto que padroniza como sistemas expõem contexto e ações para modelos de linguagem. Um servidor MCP publica um catálogo de tools — cada uma com nome, descrição e schema de entrada tipado. O cliente (Claude, Cursor, um agente seu) descobre as tools disponíveis, decide quando chamá-las e recebe resultados estruturados.
A consequência prática: em vez de ensinar o modelo a montar SQL contra uma connection string, você entrega uma tool db_run_sql com schema definido, autenticação própria e regras aplicadas no servidor. O modelo pede; o servidor decide o que pode e executa. O contrato mora no protocolo, não no prompt.
Seis produtos, um endpoint, ~54 tools
O Catcher Data expõe um servidor MCP nativo em https://data-api.catcher.one/v1/mcp, com transporte Streamable HTTP. Nativo significa que não há wrapper de terceiros nem ponte improvisada: é a própria plataforma publicando cerca de 54 tools tipadas sobre os produtos de dados.
| Produto | Exemplos de tools |
|---|---|
| Wiki (RAG) | wiki_ask, wiki_search, wiki_upsert_page |
| Vector | busca semântica e híbrida, ingestão de documentos |
| Database | db_run_sql com SQL guard |
| Storage | operações sobre objetos no storage S3-compatível |
| Cache | leitura e escrita de chaves no Redis dedicado |
O MCP é o sexto produto da plataforma — a porta de entrada dos outros cinco para agentes. A conexão com o Claude Code é um comando:
claude mcp add --transport http catcher-data \
https://data-api.catcher.one/v1/mcp \
--header "Authorization: Bearer <token>"
Cursor e qualquer cliente MCP com transporte HTTP conectam no mesmo endpoint, com o mesmo header.
O manifest é o contrato
Antes de conectar qualquer coisa, um GET /v1/mcp/manifest — parte da superfície de gestão da conta, restrita a owner e admin — devolve o contrato completo do servidor: o endpoint, o catálogo de tools com seus escopos, a lista de escopos disponíveis e um connect hint pronto para colar no cliente. Encurtado:
GET /v1/mcp/manifest
{
"endpoint": "https://data-api.catcher.one/v1/mcp",
"transport": "streamable-http",
"tools": [
{ "name": "wiki_ask", "scope": "wiki:read" },
{ "name": "wiki_upsert_page", "scope": "wiki:write" },
{ "name": "db_run_sql", "scope": "db:read" }
// ... ~54 tools no total
],
"scopes": [
"wiki:read", "wiki:write", "vec:read", "vec:write",
"db:read", "db:write", "store:read", "store:write",
"cache:read"
],
"connect": {
"hint": "claude mcp add --transport http catcher-data
https://data-api.catcher.one/v1/mcp
--header \"Authorization: Bearer <ctc_mcp_...>\""
}
}
Isso muda o fluxo de integração de duas formas. Primeiro, elimina a doc desatualizada como modo de falha: o catálogo que o manifest devolve é o mesmo que o cliente MCP descobre em runtime — se a tool existe, ela está ali; se está ali, existe. Segundo, orienta o desenho do token: como cada tool declara o escopo que exige, você lista as tools que o agente precisa, soma os escopos, e esse é o token. Nada de "dá acesso total que depois a gente restringe".
O manifest também serve de superfície de auditoria. Quando a plataforma ganha uma tool nova, ela aparece no catálogo antes de qualquer agente poder chamá-la — e um diff periódico do manifest responde "o que mudou na superfície exposta aos meus agentes" sem depender de release notes. Para quem trata acesso de agente como acesso de produção, esse diff entra na mesma rotina de revisão que qualquer mudança de permissão.
Ciclo de vida do token
A credencial do agente é um personal access token (PAT), criado por usuário via API ou console:
POST /v1/mcp/tokens
{
"label": "agente-suporte",
"scopes": ["wiki:read", "vec:read", "db:read"],
"expires_in_days": 30
}
// resposta — o segredo aparece UMA única vez
{ "token": "ctc_mcp_9f2c1a...", "label": "agente-suporte", ... }
O ciclo tem quatro momentos, e cada um fecha uma porta:
- Mint. O token nasce com label, escopos declarados e TTL opcional (
expires_in_days). O segredoctc_mcp_...é exibido uma única vez, na criação. Depois disso nem o console consegue reexibi-lo — o servidor guarda apenas o hash. Se o segredo vazar do seu lado, a resposta é revogar e mintar outro, não procurar onde ele ficou salvo. - Uso. O agente envia o token como
Authorization: Bearerem cada chamada. Cada tool é verificada contra os escopos do token, no servidor, a cada requisição. - Expiração. Se você deu TTL, o token morre sozinho no prazo. Agentes de tarefa — um sprint, uma migração, um experimento — merecem TTL curto por padrão.
- Revogação. Um
DELETEno token revoga na hora. A chamada seguinte do agente recebe 401 — não existe janela de cache nem propagação pendente.
Os escopos seguem o formato produto:verbo, e o mapa é direto:
| Escopo | O que libera |
|---|---|
wiki:read |
Perguntar (wiki_ask), buscar e ler páginas da wiki |
wiki:write |
Criar, atualizar e remover páginas |
vec:read |
Busca semântica e híbrida nas coleções |
vec:write |
Ingerir e remover documentos |
db:read |
db_run_sql em modo leitura — o padrão do guard |
db:write |
Escrita e DDL, com o SQL guard ainda ativo |
store:read / store:write |
Ler e gravar objetos no storage |
cache:read |
Ler chaves do cache dedicado |
Um agente que só responde perguntas recebe wiki:read e vec:read — e mais nada. Se ele for comprometido, o raio de dano é exatamente o que esses dois escopos alcançam.
Duas práticas baratas que o modelo de PAT viabiliza: um token por agente, nunca um token compartilhado — o label identifica o dono e cada chamada fica atribuível; e rotação por recriação — mintar o substituto, trocar no agente, revogar o antigo, sem janela em que os dois precisem coexistir por mais que minutos.
Camadas de defesa
O desenho parte do princípio de que o chamador pode errar — ou ser induzido a errar por prompt injection. Por isso a autorização não é uma verificação; são quatro muros em sequência, todos aplicados no servidor:
- Escopo do token. A tool chamada exige um escopo que o token não tem? A chamada morre ali. O escopo foi declarado no mint e não muda em runtime — nenhum prompt convence o servidor a ampliá-lo.
- RBAC por usuário, com deny vencendo. Além dos escopos, cada usuário carrega overrides de allow e deny por tool, geridos via
PUT /v1/mcp/grants. Em qualquer conflito, deny vence — sempre. Dá para liberarwiki:readinteiro e ainda negar uma tool específica para um usuário específico; um allow adicionado depois, por engano, não fura um deny existente. - SQL guard. O
db_run_sqlpassa por um guard próprio: read-only por padrão, escrita e DDL apenas com flags explícitas, eGRANT,REVOKEeCREATE USERbloqueados sempre — não existe flag que os libere. O agente consulta e opera dados; não administra o banco, mesmo que o modelo alucine o comando com convicção. - Isolamento de tenant. Todo identificador resolve dentro da empresa dona do token. Um ID forjado de outra conta não resolve — devolve 404, não os dados alheios. Essa camada é atacada continuamente pela nossa suíte de pentest, junto com as outras três.
O cenário que esse desenho cobre, narrado: um agente com token válido lê um documento envenenado que o instrui a exfiltrar dados de outro cliente e escalar privilégios no banco. Ele esbarra no escopo (o token não tem db:write), no deny (a tool sensível foi negada àquele usuário), no SQL guard (o GRANT morre antes de chegar ao banco) e no tenant (o ID alheio não resolve). Quatro muros, cada um suficiente sozinho contra esse ataque — e nenhum deles depende de o modelo se comportar.
RFC 9728 na prática
Falta o detalhe que separa integração robusta de integração frágil: o que acontece quando a credencial está ausente, expirada ou revogada. A resposta comum da indústria é um 401 seco — e o cliente fica adivinhando onde e como se autenticar.
O servidor MCP do Catcher Data responde 401 com o Protected Resource Metadata da RFC 9728: um corpo estruturado que identifica o recurso protegido e aponta como obter credenciais válidas. Clientes MCP que implementam a RFC usam esses metadados para orientar o fluxo de autenticação — detectar o que falta, pedir o token certo, reconectar — em vez de falhar em silêncio ou despejar um stack trace no usuário.
O efeito prático para quem opera agentes: o token expira no meio de uma tarefa e o cliente sabe explicar exatamente o que aconteceu e qual o próximo passo. O erro de autenticação vira parte do contrato, tão tipado quanto as tools. O formato exato da resposta está na documentação do MCP.
Um ticket, três tools
O que isso habilita, narrado. Chega um ticket: "o pedido 88317 consta pago, mas o acesso não liberou". O agente de suporte carrega um token com wiki:read, vec:read e db:read.
- O agente chama
wiki_askcom a pergunta "o que libera o acesso depois do pagamento confirmado?". Recebe a resposta fundamentada no runbook do time, com as páginas-fonte citadas. - Busca "88317" nas coleções de tickets passados via vector search. A busca é híbrida — o braço lexical garante que o número exato não seja enterrado pelos vizinhos semânticos do cosine.
- Consulta o status real do pedido com
db_run_sql. O guard opera em modo leitura, e nenhuma instrução de administração passa por ele, aconteça o que acontecer no prompt.
Três chamadas, três produtos, um token de escopo mínimo. O agente responde com o runbook citado e o estado real do banco — e tudo que ele podia fazer estava declarado no manifest e no token antes da primeira chamada.
Por que não raspar o dashboard
A alternativa que aparece com frequência é dar um browser ao agente e deixá-lo navegar no admin como um humano navegaria. Comparando com honestidade:
- Scraping quebra a cada mudança de UI. Um catálogo MCP é um contrato tipado que o cliente descobre em runtime.
- Um browser logado carrega a sessão inteira do usuário — todo clique possível vira superfície de ataque. Uma tool MCP carrega um escopo.
- Auditar screenshots é impraticável. Chamada de tool é evento estruturado, com dono identificado pelo token.
- Parse de HTML renderizado contra resposta estruturada em uma chamada HTTP: mais lento, mais caro, mais frágil.
Screen-scraping é o que você faz quando o dado está preso atrás de uma UI. Quando a plataforma fala MCP nativamente, a ponte via browser vira atrito puro. Seus dados passam a ser ferramentas — com autenticação, escopo e guarda-corpo — hospedados no Brasil, na região de São Paulo.
Conecte um agente aos seus dados
Crie a conta, gere um token MCP com escopo mínimo no console e rode o comando de conexão. Os produtos de dados ficam disponíveis como tools no mesmo endpoint, com dados na região de São Paulo.