Como saber quais ferramentas um servidor MCP expõe antes de usar em produção?

Antes de colocar uma integração pra rodar no projeto do trabalho, liste as ferramentas de um servidor MCP e leia o que cada uma faz. O método do protocolo é o tools/list, enviado pelo cliente ao servidor, e cada ferramenta volta com um inputSchema (JSON Schema com type: object e properties) dizendo quais argumentos ela aceita. Dá pra rodar isso pelo MCP Inspector em modo CLI, separar leitura de escrita pelas anotações readOnlyHint e destructiveHint, e só depois escrever a regra de permissão no Claude Code. Ler a lista é barato, descobrir na produção é caro 🙂
Conectar um servidor MCP sem olhar a lista de ferramentas é entregar a chave do repositório pra um desconhecido muito educado
A lista de ferramentas é o contrato real da integração: não é a descrição bonitinha do README, é o que o servidor de fato oferece pro modelo chamar. Ler essa lista antes é o que separa um teste isolado numa pasta qualquer de um servidor rodando no repo do trabalho
E o melhor: descobrir isso custa um comando
O que você precisa antes de inspecionar um servidor MCP
A lista é curta, mas tem uma pegadinha de versão de Node que derruba muita gente logo no primeiro npx
- Node >= 22.19.0, que é o mínimo do Inspector v2 (o v1 pedia >= 22.7.5)
- A versão atual do pacote
@modelcontextprotocol/inspectorpublicada no npm é a 2.4.0 - O caminho ou o comando do servidor que tu quer inspecionar (por exemplo, o arquivo de entrada do servidor local)
- Claude Code configurado, caso a checagem seja pelo lado do cliente e não do servidor cru
Tome cuidado! O Inspector v2 é pacote único: os sub-pacotes do v1 (inspector-client, inspector-server e inspector-cli) foram descontinuados. Se tu copiou um comando antigo de algum tutorial apontando pra um desses sub-pacotes, é ali que vai quebrar
O código e a documentação de referência ficam no repositório oficial do MCP Inspector
Passo a passo para descobrir as ferramentas que um servidor MCP expõe
A ideia aqui é simples: primeiro tu lê o servidor cru, sem cliente nenhum no meio, e só depois decide se ele entra no projeto
- Rode o
tools/listpelo Inspector em modo CLI e leia a saída
Esse é o método do protocolo MCP pra descobrir as ferramentas de um servidor, enviado pelo cliente ao servidor como uma requisição JSON-RPC
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
npx @modelcontextprotocol/inspector --cli node path/to/server/index.js --method tools/list
O erro comum deste passo: rodar isso com uma versão de Node abaixo de 22.19.0 e achar que o servidor está quebrado, quando quem está fora do mínimo é o ambiente
- Entenda os três modos do Inspector e escolha o certo pro momento
O Inspector roda em três modos selecionados por flag: --web (o padrão), --cli e --tui. O --cli é o que tu quer quando a intenção é despejar a lista, ler e sair, ou quando a checagem vai rodar dentro de um script
O erro comum deste passo: usar o modo web pra uma conferência rápida, se perder clicando na interface e não guardar a saída em lugar nenhum pra comparar depois
- Leia o
inputSchemade cada ferramenta
Cada ferramenta retornada no tools/list traz um inputSchema: um objeto JSON Schema com type igual a "object" e um properties descrevendo os argumentos esperados
{
"inputSchema": {
"type": "object",
"properties": {}
}
}
É aqui que tu descobre o que a ferramenta realmente recebe. Nome e descrição são marketing do servidor, o schema é o que vale
O erro comum deste passo: ler só o nome da ferramenta (delete_thing assusta, sync_state não, e às vezes os dois fazem a mesma bagunça)
- Percorra a paginação por cursor
A resposta de tools/list é paginada por cursor opaco: o cliente manda cursor nos params e a resposta pode trazer um nextCursor apontando pra próxima página
{
"method": "tools/list",
"params": {
"cursor": "cursor-opaco-da-pagina-anterior"
}
}
Repara que a paginação é por cursor, não por número de página. Enquanto vier nextCursor, tem coisa que tu ainda não viu
O erro comum deste passo (e talvez o mais perigoso da lista): olhar a primeira página, achar que aquilo é a lista inteira e liberar o servidor com metade das ferramentas fora do seu radar
- Separe leitura de escrita pelas anotações
O MCP define quatro anotações booleanas de comportamento por ferramenta, que funcionam como vocabulário de risco: readOnlyHint, destructiveHint, idempotentHint e openWorldHint
{
"annotations": {
"readOnlyHint": true,
"destructiveHint": false
}
}
O readOnlyHint é o hint de leitura, ou seja, sinaliza que a ferramenta não modifica o ambiente, e o destructiveHint indica se a modificação é destrutiva, em oposição a aditiva. É com esses dois que tu monta a primeira separação mental entre "isso só lê" e "isso mexe"
O erro comum deste passo: tratar anotação como garantia. Elas são apenas hints e não garantem descrição fiel do comportamento, e a orientação é clara: cliente nunca deve decidir uso de ferramenta com base em anotação vinda de servidor não confiável
- Cheque a capability
listChanged
O servidor pode declarar a capability listChanged, indicando que ele vai emitir notificação quando a lista de ferramentas mudar
Ou seja: a lista que tu leu hoje não é necessariamente a lista de amanhã. Se o servidor declara listChanged, tua auditoria tem prazo de validade
O erro comum deste passo: auditar uma vez, aprovar e nunca mais olhar
- Expanda a inspeção pra além da listagem
O mesmo modo CLI aceita outros métodos, incluindo chamar uma ferramenta específica e listar resources e prompts:
npx @modelcontextprotocol/inspector --cli node path/to/server/index.js --method tools/call --tool-name mytool --tool-arg key=value
npx @modelcontextprotocol/inspector --cli node path/to/server/index.js --method resources/list
npx @modelcontextprotocol/inspector --cli node path/to/server/index.js --method prompts/list
O erro comum deste passo: testar um tools/call de escrita apontando pro ambiente real em vez de um ambiente descartável. Chamada manual é chamada de verdade, os rm -rf da vida ensinam isso do jeito difícil
Se o servidor é seu e tu quer entender a implementação por trás dessas tools, vale entender um código que nunca viu com ajuda do próprio agente antes de sair aprovando permissão
Inspector, /mcp e claude mcp list: qual usar em cada momento
São três caminhos diferentes e MUITA gente troca um pelo outro. Cada um responde uma pergunta distinta:
| Caminho | O que responde | Quando usar | O que não mostra |
|---|---|---|---|
| MCP Inspector em modo CLI | A saída completa de tools/list, com o inputSchema de cada ferramenta e a paginação por cursor |
Antes de conectar o servidor em qualquer cliente, na hora de decidir se ele entra no projeto | Nada sobre como o teu cliente está configurado nem sobre permissão concedida |
/mcp dentro da sessão do Claude Code |
Os servidores conectados, o status deles e as ferramentas disponíveis, incluindo os nomes exatos das ferramentas MCP | Durante a sessão, quando tu precisa do nome exato pra escrever regra de permissão | Não substitui a leitura do inputSchema bruto do servidor |
claude mcp list no terminal |
Os servidores MCP configurados e o status de conexão de cada um, incluindo falha de conexão e pendência de autenticação | Antes de abrir a sessão, pra saber se o servidor sequer conecta ou se falta autenticar | Não é o caminho pra ler argumento de ferramenta nem schema |
A regra prática: Inspector pra auditar o servidor, claude mcp list pra diagnosticar conexão, /mcp pra pegar os nomes com que tu vai escrever a permissão
Como transformar a lista de ferramentas em decisão de permissão
Lista lida, agora vem a parte que importa: virar regra
No Claude Code, as ferramentas de MCP seguem o padrão de nome mcp__<nome-do-servidor>__<nome-da-ferramenta>. Um servidor github com a ferramenta list_issues vira mcp__github__list_issues
E elas exigem permissão explícita. Sem permissão, o Claude enxerga que as ferramentas existem, mas não consegue chamá-las (é por isso que às vezes parece que "o MCP não funciona", quando na verdade ele só não foi autorizado)
O glob só é aceito depois do prefixo literal mcp__<servidor>__, então o segmento do servidor precisa ser explícito:
mcp__puppeteer__*libera todas as tools do servidorpuppeteermcp__github__get_*libera só as que começam comget_
E dá pra fechar tudo de uma vez enquanto tu ainda está estudando o servidor:
{
"permissions": {
"deny": ["mcp__*"]
}
}
Repara como o passo 5 do tutorial se paga sozinho aqui: se tu já separou o que é leitura do que é escrita, o get_* da vida sai natural, sem precisar liberar o servidor inteiro no escuro
Agora o limite honesto, porque prometer segurança fácil é papo furado: anotação é hint, não garantia. A própria documentação do Claude Code avisa que servidores MCP de terceiros são usados por sua conta e risco, que a Anthropic não verificou a corretude nem a segurança de todos eles, e pede cuidado extra com servidores que buscam conteúdo não confiável por causa de risco de prompt injection
Procedência ajuda um pouco. O Registro oficial de MCP lista servidores com nome em formato DNS reverso amarrado a conta do GitHub ou domínio verificado (tipo io.github.usuario/servidor ou com.exemplo/servidor), de modo que só o dono legítimo publica naquele namespace. Hoje são 2.021 servidores ativos ali
Se a ideia é fugir da configuração servidor por servidor, tem também o caminho dos MCPs já embutidos no agente, que muda o trade-off da conversa
O que a prática mostrou sobre confiar (ou não) na lista de ferramentas
Essa história de "ler o que está exposto antes de deixar o agente agir" eu vivi de perto num assunto vizinho: o WebMCP
E já aviso, porque o nome confunde: WebMCP e MCP não são a mesma coisa apesar do nome parecido. WebMCP roda no browser, no lado do cliente, enquanto o MCP conecta o teu projeto a outros serviços, tipo GitHub ou banco de dados. O que os dois compartilham é a ideia central deste post: existe uma lista de ferramentas declarada, e ela é o contrato
No vídeo eu mostro o antes e o depois. Sem a declaração de ferramentas, o agente precisa tirar screenshot da página, usar um modelo de visão pra localizar o elemento e simular clique e digitação como um humano, repetindo o processo quando erra. Com as ferramentas declaradas, ele descobre o que existe pelo código antes mesmo de olhar a página e chama direto a função, recebendo um JSON dizendo se deu certo ou errado
Montei um fluxograma justamente pra deixar essa diferença visível, porque ela muda tudo na sensação de controle
Quando testei com a extensão de inspeção no navegador, apareceram os três cenários que tu vai encontrar na vida real: a página não tem nada declarado (painel em branco), tem (painel preenchido) ou a conexão simplesmente não foi estabelecida. Aquele painel em branco é o equivalente exato de rodar tools/list e não voltar nada: o problema pode ser o servidor, pode ser a conexão, e confundir os dois faz tu debugar o lado errado por meia hora 😅
Montei um projetinho de loja pra testar e abri o próprio código pra mostrar as duas formas de declarar ferramenta: por atributo no HTML (API declarativa) e por registro via JavaScript (API imperativa). Na versão por atributo eu preenchi só nome e descrição, e reforcei uma coisa que vale pro MCP também: o atributo só dá nome ao que já existe. A funcionalidade precisa estar funcionando por conta própria, ninguém verifica se a tua busca busca de verdade
Na versão por JavaScript eu precisei declarar também o input e as propriedades esperadas (qual produto, qual quantidade pra adicionar ao carrinho), enquanto no HTML a estrutura já era entendida automaticamente. É a mesma sensação de ler um inputSchema: sem saber quais propriedades a ferramenta espera, tu não chama nada com segurança
Achei o caminho por atributo bem mais fácil, com o site já rodando bastou ir adicionando. Declarando tudo via JavaScript no mesmo arquivo o código ficou misturado com as funcionalidades, aí a sugestão é subdividir em arquivos mesmo
A parte que mais casa com este post foi a área de teste do inspetor: escolhi uma ferramenta, preenchi os inputs na mão simulando exatamente o que um agente enviaria, inscrevi um e-mail na newsletter e recebi a confirmação, e adicionei um teclado ao carrinho. Pra chamar a ferramenta do carrinho manualmente eu precisei descobrir antes o ID do produto, coisa que uma IA já entenderia sozinha
Ou seja: chamar na mão uma vez te ensina mais sobre a superfície exposta do que ler descrição por uma hora
No vídeo acima tu vê em movimento o painel do inspetor preenchendo, o código com as duas formas de declaração e a ferramenta sendo chamada na mão, com resposta na tela
O que muda com a especificação MCP 2026-07-28 na hora de inspecionar
Algumas mudanças recentes batem direto em quem lista ferramentas, então vale a leitura
O protocolo virou stateless na camada de protocolo: saiu o handshake initialize/notifications/initialized e saiu o header Mcp-Session-Id do transporte Streamable HTTP. Na prática, os endpoints de listagem deixaram de variar por conexão, o que torna a inspeção mais previsível: o que tu lista é o que está lá, não o resultado de uma sessão específica
Os resultados de tools/list, prompts/list e resources/list passaram a exigir os campos ttlMs e cacheScope pela interface CacheableResult. O ttlMs é dica de frescor pro cliente cachear e o cacheScope controla se intermediários podem cachear
Combina bem com a capability listChanged do passo 6: a listagem agora carrega, no próprio resultado, a informação de por quanto tempo aquilo é considerado fresco
Roots, Sampling e Logging foram descontinuados (deprecated), mas continuam funcionais durante a janela de deprecação. Se o teu servidor depende de algum deles, é tempo de planejar, não de correr
E o Inspector v2 saiu junto com essa especificação, com codebase novo e cliente web, CLI e TUI num pacote npm só. Por isso os sub-pacotes antigos ficaram pra trás
Conclusão
Ler o tools/list é a coisa mais barata do processo todo, e é exatamente ela que evita tu descobrir em produção o que a integração podia apagar
Recapitulando o caminho: roda o Inspector em modo CLI no servidor que tu pretende usar, lê o inputSchema de cada ferramenta, percorre a paginação até acabar o nextCursor, separa leitura de escrita pelas anotações (lembrando que são hints, não promessa) e checa se o servidor declara listChanged
Daí sim tu escreve a regra de permissão por prefixo no Claude Code, liberando só o que faz sentido pro teu caso
E se ainda restar dúvida sobre alguma ferramenta de escrita, deixa mcp__* no deny até ter certeza. Servidor parado não quebra nada 🙂
até o próximo post!
Perguntas frequentes
Dá pra listar as ferramentas de um servidor MCP sem instalar nada no projeto?
Dá sim. O comando usa npx, então baixa o pacote @modelcontextprotocol/inspector na hora, roda o tools/list e sai, sem deixar dependência instalada. É o jeito mais rápido de auditar um servidor antes de decidir se ele entra no repo.
Ferramenta com readOnlyHint true pode ser liberada sem revisão?
Não é recomendado. readOnlyHint e destructiveHint são úteis pra separar leitura de escrita rapidamente, mas o próprio MCP deixa claro que anotações são apenas hints e não garantem descrição fiel do comportamento. Cliente não deve decidir uso de ferramenta com base em anotação vinda de servidor não confiável.
Como saber se as ferramentas MCP estão liberadas pro Claude Code usar?
Rode /mcp dentro da sessão pra ver servidores conectados, status e ferramentas disponíveis, ou claude mcp list no terminal pra conferir conexão e autenticação pendente. Mesmo aparecendo na lista, a ferramenta só é chamada se tiver permissão explícita: sem isso o Claude enxerga que ela existe, mas não consegue usar.
Como bloquear de uma vez todas as ferramentas de um servidor MCP no Claude Code?
Usa uma regra de deny com o prefixo daquele servidor e o glob depois dele, tipo { "permissions": { "deny": ["mcp__puppeteer__"] } } pra fechar todas as tools do servidor puppeteer. O segmento do servidor precisa ser explícito, o glob só entra depois de mcp__<servidor>__. Se a intenção for fechar todos os servidores MCP de uma vez, aí o padrão é o deny com mcp__.
Por que a lista de ferramentas de hoje pode não valer amanhã?
Porque o servidor pode declarar a capability listChanged, que indica que ele vai notificar quando a lista de ferramentas mudar. Se essa capability está presente, a auditoria feita hoje tem prazo de validade e precisa ser repetida depois de qualquer atualização do servidor.
tools/list traz todas as ferramentas numa resposta só?
Não necessariamente. A resposta é paginada por cursor opaco: o cliente manda cursor nos params e o servidor pode devolver nextCursor apontando pra próxima página. Enquanto vier nextCursor, ainda tem ferramenta fora da página que você já leu.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
Supabase MCP no Claude Code: como conectar o agente ao schema do seu banco
Supabase MCP no Claude Code conecta o agente ao schema real do seu banco: veja como instalar, autenticar via OAuth e por que usar só em desenvolvimento.
O que são servidores MCP no Claude Code e quando eles valem a pena?
Servidores MCP no Claude Code conectam o agente a bancos, docs e ferramentas externas. Entenda como funcionam e quando realmente valem a pena usar.
Context7 MCP no Claude Code: como parar de receber código de uma versão antiga da biblioteca
Context7 MCP no Claude Code busca a documentação atual da biblioteca e evita código desatualizado. Veja como instalar, os comandos e os planos Free e Pro.
