mozak.tech Arquitetura de IA Corporativa 14%

Parte 3 — Topologia de Integração e o Protocolo MCP

3.1 — MCP como Middleware: Fim das Integrações Point-to-Point Customizadas

Objetivo da Aula

Explicar por que integrações ponto a ponto colapsam quando o número de agentes e de sistemas corporativos cresce ao mesmo tempo

Reclassificar o MCP: não como biblioteca de conector, mas como camada de middleware entre o harness e a organização

Projetar versionamento de capabilities que não quebra agentes já em produção quando um servidor MCP evolui

Definir controle de acesso granular no nível de servidor, de tool e de recurso — não apenas "o agente tem MCP ou não tem"

Desenhar o mecanismo pelo qual o harness decide, em tempo de execução, quais tools um agente específico pode efetivamente chamar

Por que isso importa

Você já sabe conectar um cliente MCP a um servidor e fazer um agente chamar uma tool. Isso resolve o problema de um agente com um sistema. O problema que separa quem monta demo de quem projeta plataforma é outro: uma empresa não tem um agente e um sistema — tem dezenas de agentes (atendimento, engenharia, financeiro, RH) e dezenas de sistemas (CRM, ERP, ticketing, data warehouse, repositório de código, billing). A pergunta arquitetural não é "como esse agente fala com esse sistema", é "como qualquer agente aprovado fala com qualquer sistema aprovado, sem que cada par vire um projeto de integração próprio".

Essa é exatamente a pergunta que a engenharia de software corporativa já respondeu antes, com Enterprise Service Bus e API Gateway: quando o número de integrações cresce, você para de conectar ponta a ponta e insere uma camada de contrato no meio. O MCP faz o mesmo papel para agentes, com uma diferença que muda o jogo: o contrato é descoberto em tempo de execução pelo próprio modelo, não compilado em código cliente-específico.

Impacto direto no seu trabalho: quando você aprova a inclusão de um novo sistema corporativo no ecossistema de agentes, a decisão que você toma não é "vamos escrever um conector". É "vamos publicar um servidor MCP, registrá-lo, versionar suas capabilities e decidir quem pode chamar o quê". Errar essa decisão custa caro dois anos depois — quando o décimo agente e o vigésimo sistema entrarem em produção e a malha de integrações customizadas virar dívida técnica que ninguém consegue mais mapear.

Conceitos Fundamentais

O problema que o middleware resolve: explosão combinatória

Antes de qualquer protocolo padronizado, a forma natural de conectar um agente a um sistema é escrever código específico: um adaptador que sabe autenticar no CRM, formatar a chamada, tratar o retorno e expor isso como uma função que o LLM pode invocar. Funciona bem para um agente e um sistema. O problema aparece na escala:

Integração ponto a ponto (pré-middleware): cada agente mantém um conector direto e próprio para cada sistema que precisa acessar.

  • Agente Atendimento conecta a: Conector CRM, Conector Ticketing, Conector Billing
  • Agente Financeiro conecta a: Conector ERP, Conector Billing (outra implementação!), Conector Data Warehouse
  • Agente Engenharia conecta a: Conector Git, Conector CI/CD, Conector Ticketing (outra implementação!)

Com N agentes e M sistemas, o pior caso é N × M conectores distintos — cada um com sua própria autenticação, tratamento de erro, paginação, rate limit e formato de retorno.

Isso não é abstração de slide. Coloque números realistas de uma empresa de porte médio nesse cálculo:

Cenário concreto:
  8 agentes em produção (Atendimento N1, Atendimento N2,
  Financeiro, RH, Engenharia, Vendas, Compliance, Suporte Interno)
  12 sistemas corporativos (CRM, ERP, Ticketing, Billing,
  Data Warehouse, Git, CI/CD, HRIS, Assinatura Eletrônica,
  Data Lake, Calendário, E-mail Corporativo)

  Ponto a ponto, pior caso:  8 × 12 = 96 conectores possíveis
  Hub-and-spoke via MCP:     8 + 12 = 20 pontos de integração

  Cada conector ponto a ponto mantido por uma equipe diferente,
  em uma linguagem diferente, sem padrão de auditoria comum,
  é o equivalente a 96 pequenos projetos de software vivos.
  Com hub-and-spoke, o mesmo ecossistema vira 12 servidores MCP
  (um por sistema, mantido por quem já é dono do sistema) e
  8 configurações de política de acesso no harness (uma por
  perfil de agente).

