Como criar um servidor MCP para a API interna da sua empresa (e o que deixar de fora)

Criar servidor MCP para uma API interna faz sentido quando o sistema não tem integração pública e ninguém vai manter isso por você. O post é sobre decisão de escopo, não sobre copiar código: quais ações viram tools, o que fica em resources e prompts, e o que precisa ficar de fora por risco (token passthrough, confused deputy, operação destrutiva em massa). Tem também o custo escondido: a Anthropic relata cinco servidores com 58 ferramentas consumindo cerca de 55 mil tokens antes da conversa começar. Ferramenta a mais é contexto a menos, então comece com uma leitura só.
Fala aí, beleza? Existe um sistema na sua empresa que nenhum MCP pronto do mundo conhece
Pode ser o ERP que só roda na rede interna, o painel de pedidos que o time construiu lá atrás, a API de faturamento que ninguém documentou direito
O agente de IA só vira útil de verdade quando ele enxerga o que é SEU, e a ponte pra isso é um servidor MCP escrito por você
Esse post não é copy-paste de código, beleza? É sobre a parte que dá errado antes do código: decidir o que da sua API vira ferramenta, como descrever cada uma pro modelo entender, e o que fica de fora porque o risco não compensa
Servidor MCP pronto x servidor MCP caseiro: quando escolher cada um
Antes de sair codando, a pergunta honesta: alguém já não fez isso?
Se o sistema é um SaaS popular, provavelmente sim. Se é interno, provavelmente não, e aí não tem escapatória
| Critério de decisão | Servidor MCP pronto | Servidor MCP caseiro |
|---|---|---|
| Existe servidor oficial pro sistema | Sim, é o caminho óbvio | Não existe e nem vai existir (API interna) |
| Quem mantém quando a API muda | O fornecedor ou a comunidade | Seu time, e isso é trabalho recorrente |
| Controle sobre quais ações são expostas | O que vier, vem | Você escolhe ferramenta por ferramenta |
| Esforço de autorização | Já resolvido no pacote | Por sua conta: validar audience, consentimento, credencial de serviço |
| Custo de contexto | Igual, e nem sempre enxuto | Igual, mas você decide o tamanho |
O critério fecha assim: API interna sem integração pública tende pro caseiro, SaaS popular tende pro pronto
E tem um detalhe que quase ninguém considera na hora de somar mais um servidor na lista: isso não é de graça
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 116 aulas
- 4 projetos
- 9h 23min
A Anthropic cita um cenário de cinco servidores MCP conectados com 58 ferramentas consumindo cerca de 55 mil tokens antes mesmo da conversa começar. E relata já ter visto definições de ferramentas consumirem 134 mil tokens antes da otimização
A maioria dos clientes MCP carrega todas as definições de ferramenta no contexto de forma antecipada, então cada tool que você inventa fica lá ocupando espaço mesmo quando não é chamada
Se a sua dúvida é entre montar o seu ou usar um conjunto de MCPs prontos já embutidos no cliente, o raciocínio é o mesmo: o pronto ganha em manutenção, o caseiro ganha em controle
Quais ações da sua API viram ferramenta (e quais viram resource ou prompt)
O MCP tem três primitivas: tools (ações), resources (contexto somente leitura) e prompts (templates reutilizáveis)
Muita gente joga tudo em tool e depois reclama que o agente se perde. Faz sentido, né? Se tudo é ação, nada é contexto
O mapeamento pro mundo de uma API interna fica mais ou menos assim:
- Ação com efeito vira tool: criar chamado, atualizar status do pedido, disparar reprocessamento de fatura
- Consulta somente leitura e documento de referência cabem em resource: a tabela de códigos de status, o glossário de campos do ERP, o payload de exemplo que todo mundo do time cola no Slack
- Fluxo repetitivo do time vira prompt: aquele roteiro de "levanta os chamados abertos, agrupa por cliente e escreve o resumo pro daily"
E aqui vai o critério prático mais importante: uma ferramenta por INTENÇÃO do usuário, não um endpoint por rota
Sua API tem dezenas de rotas? Ótimo. Isso não significa dezenas de tools. O agente não pensa em REST, ele pensa em "quero saber o status desse pedido"
Se você já monta seu próprio fluxo de prompts no Claude Code, a primitiva de prompts do MCP é a versão compartilhável disso: o mesmo roteiro, mas disponível pra qualquer pessoa que conectar no servidor
Nome de ferramenta ruim é bug de produto:
A Anthropic recomenda namespacing com prefixo unificado, por serviço (asana_search, jira_search) ou por recurso (asana_projects_search, asana_users_search)
Parece bobo até o dia em que você tem uma tool chamada buscar no seu MCP e outra chamada buscar em um servidor conectado ao mesmo agente
Aí ele chuta. E chuta errado 🙂
Cuidado com o tamanho da resposta:
A recomendação é manter as respostas das ferramentas abaixo de 25.000 tokens pra ter desempenho ideal
Se o seu endpoint interno devolve um JSON gigante, com dezenas de campos por item, não repasse cru. Filtre no servidor, devolva só o que importa pra intenção daquela ferramenta
A API interna é sua, então você tem o luxo de escolher o que sai
O que deixar de fora do seu MCP por risco
Essa é a seção que ninguém escreve e todo mundo precisa
Criar servidor MCP é fácil, o difícil é ter disciplina pra NÃO expor coisa
Lista de exclusão consciente:
- Operação destrutiva em massa: deletar em lote, resetar ambiente, cancelar todos os pedidos de um filtro. Os rm -rf da vida não precisam de uma interface conversacional
- Endpoint que expõe dado sensível de terceiro: se a rota devolve dado de outro cliente, de outro usuário ou informação pessoal que não é do solicitante, ela não vira tool
- Qualquer coisa que dependa de repassar o token do cliente
Esse último merece parágrafo próprio
Token passthrough é antipadrão, e é proibido:
A especificação de autorização do MCP é dura nesse ponto: o servidor MUST aceitar apenas tokens destinados a ele, MUST rejeitar tokens que não o incluam na claim de audience e MUST NOT repassar o token recebido do cliente ao chamar APIs upstream
Ou seja: aquele atalho gostoso de pegar o token que chegou e mandar direto pra API interna? Fora
O servidor precisa da credencial DELE pra falar com a sua API
Confused deputy, o problema do servidor que virou proxy:
Quando o seu servidor MCP atua como proxy pra uma API de terceiro, aparece a vulnerabilidade de confused deputy
As boas práticas de segurança do MCP exigem que esses proxies mantenham um registro de client_id aprovados por usuário, consultem esse registro ANTES de iniciar o fluxo de autorização e guardem as decisões de consentimento de forma segura
Tome cuidado aqui: é exatamente o tipo de coisa que funciona lindamente no teste e vira incidente em produção
E as annotations não te salvam:
A spec é explícita: todas as propriedades de ToolAnnotations são apenas hints, não garantem descrição fiel do comportamento da ferramenta, e clientes nunca devem tomar decisão de uso de ferramenta com base em annotations vindas de servidores não confiáveis
Annotation é sinalização, não trava de segurança. A trava mora no seu código
O que você precisa antes de começar
Checklist curto, sem enrolação:
- Uma linguagem com SDK oficial: os SDKs Tier 1 (Python, TypeScript, Go e C#) já foram atualizados pra especificação 2026-07-28. O SDK de Rust suporta a nova spec em beta e o SDK oficial de Ruby chegou à versão 1.0.0 com API pública estável
- Acesso à documentação da API interna: se ninguém sabe o que a rota faz, o modelo também não vai saber
- Uma credencial de serviço própria do servidor: não a do usuário, lembra do token passthrough?
- Decisão de transporte: stdio pra processo local e HTTP (Streamable HTTP/SSE) pra servidor remoto, com o mesmo payload JSON-RPC nos dois
- Claude Code instalado como cliente de teste, pra você validar sem depender de mais ninguém
A especificação atual está publicada em modelcontextprotocol.io e vale a leitura antes de começar: ela trouxe núcleo stateless, requisições multi round-trip, roteamento por header, listas cacheáveis (as respostas de listagem passam a carregar os campos ttlMs e cacheScope), endurecimento de autorização e um framework formal de extensões
Passo a passo: do endpoint interno à ferramenta que o modelo entende
- Escolha de 3 a 5 ações de maior valor. Não comece pelo catálogo completo da API. Erro comum deste passo: mapear todas as rotas "pra já deixar pronto" e afogar o contexto do agente antes do primeiro teste
- Nomeie com prefixo por serviço ou por recurso, no estilo asana_search ou asana_projects_search. Erro comum: nome genérico tipo buscar ou listar, que colide com ferramenta de outro servidor conectado
- Escreva a descrição explícita: quando usar aquela ferramenta, quais parâmetros são obrigatórios, quais são opcionais e qual o formato de saída esperado
Isso não é detalhe cosmético: a Anthropic afirma que refinamentos precisos nas descrições das ferramentas levaram o Claude Sonnet 3.5 a performance estado da arte no SWE-bench Verified, reduzindo drasticamente taxas de erro
Erro comum: descrição de uma linha copiada do nome do endpoint, que não diz ao modelo QUANDO chamar
- Preencha as annotations: title, readOnlyHint, destructiveHint, idempotentHint e openWorldHint. A orientação é marcar readOnlyHint: true nas ferramentas somente leitura e destructiveHint: false nas operações apenas aditivas. Erro comum: deixar em branco achando que o padrão é seguro. Quando readOnlyHint não é especificado, o cliente deve assumir false
- Enxugue a resposta pra menos de 25.000 tokens. Erro comum: devolver o JSON bruto da API interna e descobrir depois que uma única chamada comeu a janela inteira
- Aproveite ttlMs e cacheScope nas listagens. Na spec 2026-07-28, as respostas de tools/list, prompts/list, resources/list e resources/read passam a carregar esses campos, deixando o cliente decidir a estratégia de cache e evitar re-fetch desnecessário. Erro comum: ignorar isso e pagar listagem repetida à toa
- Escolha o transporte e registre no Claude Code. A adição é feita com o comando claude mcp add: pra endpoint https:// usa-se –transport http, pra endpoints com Server-Sent Events usa-se –transport sse, e stdio é pro servidor que roda na mesma máquina. Na configuração JSON, o campo type aceita streamable-http como alias de http. Erro comum: apontar transporte HTTP pra um servidor que na verdade roda local por stdio
- Defina o escopo. Cada comando de adição grava no escopo local por padrão. Com –scope project o servidor vai pro arquivo .mcp.json na raiz do projeto, compartilhado com o time. Com –scope user ele fica disponível em todos os seus projetos, junto do escopo local, no ~/.claude.json. Erro comum: subir pro .mcp.json do time um servidor que ainda nem foi validado, e todo mundo herdar seu experimento
Deu errado: os problemas mais comuns ao plugar seu MCP
O comando que te salva primeiro é esse:
claude mcp list
Ele mostra o status de saúde ao lado de cada servidor, como Connected, Needs authentication ou Failed to connect
Sintoma: Failed to connect
Causa provável: transporte ou comando errado. Servidor local registrado como HTTP, endpoint com typo, processo que nem sobe
Correção: inspecione a configuração daquele servidor específico
claude mcp get nome-do-servidor
Se estiver errado, remove e adiciona de novo com o transporte certo
claude mcp remove nome-do-servidor
Prevenção: valide o servidor sozinho antes de registrar em qualquer cliente
Sintoma: Needs authentication
Causa provável: fluxo de autorização incompleto
Correção: revise o lado do servidor, principalmente a validação de audience. Lembra que ele MUST rejeitar token que não o inclua na claim de audience?
Prevenção: trate autorização como parte do design da ferramenta, não como remendo do final
Sintoma: o agente chama a ferramenta errada
Causa provável: nome sem prefixo e descrição vaga. As duas coisas juntas, quase sempre
Correção: renomeie com namespacing e reescreva a descrição dizendo QUANDO usar, com parâmetros obrigatórios e opcionais explícitos
Prevenção: leia sua própria descrição fingindo que você nunca viu a API. Se você hesitaria, o modelo também hesita
Sintoma: contexto estourado por ferramenta demais
Causa provável: servidor virou espelho da API inteira
Correção: corta. Sério. Volta pras 3 a 5 ações de maior valor e transforma o resto em resource quando for só leitura de referência
Prevenção: restrinja também pelo lado das permissões. Os nomes de ferramentas MCP seguem o padrão mcp__{nome_do_servidor}__{nome_da_ferramenta}, onde a chave em mcpServers vira o segmento do nome do servidor
As regras de permissão aceitam glob apenas depois do prefixo literal mcp__servidor__, e o segmento do servidor precisa ser livre de glob
Então mcp__puppeteer__ cobre todas as ferramentas daquele servidor, e mcp__github__get_ cobre só as que começam com get_
É um jeito bem prático de liberar leitura e segurar escrita 😀
Na prática: o que aprendi conectando um agente a um MCP
No vídeo abaixo eu monto um agente de IA com MCP no n8n do zero, e vários aprendizados de lá valem igualzinho quando o servidor é seu e a API é interna
Eu tinha feito um vídeo anterior só apresentando a funcionalidade de MCP, e o pessoal pediu a implementação completa. Aí resolvi montar o fluxo inteiro
A primeira decisão foi de propósito: evitei exemplo aleatório. Escolhi um caso com utilidade real, porque MCP em cima de exemplo bobo não ensina nada
O servidor que eu monto expõe três ações ligadas a e-mail: buscar mensagens, gerar um resumo delas em um documento e enviar uma resposta quando o resumo indicar necessidade
O cenário é o de quem trabalha em empresa, não tem tempo de acompanhar a caixa de entrada, mas precisa saber o que chegou no dia
Repare que são TRÊS ações, cada uma com intenção clara. É exatamente o mesmo raciocínio de escolher de 3 a 5 ferramentas da sua API interna
Algumas coisas que eu faço lá e recomendo carregar pro seu servidor:
- Construo cada parte separada em vez de criar tudo junto, por organização. Fica MUITO mais fácil achar onde quebrou
- Renomeio o caminho da URL gerada pelo gatilho, trocando o valor aleatório por um nome descritivo, pra identificar o serviço só de bater o olho
- Renomeio os nós com nomes descritivos em vez de deixar o nome padrão. Nome descritivo é a mesma disciplina do namespacing das tools
- Filtro por caixa de entrada na busca de e-mails, senão o fluxo traz mensagem enviada pelo próprio usuário. Escopo mal definido devolve lixo, e a IA acredita no lixo
- Deixo o intervalo de datas pra IA preencher, porque lidar com data na mão é a parte chata haha
Sobre credencial: a do Google é a parte mais trabalhosa do processo todo, tanto que eu opto por não detalhar cada passo pra não estender demais o vídeo. Já a da OpenAI é bem mais simples, exige só uma chave de API
E eu oriento criar uma chave nova quando você não tem a antiga guardada. Evito deixar chave circulando por aí, não quero dar acesso pra outras pessoas sem perceber
Um aviso que salva tempo: ativar o serviço é obrigatório. Sem ativar, o MCP não é acessível por consumidor nenhum, nem local nem externo. Já vi gente debugando cliente por meia hora com o servidor desligado
A parte que eu mais recomendo copiar é essa: antes de integrar com qualquer serviço externo, eu construo um agente de teste no PRÓPRIO n8n
Um mock pra validar o MCP e só depois distribuir o serviço pra outras pessoas
O motivo é simples: quando você testa direto no serviço externo e dá erro, você fica sem saber se o problema está no MCP ou no outro lado. Validando no mesmo ambiente, a resposta chega rápido
Pra validar eu escolho um modelo mini, com o raciocínio de que, se funciona no mais econômico, deve funcionar nos mais avançados
Também adiciono memória ao agente, porque sem ela cada mensagem do chat é tratada como conversa nova e o histórico da interação se perde
E salvo o fluxo com frequência ao longo da construção, já que perder trabalho é péssimo 😛
No fim eu mostro o mesmo servidor sendo consumido FORA do n8n, justamente pra provar que o MCP pode ser externalizado
Esse é o ponto que amarra tudo com a API interna da sua empresa: você constrói em cima de um caso de uso real, valida primeiro com um agente montado no mesmo ambiente, ativa o serviço, testa ponta a ponta, e só então distribui pros outros consumidores
Vale assistir antes de escrever o seu próprio servidor, porque lá dá pra ver a sequência inteira acontecendo: definir as ações, montar parte por parte, ativar, testar com um agente local e só depois externalizar
Comece pequeno: uma ferramenta de leitura antes de tudo
Se você chegou até aqui querendo criar servidor MCP pra API interna, o próximo passo é bem menor do que parece
Escolhe UMA consulta somente leitura da sua API. Uma só
Expõe como tool com readOnlyHint: true, descrição explícita de quando usar e resposta enxuta
Registra no escopo local, que é o padrão, e roda claude mcp list pra ver o Connected aparecer
Usa por alguns dias, ajusta a descrição quando o modelo errar a chamada, valida com uma ou duas pessoas do time
Só então promove pro –scope project e deixa no .mcp.json compartilhado
A partir daí, cada nova ferramenta entra respondendo uma pergunta única: essa intenção existe de verdade no dia a dia do time?
Porque ferramenta a mais é contexto a menos, e contexto a menos é agente pior
Revisa a lista antes de crescer o servidor, beleza? Até o próximo post!
Perguntas frequentes
Servidor MCP para API interna deve usar stdio ou HTTP?
Depende de onde a API interna vive. Se o servidor roda na mesma máquina do cliente, stdio resolve. Se é um serviço remoto acessível por rede, o transporte é HTTP, usando Streamable HTTP ou SSE, ambos com o mesmo payload JSON-RPC por baixo.
Como saber se o meu servidor MCP caseiro está conectado no Claude Code?
Rode claude mcp list. O comando mostra o status de saúde ao lado de cada servidor, como Connected, Needs authentication ou Failed to connect. Pra detalhar um servidor específico, use claude mcp get seguido do nome dele.
Dá pra dar permissão só pra algumas ferramentas do meu servidor MCP interno?
Dá, mas a regra de permissão só aceita glob depois do prefixo literal mcp__servidor__, e o segmento do servidor não pode ter glob. É o mesmo padrão que aparece no post: mcp__puppeteer__ cobre todas as ferramentas daquele servidor, e mcp__github__get_ cobre só as que começam com get_.
Preciso marcar cada ferramenta como somente leitura no meu servidor MCP?
Sim, e é orientação da própria especificação pra quem escreve o servidor: marque readOnlyHint: true nas ferramentas somente leitura e destructiveHint: false nas operações apenas aditivas. Só que annotation é hint, não garantia de comportamento, então ela serve pra sinalizar intenção, nunca como trava. A trava de verdade mora no código do seu servidor.
Meu servidor MCP interno precisa acompanhar a versão mais nova da especificação?
Vale acompanhar, principalmente se você usa um dos SDKs oficiais Tier 1 (Python, TypeScript, Go ou C#), que já foram atualizados pra spec 2026-07-28. Essa versão trouxe coisa útil pra API interna, como os campos ttlMs e cacheScope nas respostas de listagem, que ajudam o cliente a decidir quando re-buscar dado sem sobrecarregar.
Posso deixar meu servidor MCP repassar o token de autenticação do usuário pra API interna?
Não, e isso não é escolha de estilo, é regra da especificação. O servidor deve aceitar só tokens destinados a ele, rejeitar token que não o inclua na claim de audience e nunca repassar o token recebido do cliente pra chamar a API upstream. A credencial que fala com a sua API interna é do servidor, não do usuário que está do outro lado da conversa.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
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.
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.
