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

Diagrama de como criar servidor MCP para conectar a API interna da empresa a um assistente de IA
Resposta rápida

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
Formação Recomendada

Formação Claude Code

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

  • 120 aulas
  • 4 projetos
  • 9h 45min

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

  1. 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
  1. 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
  1. 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

  1. 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
  1. 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
  1. 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
  1. 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
  1. 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.




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