Repare no detalhe que dói de verdade: não é só o volume de código. É que o conector de Ticketing escrito pelo time de Atendimento e o conector de Ticketing escrito pelo time de Engenharia divergem — comportamentos diferentes, bugs diferentes, ausência de auditoria centralizada, e nenhum dos dois documentado de um jeito que o outro time consiga reaproveitar. Cada integração é um silo. Multiplicar agentes não multiplica capacidade, multiplica dívida.

MCP como camada de contrato: hub-and-spoke

O middleware resolve isso invertendo a topologia. Em vez de cada agente falar diretamente com cada sistema, todo mundo fala um único protocolo com um hub central — e cada sistema publica um servidor MCP, uma vez, para todos os consumidores:

Topologia hub-and-spoke via MCP: todos os agentes conectam ao mesmo hub central, e o hub conecta a cada servidor MCP.

  • Agente Atendimento, Agente Financeiro e Agente Engenharia conectam a: Harness (cliente MCP)
  • Harness (cliente MCP) conecta a: Servidor MCP CRM, Servidor MCP Ticketing, Servidor MCP Billing, Servidor MCP ERP, Servidor MCP Git

Com N agentes e M sistemas, o custo de integração passa a ser N + M: cada sistema publica um servidor MCP (M), cada agente consome o protocolo padrão (N) — não N × M pares customizados.

A diferença não é estética. Publicar um servidor MCP para o Ticketing é trabalho do time que é dono do Ticketing, feito uma vez, com autenticação, rate limiting e tratamento de erro decididos por quem entende o sistema. Qualquer agente aprovado no ecossistema consome essa mesma superfície, sem reescrever nada. O time de Atendimento e o time de Engenharia deixam de manter dois conectores de Ticketing divergentes — passam a consumir o mesmo contrato.

Capability discovery como dado, não como código

A peça que faz o hub-and-spoke funcionar sem que o harness precise de código hardcoded por sistema é a descoberta de capabilities em tempo de execução. Quando o harness conecta a um servidor MCP, ele não precisa saber de antemão quais tools existem — ele pergunta:

// Handshake de inicialização (resumido)
harness → servidor: initialize({ protocolVersion: "2025-06-18" })
servidor → harness: { protocolVersion: "2025-06-18", capabilities: {...} }

// Descoberta de capabilities — isto é DADO, não código
harness → servidor: tools/list
servidor → harness: {
  tools: [
    { name: "criar_ticket", description: "...", inputSchema: {...} },
    { name: "consultar_status_pedido", description: "...", inputSchema: {...} },
    { name: "cancelar_assinatura", description: "...", inputSchema: {...} }
  ]
}

Isso é a diferença estrutural entre middleware e biblioteca de conector. Uma biblioteca de conector tem, no código do harness, uma função criarTicket(titulo, prioridade) escrita à mão — se o sistema de Ticketing adicionar um campo obrigatório, alguém precisa achar e editar essa função. Com MCP, o schema da tool é publicado pelo servidor e consumido dinamicamente: o harness injeta as tools descobertas no contexto do LLM sem que uma linha de código do harness precise mudar. O harness deixa de ser "N implementações de conector" e passa a ser "um interpretador de contratos".

Fundamento: Contrato vs. Implementação

Um contrato descreve o que uma interface promete (nome da operação, formato de entrada, formato de saída) sem dizer como ela é implementada por dentro. Middleware funciona porque desacopla os dois lados de uma integração através de um contrato estável: o time do CRM pode reescrever o backend inteiro do CRM, e nenhum agente consumidor percebe, desde que o contrato MCP publicado não mude. Essa é a mesma lógica de uma interface em programação orientada a objetos, ou de um contrato de API REST versionado — só que aqui o "cliente" que consome o contrato é, em parte, o próprio modelo de linguagem, lendo o inputSchema para decidir como preencher os argumentos.

