Como funciona um MCP server — explicado por quem publicou um
Um MCP server é um programa que expõe capacidades para modelos de IA num formato padronizado: ferramentas, dados, prompts. O MCP (Model Context Protocol) define como um assistente de IA descobre o que o server oferece e como invoca cada capacidade. O server traduz essas invocações para o sistema real por trás dele, seja uma API, um banco ou o filesystem. É o que permite dizer “verifique se este PDF foi alterado” para um agente e ver a resposta vir do seu produto. Ninguém precisou escrever integração específica para aquele assistente.
Essa é a resposta curta. A longa é mais interessante, e este post a percorre com um exemplo real. O tamperlens-mcp é o server que empacota a API do Tamperlens, publicado no npm e no MCP Registry oficial. As decisões de empacotamento desse server têm um post próprio. Este aqui é sobre o protocolo: o que acontece entre o pedido do usuário e a resposta da sua API.
O que é o MCP, afinal?
O MCP é um protocolo aberto, criado pela Anthropic e publicado no fim de 2024. Ele padroniza a conversa entre aplicações de IA e sistemas externos. Antes dele, cada assistente tinha seu formato próprio de plugin ou de function calling, o modelo chamando funções. Integrar um produto com N assistentes custava N integrações. Com o MCP, o produto expõe um server, e qualquer cliente que fale o protocolo o consome. Ao longo de 2025, os principais clientes de IA (desktops, IDEs, frameworks de agente) passaram a falar esse protocolo.
A arquitetura tem três papéis:
- Host: a aplicação de IA que o usuário vê, como um desktop de chat, um IDE ou um agente rodando num servidor.
- Client: o componente dentro do host que mantém a conexão com um server específico (um client por server).
- Server: o programa que expõe as capacidades. É a parte que você escreve.
Por baixo, as mensagens são JSON-RPC 2.0, um formato de pergunta e resposta em JSON: requisições com method e params, respostas com result ou error. Nada exótico. A força do MCP não está na engenharia da mensagem, e sim na padronização do ciclo de vida: como descobrir capacidades, como invocá-las, como negociar o que cada lado suporta.
Como funciona uma chamada, do pedido à resposta?
O ciclo completo, na ordem em que acontece:
- Handshake. O client conecta e manda
initialize. Server e client trocam versões do protocolo e declaram capacidades (“eu sirvo tools”, “eu aceito notificações”). Só depois disso qualquer coisa útil acontece. - Descoberta. O client pede
tools/liste recebe cada ferramenta com nome, descrição e um schema JSON dos parâmetros, isto é, o formato esperado de cada argumento. Esse texto vai para o contexto do modelo, e é a partir dele que o modelo sabe o que existe. - Escolha. O usuário pede algo (“esse contrato foi editado depois de assinado?”). O modelo, olhando as descrições disponíveis, decide invocar uma ferramenta e monta os argumentos conforme o schema.
- Invocação. O client manda
tools/callcom nome e argumentos. Em clients interativos, este é o ponto onde o usuário aprova ou recusa a chamada. - Execução. O server valida os argumentos e faz o trabalho de verdade. No nosso caso, ler o arquivo do disco e enviá-lo para a API de análise.
- Resposta. O resultado volta como conteúdo (texto, dados estruturados) e entra no contexto do modelo, que o usa para responder ao usuário.
Duas consequências práticas desse desenho que só ficam óbvias quando você opera um server:
A descrição da ferramenta é interface de usuário, e o usuário é o modelo. No passo 3, tudo o que o modelo tem para decidir é o texto que você escreveu. As descrições do tamperlens-mcp dizem o que cada ferramenta não faz: “retorna sinais de risco com a evidência bruta — nunca um veredicto de autenticidade”. A razão é que o modelo repete para o usuário o que a descrição afirma. Descrição imprecisa vira alucinação com a sua marca em cima.
O payload atravessa o contexto, então binário não pode ir inline. Tudo que trafega nos passos 4 e 6 passa pelo modelo. Documento entra em megabytes. Por isso as ferramentas aceitam caminho de arquivo ou URL, nunca o conteúdo em base64. O binário vai do disco para a API pelo server, e o modelo só vê o caminho e, depois, o relatório. O post de empacotamento detalha essa decisão e a contrapartida de segurança que ela exige.
O que um server expõe: tools, resources e prompts
O protocolo define três primitivas, e a distinção importa na hora de desenhar:
- Tools (ferramentas): ações que o modelo decide invocar, como “inspecione este documento” ou “compare estes dois arquivos”. São a primitiva principal para empacotar uma API.
- Resources (recursos): dados que a aplicação anexa como contexto, como um arquivo, um registro ou um relatório já pronto. Não são o modelo agindo; são contexto disponível.
- Prompts: templates de interação que o usuário escolhe explicitamente (“analisar contrato”), pré-preenchendo instruções que orquestram tools e resources.
O tamperlens-mcp expõe só tools: inspecionar um documento, fazer a triagem barata de entrada, checar se uma redação de fato removeu o texto, comparar um candidato contra o original. A regra que usamos: ferramenta de agente não é espelho de API. A API tem mais rotas do que o server expõe. Cada ferramenta a mais é uma decisão a mais que o modelo pode errar, e uma descrição a mais competindo por atenção no contexto. A pergunta de design é “o que um agente faria com isto num fluxo real?”, não “quais endpoints existem?“.
stdio ou HTTP: onde o server roda?
O protocolo define dois transportes, e a escolha define a experiência de instalação:
- stdio, a entrada e a saída padrão do processo. O client sobe o server como processo local e conversa por stdin/stdout. É o modo
npx tamperlens-mcp: nada para hospedar, e o server roda na máquina do usuário, com acesso aos arquivos locais dele. - HTTP (streamable): o server é um serviço remoto, e o client conecta pela rede. Faz sentido para servers multiusuário, com estado central ou que não precisam tocar o disco de ninguém.
Para o nosso caso a escolha foi stdio, e o motivo é o fluxo: o documento que o usuário quer verificar está no disco dele. Um server local lê o arquivo e o envia para a API. Um server remoto exigiria upload prévio para algum lugar, recriando o atrito que o MCP deveria eliminar. A regra geral: se a ferramenta precisa alcançar algo que só existe na máquina do usuário, stdio; se o estado mora no seu backend, HTTP.
O que muda na segurança quando o server toca disco e rede?
“Um processo local lê o arquivo que o modelo nomear” é uma frase que deveria arrepiar. É aqui que um MCP server sério se separa de um wrapper de fim de semana. No tamperlens-mcp, três guardas são parte do produto, não nota de rodapé:
- Allowlist de diretórios, a lista do que pode ser lido. O server só lê dentro dos diretórios que o operador listou em
TAMPERLENS_ALLOWED_DIRS. Sem isso, um agente confuso, ou um prompt injetado num documento, poderia pedir a inspeção de~/.ssh/id_rsa. - Symlink resolvido antes de decidir. Um link simbólico dentro do diretório permitido apontando para fora dele é resolvido e recusado. Allowlist sem resolução de symlink é porta com a chave pendurada.
- Guarda anti-SSRF nas URLs, contra pedidos forjados para a rede interna. Origem remota é validada, e o protocolo é re-checado a cada redirect. Um server que baixa o que mandarem é um proxy para a rede interna esperando acontecer.
E há um risco simétrico, do lado do conteúdo. O documento inspecionado pode conter texto escrito para ser lido pelo modelo, não por humanos: é prompt injection dentro do arquivo. É um dos sinais que a própria análise reporta. E é um lembrete de que agente confiável é propriedade do sistema inteiro, não do protocolo. O MCP padroniza a conversa, mas não a torna segura sozinho.
Quando a sua API precisa de um MCP server?
A leitura honesta, que mantivemos depois de publicar: registry de MCP não é canal de aquisição. Hoje ninguém descobre produto novo navegando registry. O valor real está em outro lugar:
- Resposta de procurement, ou seja, para quem avalia a compra. Quando alguém avaliando o produto pergunta “nossos agentes conseguem usar isso?”, a resposta é um comando de uma linha com listing oficial. Não é um “dá para integrar”.
- Superfície para quem conversa. A API REST continua sendo a interface de quem programa. O MCP server é a interface de quem opera por agente. São públicos diferentes do mesmo produto.
- Custo baixo, bem delimitado. Empacotar uma API existente como server com poucas ferramentas é projeto pequeno, desde que a API já resolva autenticação, quota e limites. O
tamperlens-mcpfunciona sem chave porque herda a cota anônima que a API já impunha ao checker gratuito.
Se a sua API não tem um fluxo que um agente executaria de ponta a ponta, o server pode esperar. Se tem, o protocolo é a parte fácil. As decisões difíceis são as de empacotamento e segurança acima.
O resumo que você leva
- MCP server = capacidades padronizadas para modelos: JSON-RPC 2.0, ciclo handshake → descoberta → escolha → invocação → resposta.
- A descrição da ferramenta é a interface. Escreva para o modelo decidir certo, inclusive o que a ferramenta não faz.
- Tools agem, resources contextualizam, prompts orquestram. E menos ferramentas decidem melhor que muitas.
- stdio para alcançar a máquina do usuário, HTTP para estado no backend.
- Server que toca disco/rede tem o confinamento como feature principal: allowlist, symlink resolvido, guarda SSRF.
- Expectativa calibrada: empacote como resposta de procurement e superfície de agente, não como funil de aquisição.
Precisa de um projeto técnico sob medida?
Arquitetura, TypeScript, APIs e automação, do protótipo à produção. Quem responde o seu e-mail é quem escreve o código, e o prazo que eu prometo é o prazo que eu consigo cumprir.
Me manda uma mensagem →