MCP, Harness engineering e Loop engineering: arquitetura de agentes de IA em produção
Onde o protocolo termina e a engenharia de confiabilidade começa: arquitetura, segurança, observabilidade e os trade-offs de levar agentes de IA para produção.

Todo engenheiro que colocou um agente de IA em produção já bateu na mesma parede. O modelo raciocina bem, escreve bem, decide bem, mas não sabe nada sobre o seu banco de dados, o seu sistema de arquivos ou a sua API interna. Cada nova fonte de dado vira uma integração nova, escrita à mão, com contrato próprio, tratamento de erro próprio e manutenção própria. O Model Context Protocol existe para resolver exatamente esse problema, e vale entender a fundo por que ele importa antes de tratá-lo como só mais uma biblioteca para plugar ferramenta em LLM.
O problema não é tool calling, é interoperabilidade
Antes do MCP, conectar um modelo a uma fonte de dados externa significava escrever um adaptador específico para aquele modelo, para aquele provedor e para aquela fonte. Se eu tinha três modelos e cinco sistemas internos, eu não tinha oito integrações, eu tinha potencialmente quinze, uma para cada combinação. Esse é o clássico problema N x M de integração, o mesmo que sistemas distribuídos já resolveram décadas atrás com padrões de mensageria e APIs bem definidas.
Preciso ser preciso aqui, porque é fácil exagerar o argumento: o MCP não elimina a necessidade de integração. Alguém ainda precisa definir tools, schemas, autenticação, políticas e comportamento de erro daquela fonte de dado específica. O que o MCP elimina é a necessidade de cada consumidor reinventar o contrato de integração do zero. Eu escrevo um servidor MCP uma única vez, e qualquer cliente compatível com o protocolo consegue conversar com ele, da mesma forma que JDBC, ODBC ou o próprio HTTP funcionam como interface padronizada entre consumidor e fonte de dado.
Arquitetura: host, client, server
Host (Claude Desktop, IDE, agente) → MCP Client → JSON-RPC / MCP → MCP Server (Tools | Resources | Prompts)
A partir do MCP Server, três destinos possíveis:
- → APIs
- → Bancos de dados
- → Sistemas de arquivos
O host é a aplicação que fornece o ambiente de execução. O client vive dentro do host e mantém a comunicação com um servidor específico, um client por servidor, o que isola falha por design: se um servidor cai ou se comporta mal, o blast radius fica contido naquela conexão. O server é um processo independente, geralmente leve, que expõe contexto e capacidades para o modelo consumir.
A virada para stateless
Essa é a mudança arquitetural mais importante do protocolo desde o lançamento, e por isso merece seção própria em vez de uma linha perdida no meio do texto. Até a revisão 2025-11-25, o protocolo, especialmente no transporte Streamable HTTP, era orientado a sessão: o client iniciava a interação com o handshake initialize/initialized, e servidores que precisavam manter estado podiam emitir um Mcp-Session-Id. Quando esse identificador era emitido, o client precisava ecoá-lo nas requisições seguintes, o que prendia cada client a uma instância específica de servidor e tornava escala horizontal um problema de infraestrutura antes de ser um problema de produto.
A especificação 2026-07-28 remove o handshake e a sessão de nível de protocolo. Cada requisição agora carrega sua própria versão de protocolo e capacidades, e é autocontida.
Antes, o client enviava initialize, o server respondia com um session id, e toda requisição seguinte precisava ecoar esse id, o que prendia o client a uma instância específica do server. Hoje, cada requisição do client já chega autocontida, com a versão do protocolo no header MCP-Protocol-Version e identidade mais capacidades em _meta, o server responde, e qualquer instância consegue atender qualquer requisição.
Na prática isso significa que um servidor MCP remoto pode viver atrás de um load balancer comum, sem sticky session, sem store de sessão compartilhado, sem gateway fazendo inspeção de pacote para rotear para a instância certa. É a diferença entre tratar MCP como curiosidade de laptop e tratar MCP como infraestrutura HTTP convencional.
Primitivas fundamentais do servidor
O protocolo define três primitivas centrais no lado do servidor, e a distinção entre elas não é sobre efeito colateral, é sobre quem decide o uso.
- Tools → controlado pelo modelo → o LLM decide chamar
- Resources → controlado pela aplicação → o host decide carregar
- Prompts → controlado pelo usuário → o usuário decide invocar
Tools são capacidades executáveis que o modelo descobre e invoca de forma autônoma. Isso não significa que toda Tool altera estado: uma Tool pode apenas consultar um dado, sem efeito colateral nenhum. A distinção que importa para produção é outra, e é a que eu uso para desenhar política de acesso:
- Read-only →
consultar_cliente(),buscar_documento() - Idempotent write →
atualizar_status(),reprocessar_item() - Destructive/privileged →
deletar_registro(),cancelar_pagamento()
Cada categoria pede um nível diferente de validação, confirmação e auditoria. Tratar todas as Tools com o mesmo rigor é ou permissivo demais para as destrutivas ou burocrático demais para as de leitura.
Resources são dados estruturados que o servidor disponibiliza, e é o host, não o modelo, que decide quando carregá-los no contexto. Prompts são templates de instrução que o usuário aciona deliberadamente, o modelo não escolhe usar um Prompt por conta própria.
O que foi depreciado, e o que veio no lugar
Até a revisão anterior, o protocolo também incluía Roots, Sampling e Logging entre suas funcionalidades centrais. Na especificação 2026-07-28 essas três foram formalmente depreciadas, com janela mínima de doze meses antes de qualquer remoção. Continuam funcionando, mas novas implementações não deveriam mais se apoiar nelas.
Com a revisão stateless, o padrão de server-initiated requests usado por Sampling, Elicitation e Roots foi substituído pelo Multi Round-Trip Requests (MRTR). Antes, se um servidor precisasse de ajuda do client no meio de uma chamada, ele abria uma requisição de volta (sampling/createMessage, elicitation/create, roots/list), o que exigia um canal bidirecional sempre aberto, incompatível com um protocolo stateless. Agora o servidor devolve um resultado incompleto sinalizando input_required, o client resolve o que falta e refaz a chamada original com a resposta anexada.
Antes, o server abria uma requisição de volta ao client no meio da chamada, sampling/createMessage, sobre um canal bidirecional sempre aberto. Com o MRTR, o server passa a devolver um resultado incompleto (input_required), o client resolve o que falta e refaz a chamada original com inputResponses anexado, e toda perna do fluxo vira uma requisição client→server comum, sem canal aberto.
Como o MCP trafega
MCP não é o transporte, é a camada de contrato por cima de JSON-RPC. Os dois transportes que importam na prática são:
- stdio → processo local, CLI, IDE, processo filho
- Streamable HTTP → servidor remoto, cloud, gateway, load balancing
O transporte legado HTTP+SSE está oficialmente depreciado na revisão 2026-07-28, com o mesmo prazo de doze meses de transição. Se você está desenhando um servidor novo hoje, não há motivo para partir dele.
Um exemplo que mostra o protocolo em produção
O caso mais didático é conectar um assistente a um banco PostgreSQL via servidor MCP. O usuário faz uma pergunta em linguagem natural, o modelo identifica que precisa de dado estruturado, descobre via Tools quais operações o servidor expõe, formula a chamada, e o servidor executa a operação autorizada contra o banco.
Aqui vale uma correção de precisão importante: a chamada de Tool não devolve automaticamente um Resource. Ela devolve um resultado de Tool, que pode conter conteúdo textual, conteúdo estruturado ou referências a Resources. Esse resultado volta ao host, que o incorpora ao contexto usado pelo modelo para compor a resposta final.
O ponto que costuma passar despercebido é que um servidor MCP bem desenhado não expõe SQL arbitrário para o modelo. Ele expõe operações controladas, com schema definido, validação de entrada e limite de escopo, exatamente como eu trataria qualquer camada de API voltada para um consumidor não confiável.
MCP como fronteira de confiança
MCP padroniza como capacidades são expostas. Ele não transforma capacidades inseguras em capacidades seguras. O servidor MCP deve ser tratado como uma API voltada para um consumidor parcialmente não confiável, porque é exatamente isso que ele é: uma superfície que um modelo, cujo comportamento é probabilístico, vai chamar de forma autônoma.
A revisão 2026-07-28 reforçou justamente essa fronteira, com validação de issuer conforme RFC 9207 para mitigar ataques de mix-up entre authorization servers, e uma transição formal de Dynamic Client Registration para documentos de metadados de client. O protocolo também mantém, desde revisões anteriores, a proibição explícita de token passthrough: o servidor MCP não deve, em nenhuma hipótese, repassar o access token recebido do client para um serviço downstream. Se o servidor precisa chamar uma API upstream, ele age como client OAuth daquela API e obtém uma credencial própria, emitida especificamente para aquele recurso, nunca reaproveitando o token que recebeu.
Para ambiente corporativo, a peça que faltava chegou em junho de 2026: a extensão Enterprise-Managed Authorization (EMA) saiu de preview e se tornou estável. Em vez de cada usuário autorizar cada servidor MCP individualmente por consentimento em navegador, o provedor de identidade da empresa passa a ser o ponto de decisão. Um administrador aprova o servidor uma vez no IdP, e todo usuário autorizado se conecta automaticamente via um grant de identidade de curta duração, sem tela de consentimento por servidor. Isso resolve um problema real de escala: cem servidores MCP internos não deveriam significar cem consentimentos manuais por funcionário.
Antes de conectar qualquer servidor MCP de terceiro a um sistema em produção, eu pergunto:
- Quem escreveu esse servidor e qual é a superfície real de acesso que ele expõe.
- O servidor valida os parâmetros de cada Tool ou confia cegamente no que o modelo envia.
- Existe log e trace de toda chamada de Tool, com quem chamou, quando e com qual resultado.
- Existe isolamento de tenant, ou um único servidor atende múltiplos clientes sem separação de escopo.
- Operações destrutivas exigem confirmação humana, ou o modelo pode executá-las de ponta a ponta sozinho.
- O servidor tem acesso de leitura e escrita, e essa distinção está refletida em permissão real, não só em boa vontade do prompt.
A tese central: camada probabilística decide, camada determinística executa
Essa é a ideia que sustenta o artigo inteiro, e ela merece ser dita de forma explícita: a camada probabilística decide a intenção, a camada determinística valida e executa.
Usuário → LLM / Agente (probabilístico, decide a intenção) → Camada de política (determinístico, valida):
- usuário pode fazer isso?
- a tool está autorizada?
- os argumentos são válidos?
- precisa de confirmação humana?
- o tenant está correto?
→ MCP Client → MCP Server → Sistema real
O modelo nunca deveria ter permissão implícita para executar. Ele propõe, a camada determinística decide se a operação é permitida, e só então o servidor MCP a executa contra o sistema real. O MCP padroniza o contrato de interação entre essas camadas; ele não substitui a necessidade de ter essa segunda camada.
MCP não basta sozinho: harness engineering e loop engineering
Essa ressalva final merece ser desenvolvida, porque é onde a maioria dos projetos de agente tropeça depois de já ter resolvido a parte de integração. Uma forma útil de organizar a evolução recente dessa disciplina é enxergar quatro níveis: prompt engineering define o que pedir ao modelo, context engineering define quais instruções, dados e ferramentas ficam disponíveis, harness engineering conecta o modelo a um ambiente executável com arquivos, memória e mecanismos de feedback, e loop engineering define como o sistema observa, age, verifica e se recupera repetidamente. Não existe um padrão formal da indústria dizendo que essas são necessariamente quatro camadas universais, mas é uma taxonomia que ajuda a situar onde o MCP entra e onde ele para: o protocolo resolve parte de context engineering e parte do harness ao padronizar a exposição e a invocação de ferramentas e dados. Ele não resolve as outras duas sozinho.
Harness engineering parte de uma formulação que ganhou forte tração na engenharia de agentes em 2026: agente é igual a modelo mais harness. O modelo contém a inteligência bruta, o harness é tudo que transforma essa inteligência em ação confiável, orquestração de ferramentas, controle de permissão, compactação de contexto, guardrails e observabilidade. Um servidor MCP bem desenhado entrega a parte de exposição padronizada de Tools e Resources, mas quem decide se uma Tool destrutiva precisa de confirmação humana, como o agente se recupera de uma chamada que falhou, e como o contexto é compactado quando a conversa fica longa, é o harness, não o protocolo. É perfeitamente possível ter um servidor MCP impecável e um harness ruim, e o resultado ainda vai ser um agente que erra em produção.
Loop engineering é a camada seguinte, e resolve um problema diferente: como o agente decide repetir, parar ou se corrigir. Em vez de prompt único seguido de resposta única, um agente loop-engineered opera em ciclos de ação, observação e nova decisão até bater um critério de sucesso explícito ou um limite de tentativas. Toda chamada de Tool via MCP é, nesse desenho, um passo de "ação" dentro do loop, mas o protocolo não decide quando chamar de novo, quando desistir ou quando escalar para um humano. Isso é decisão de loop engineering, definida fora do MCP, geralmente como uma condição de parada explícita e um número máximo de iterações, exatamente para evitar o cenário clássico de agente que entra em ciclo infinito reexecutando a mesma Tool sem nunca convergir.
- Prompt engineering → o que pedir ao modelo
- Context engineering → o que fica disponível (MCP entra aqui)
- Harness engineering → o que garante execução confiável em volta do modelo
- Loop engineering → como o ciclo se repete até o objetivo, e quando para
Na prática, quando eu desenho um agente em produção, MCP resolve como o agente enxerga e chama sistemas externos de forma padronizada. Harness engineering resolve o que acontece em volta de cada chamada, permissão, retry, guardrail. Loop engineering resolve a estratégia de iteração inteira, quando parar, quando insistir, quando pedir ajuda humana. Tratar as três como a mesma coisa é o motivo pelo qual tanto projeto de agente funciona bem em demonstração e falha assim que sai do ambiente controlado.
Observabilidade e auditoria
A revisão 2026-07-28 formalizou a propagação de W3C Trace Context dentro do campo _meta, fixando os nomes de chave traceparent, tracestate e baggage. Isso significa que um trace iniciado no host consegue atravessar client, servidor MCP e sistema downstream como uma única árvore de spans em um backend compatível com OpenTelemetry, sem instrumentação customizada para cada gateway.
Para produção, o mínimo que eu meço por chamada de Tool é:
tool.name, duration, status, caller / tenant, authorization_result, input_validation, downstream_service, error_type, retry_count.
Operações de longa duração
Nem toda Tool deveria bloquear esperando terminar. Gerar um relatório financeiro, processar cem mil documentos ou reindexar um repositório não cabe no modelo de requisição e resposta síncrona. A extensão Tasks, que migrou do núcleo experimental para uma extensão formal nesta revisão, resolve isso: o servidor responde com um task handle, e o client consulta status, atualiza ou cancela a tarefa de forma assíncrona, em vez de manter a chamada original aberta.
Governança: já não é mais só um padrão da Anthropic
O MCP foi lançado pela Anthropic em novembro de 2024, mas em dezembro de 2025 o projeto foi doado à Agentic AI Foundation, um fundo dirigido sob a Linux Foundation, lançado com contribuições fundadoras de Anthropic, Block e OpenAI, e apoio de Google, Microsoft, AWS, Cloudflare e Bloomberg. Isso importa para o argumento do artigo: um protocolo com governança neutra multiplica o número de clientes e servidores que se beneficiam do desacoplamento, porque nenhum vendor único controla a direção técnica.
Quando MCP resolve e quando é overengineering
MCP compensa quando existem múltiplos modelos, múltiplos hosts ou múltiplas equipes consumindo as mesmas fontes de dado, porque aí o custo de manter N integrações customizadas supera o custo de manter um servidor padronizado. Para um único agente, com um único modelo, acessando uma única fonte de dado interna, uma integração direta via função nativa ainda pode ser mais simples e mais fácil de operar do que subir e manter um processo de servidor MCP à parte.
A pergunta que uso para decidir não é "o MCP é o padrão, devo usar". É a mesma pergunta de sempre: esse problema é de integração ponto a ponto ou é de integração N x M, com múltiplos consumidores que vão precisar do mesmo contrato no futuro. Se for ponto a ponto, resolvo direto. Se for N x M, o MCP paga o investimento inicial rápido.
Para onde o protocolo vai a partir daqui
Em 22 de agosto de 2026, os mantenedores publicaram um roadmap atualizado organizado em cinco frentes oficiais: primitivas de mensageria agêntica, unificação e hardening de transporte HTTP-nativo, identidade de agente e segurança enterprise, melhoria das primitivas existentes, e experiência de desenvolvimento dos SDKs. Entre esses temas, os seguintes merecem atenção especial de quem desenha arquitetura MCP hoje, porque sinalizam onde ainda existe lacuna real:
- Identidade de agente, dentro da frente de segurança enterprise. A autorização atual pressupõe uma pessoa aprovando acesso em um navegador. Cada vez mais o caller é um agente rodando como workload de nuvem, agindo em nome de um usuário ausente ou delegando autoridade a subagentes. O trabalho em andamento cobre Demonstrating Proof of Possession (DPoP) e Workload Identity Federation como caminho padronizado para isso, em vez de API key colada em variável de ambiente.
- Unificação de transporte. A meta é estender o modelo HTTP-nativo que a revisão de julho trouxe para servidores remotos também a servidores locais falando Streamable HTTP sobre stdio, simplificando o desenvolvimento de client e servidor em um único transporte.
- Contrato de resultado de Tool mais rígido e descoberta progressiva de Tools, as duas dentro da frente de melhoria de primitivas. Hoje uma resposta de
tools/callpode carregar o mesmo dado em mais de um formato, e um desenvolvedor de servidor não sabe de antemão qual forma um client específico vai usar, os mantenedores querem padronizar em um contrato único. Separadamente, conectar um servidor com cem Tools significa que o modelo paga o custo de contexto daquela superfície inteira antes do usuário fazer a primeira pergunta, e a seleção de Tool piora conforme a lista cresce. A direção é permitir que um servidor exponha um catálogo pequeno de entrada e revele mais conforme a conversa se especializa. - Mensageria agêntica. Consolidar Tasks,
subscriptions/listene notificações de progresso em um conjunto coerente, incluindo eventos iniciados pelo servidor via webhook em vez de o client ficar em polling.
Nenhum desses itens está na especificação ainda, são prioridades de trabalho, não features prontas. Mas se você está desenhando um servidor MCP hoje com mais de uma dezena de Tools ou com caller que é outro agente em vez de um usuário humano, vale desenhar sabendo que essas duas lacunas específicas, descoberta progressiva e identidade de agente, estão no radar oficial do protocolo.
Posicionamento final
O MCP não elimina a complexidade de integrar IA a sistemas reais. Ele cria uma fronteira padronizada onde essa complexidade pode ser controlada, governada, observada e reutilizada. Quem trata MCP como atalho de produtividade vai sentir a dor na primeira vez que um servidor mal desenhado expuser dado sensível ou executar uma ação sem controle. Quem trata MCP como parte da arquitetura, com contrato explícito, fronteira de confiança bem definida e observabilidade de ponta a ponta, ganha um padrão real de desacoplamento entre IA e infraestrutura.