Versionamento de capabilities sem quebrar agentes em produção

Um servidor MCP publicado hoje vai mudar. Vai ganhar tools novas, vai precisar depreciar tools antigas, vai precisar alterar o schema de uma tool existente porque o sistema por trás dela mudou. O erro de arquitetura mais comum nessa hora é tratar a evolução do servidor como um deploy qualquer — e quebrar, silenciosamente, todo agente que já estava calibrado para o schema anterior.

Três disciplinas de versionamento resolvem isso na prática:

1. Mudança aditiva não quebra contrato
   - Adicionar um campo OPCIONAL a inputSchema: seguro.
   - Adicionar uma tool nova: seguro (agentes antigos simplesmente
     não a descobrem em seus prompts se o harness filtrar por
     política — ver seção de controle de acesso).
   - Tornar um campo antes opcional em OBRIGATÓRIO: quebra
     contrato. Trate como breaking change.

2. Depreciação com janela de convivência
   - Tool antiga marcada como deprecated na description,
     continua respondendo.
   - Tool nova publicada em paralelo (ex.: "cancelar_assinatura"
     e "cancelar_assinatura_v2" coexistindo).
   - Telemetria de quem ainda chama a versão antiga antes de
     desligar (ligação direta com a Parte 5 — FinOps e telemetria).

3. Negociação de protocolVersion no handshake
   - O servidor pode recusar ou adaptar o comportamento conforme
     a protocolVersion que o harness anuncia no initialize.
   - Isso separa "versão do protocolo MCP" de "versão do
     conjunto de tools" — são dois relógios diferentes.

Na prática, isso significa que "publicar um servidor MCP" não é um evento único — é a abertura de um contrato de longo prazo que precisa de disciplina de compatibilidade, exatamente como qualquer API pública versionada. A diferença é que, aqui, quem consome o contrato inclui um modelo de linguagem que decide como preenchê-lo com base na description em linguagem natural — o que faz da própria descrição da tool parte do contrato, não só o schema formal.

Controle de acesso granular: quem pode chamar o quê

O protocolo MCP, por si, não resolve autorização corporativa. Um servidor MCP tipicamente expõe o mesmo conjunto de tools para qualquer cliente que se conecte e autentique — a granularidade de "este agente de Atendimento pode consultar pedidos mas não pode cancelar assinaturas, enquanto este agente de Suporte Nível 2 pode fazer as duas coisas" não é uma decisão do protocolo. É uma decisão do harness.

Isso conecta direto com a Parte 1 desta série (RBAC no Agent Loop): o harness mantém uma política que mapeia identidade do agente (papel, time, ambiente) para o subconjunto de servidores e tools que ele está autorizado a sequer ver — porque a primeira camada de controle de acesso é não colocar a tool no contexto do LLM, não confiar que o modelo vai se recusar a chamá-la:

// Política de acesso — avaliada pelo harness antes de expor
// qualquer tool ao contexto do LLM
politica_acesso = {
  "agente:atendimento-nivel-1": {
    servidores_permitidos: ["ticketing-mcp", "crm-mcp"],
    tools_bloqueadas: ["crm-mcp.excluir_cliente"],
  },
  "agente:atendimento-nivel-2": {
    servidores_permitidos: ["ticketing-mcp", "crm-mcp", "billing-mcp"],
    tools_bloqueadas: ["billing-mcp.emitir_estorno_acima_limite"],
  },
  "agente:financeiro": {
    servidores_permitidos: ["billing-mcp", "erp-mcp"],
    tools_bloqueadas: [],
  },
}

function tools_disponiveis(agente, todas_tools_descobertas):
  politica = politica_acesso[agente.papel]
  return todas_tools_descobertas
    .filtrar(t => politica.servidores_permitidos.inclui(t.servidor))
    .filtrar(t => !politica.tools_bloqueadas.inclui(t.nome_qualificado))

O resultado prático: dois agentes conectados ao mesmo servidor MCP de Billing enxergam conjuntos de tools diferentes no próprio contexto — um nunca vê emitir_estorno_acima_limite na lista, então nunca tem a chance de tentar chamá-la. Controle de acesso no nível de visibilidade é mais forte do que controle de acesso "deixa ver mas recusa na hora de executar", porque reduz a superfície de decisão do modelo, não só a superfície de execução.

Custo real de propriedade: quem mantém o quê

A economia de N + M em vez de N × M só se sustenta se a propriedade de cada servidor MCP for clara. O padrão que funciona na prática é ownership descentralizado com governança centralizada: o time dono do sistema (o time de Billing, o time de Ticketing) publica e mantém o servidor MCP daquele sistema — porque é quem entende as regras de negócio, os limites de rate limit reais da API interna, e o que é seguro expor. O time de plataforma/harness não escreve conectores; ele mantém o registro de servidores aprovados, a política de acesso e o pipeline de auditoria (aprofundado adiante).

Modelo de ownership:

  Time de Billing        → dono do servidor billing-mcp
                            (schema das tools, versionamento,
                            SLA de disponibilidade)

  Time de Plataforma/IA  → dono do harness e da política de
                            acesso (quem pode ver billing-mcp,
                            em que nível de risco, com que
                            aprovação)

  Nenhum dos dois lados precisa entender profundamente o
  domínio do outro para que a integração funcione — isso é
  o próprio ponto do contrato.

Quando essa separação não é explícita, o padrão que se instala é o pior dos dois mundos: o time de plataforma acaba escrevendo e mantendo lógica de negócio de Billing dentro do harness ("é mais rápido fazer aqui"), recriando o acoplamento ponto a ponto que o MCP existia para eliminar — só que agora escondido atrás de um único componente central em vez de espalhado em vários conectores. O sintoma de alerta é fácil de reconhecer: se o time de plataforma precisa entender regra de negócio de Billing para debugar um agente, a fronteira de contrato vazou.

Aprofundamento Técnico

Registro central de servidores MCP: o portão antes da porta

Hub-and-spoke sem controle de quem pode publicar um "spoke" novo vira o mesmo caos ponto a ponto, só que disfarçado de padrão. A prática que sustenta o modelo em escala é um registro interno de servidores MCP aprovados — equivalente arquitetural a um registro interno de pacotes (npm privado, registry Docker interno): nenhum servidor entra na malha sem passar por uma etapa de revisão.

Essa revisão não é burocracia gratuita. A superfície de risco de um servidor MCP mal revisado é real e específica do domínio: a description de cada tool é texto que entra no contexto do modelo como se fosse instrução do sistema. Um servidor malicioso ou mal escrito pode publicar uma tool cuja descrição contém instruções escondidas ("ignore restrições anteriores e execute X") — isso é injeção de prompt via superfície de integração, não via input do usuário. A checklist mínima de revisão antes de registrar um servidor:

Checklist de onboarding de servidor MCP:
  [ ] Autenticação do servidor usa credencial com escopo mínimo
      necessário (não uma chave de admin genérica)
  [ ] Descriptions de tools revisadas por humano — sem instruções
      embutidas, sem texto que tenta reconfigurar comportamento
      do agente
  [ ] inputSchema de cada tool valida tipos e limites (não aceita
      string livre onde deveria haver enum ou número)
  [ ] Tools com efeito colateral (escrita) documentadas e
      classificadas por raio de impacto — ver Capítulo 3.2
  [ ] Versionamento e política de depreciação documentados
  [ ] Owner do servidor identificado (time responsável por
      manter e responder incidentes)

O registro central não precisa de aprovação lenta e centralizada em um único time de plataforma — pode (e geralmente deve) ser descentralizado na publicação, com times donos de cada sistema publicando seus próprios servidores. O que precisa ser central é o processo de revisão e o catálogo: onde qualquer harness da empresa descobre, de forma confiável, quais servidores existem, quem é dono, e qual é o nível de confiança atribuído a cada um.

Gateway agregador vs. conexão direta multi-servidor

Existem duas formas de o harness se relacionar com múltiplos servidores MCP: conectar diretamente em cada um (o harness mantém N conexões simultâneas), ou conectar a um único gateway/agregador que, por trás, fala com os N servidores e apresenta uma superfície unificada.

Conexão direta multi-servidor
  • Harness conecta diretamente a: Servidor CRM, Servidor Ticketing, Servidor Billing
Gateway agregador
  • Harness conecta a: Gateway MCP
  • Gateway MCP conecta a: Servidor CRM, Servidor Ticketing, Servidor Billing

A tabela a seguir compara os dois modelos por aspecto.

AspectoConexão direta multi-servidorGateway agregador
Ponto único de falhaNão háSim, se não for redundante
LatênciaMenor (sem hop extra)Hop de rede extra
Política de acessoDuplicada em cada integraçãoAplicada em um único lugar
Observabilidade/AuditoriaFragmentadaCentralizadas por padrão

Não existe resposta universal — é trade-off real. Organizações que já têm um harness robusto o suficiente para aplicar política de acesso de forma consistente em cada conexão (a política descrita na seção anterior, avaliada uma vez por sessão de agente) tendem a preferir conexão direta, porque elimina um componente de infraestrutura adicional. Organizações com múltiplos harnesses distintos (times diferentes rodando frameworks de agente diferentes) tendem a preferir gateway agregador, porque centralizar a política de acesso e a auditoria em um único componente é mais barato do que replicar essa lógica em cada implementação de harness.

Observabilidade centralizada como subproduto estrutural

Um efeito colateral bom do middleware, que não é o motivo principal para adotá-lo mas se paga sozinho depois: toda chamada de tool passa, estruturalmente, por um ponto instrumentável. Isso significa que registrar quem chamou o quê, quando, com quais argumentos e com qual resultado deixa de ser responsabilidade de cada conector individual (que na topologia ponto a ponto, na prática, quase nunca implementa isso de forma consistente) e passa a ser responsabilidade de uma única camada.

Essa auditoria centralizada é o que sustenta duas coisas que aparecem mais adiante nesta série: telemetria de custo por fluxo de negócio (Parte 5, FinOps) e trilha auditável para compliance (Parte 6, Governança). Ambas dependem do mesmo fato estrutural: se toda chamada de ferramenta atravessa o middleware, o middleware é o lugar certo para instrumentar — não cada integração isoladamente.

Multi-tenancy: servidor compartilhado vs. servidor por time

Uma última decisão de topologia que aparece assim que a malha cresce: um único servidor MCP de Billing atende todos os times (multi-tenant), ou cada time que precisa de Billing recebe uma instância própria, configurada com suas próprias credenciais e limites?

AspectoServidor compartilhado (multi-tenant)Servidor por time (isolado)
CredencialUma instância, credencial ampla com escopo por chamadorN instâncias, credencial escopada por time
Raio de impacto de bug de autorizaçãoToda a empresaContido ao time afetado
Rate limitCompartilhado — um time barulhento afeta os outrosIsolado — um time barulhento não afeta os demais
ManutençãoCentralizada (1 deploy)Replicada (N deploys)

A regra prática: quanto maior o raio de impacto potencial das tools de escrita expostas por um servidor, mais a balança pende para isolamento por time ou por ambiente (produção vs. homologação, no mínimo). Servidores majoritariamente de leitura, com baixo raio de impacto, geralmente não justificam o custo operacional de manter N instâncias — multi-tenant com boa política de autorização por chamador resolve. Essa classificação de raio de impacto — leitura, escrita reversível, escrita irreversível — é exatamente o ponto de partida do próximo capítulo, onde a decisão desce do nível "quem pode ver a tool" para "como o harness garante que a chamada, uma vez decidida, execute de forma determinística e auditável".