Como escalar servidores MCP behind um Load Balancer no Azure App Service
TL;DR: A maioria dos servidores Model Context Protocol (MCP) operam como instâncias únicas, sendo ineficientes para ambientes de produção. Com a adoção do transporte HTTP stateless, tornou-se viável executar servidores MCP atrás de um load balancer, como o do Azure App Service. Isso possibilita alta disponibilidade, escalabilidade horizontal e implantações sem downtime, tratando o agente de IA como uma API web robusta. A conclusão principal é que a arquitetura stateless é o caminho para agentes resilientes e produtivos.
A grande maioria das implementações de servidores MCP hoje limita-se a processos de instância única. Embora isso funcione bem para sessões locais via VS Code, essa abordagem é inviável em cenários de produção. Agentes que precisam processar picos de tráfego, realizar deploys frequentes e garantir resiliência contra falhas exigem uma arquitetura distribuída e escalável.
A boa notícia é que a especificação MCP evoluiu. A revisão de 2025-06-18 (mantida na versão 2025-11-25) formalizou o transporte HTTP stateless. Isso significa que cada requisição carrega todas as informações necessárias para que o servidor responda, dispensando conexões de longa duração, tabelas de sessão in-process e os problemáticos "sticky-session hacks" que amarram clientes a instâncias específicas.
Essa mudança protocolar simplifica radicalmente a infraestrutura: você pode colocar seu servidor MCP atrás de um Load Balancer (como o do Azure App Service) e escalá-lo de forma idêntica a qualquer outra API web.
Por que o modelo stateless é fundamental?
Transmissões MCP anteriores dependiam de conexões persistentes, como SSE (Server-Sent Events) ou WebSockets, onde o servidor mantinha estado do cliente em memória (ferramentas ativas, assinaturas ou streams parciais). Esse modelo é eficiente para um ambiente local de desenvolvimento, mas é hostil a qualquer tentativa de load balancing.
O transporte HTTP stateless resolve isso transformando cada chamada em um envelope JSON-RPC completo (ex: initialize, tools/list, tools/call). Cada resposta é autocontida, permitindo que o servidor "esqueça" o cliente entre as requisições. Para que isso funcione, o time de engenharia deve adotar uma disciplina de desenvolvimento: garantir que toda ferramenta seja uma função pura dos seus argumentos, sem tocar em memória atrelada ao estado da sessão.
O exemplo em seligj95/app-service-mcp-stateless-scale-python demonstra como configurar esse ambiente via azd, garantindo, inclusive, telemetria via Application Insights para visualizar como o tráfego é distribuído.
Por que escolher o Azure App Service?
Embora existam opções como Azure Functions ou AKS, o App Service atende melhor aos requisitos de um servidor MCP por alguns motivos estratégicos:
- Always On: Ferramentas de raciocínio que chamam LLMs frequentemente possuem latências na casa de segundos. O App Service mantém o processo residente, ao contrário de funções serverless que, ao escalar para zero, destroem o cache de warm-up.
- Escalabilidade Horizontal Simples: Definir o número de instâncias (
N) no Premium SKU coloca seus servidores atrás de um load balancer gerenciado. Esqueça configurações complexas de VMSS ou ingress controllers. - Deployment Slots: A capacidade de fazer o swap de um slot de staging para produção garante zero downtime, algo crítico quando seu backend de ferramentas de IA está sendo consumido por agentes ativos.
- Easy Auth: A autenticação OAuth 2.1 via Entra ID é trivial, bastando configurar a blade de autenticação do App Service, economizando tempo no desenvolvimento de fluxos de segurança customizados.
O código que garante a escalabilidade
Para que o load balancer funcione corretamente no App Service, a configuração mais importante no seu arquivo Bicep é desabilitar a afinidade de sessão:
resource web 'Microsoft.Web/sites@2024-04-01' = {
// ...
properties: {
clientAffinityEnabled: false // O parâmetro mais importante
}
}
Deixar o clientAffinityEnabled como true (padrão do App Service para aplicações legadas ASP.NET) causaria o uso de cookies ARRAffinity, forçando o tráfego de um único cliente para a mesma instância. Em uma aplicação stateless, isso mata completamente a capacidade do seu sistema de distribuir, efetivamente, a carga entre as instâncias disponíveis.
Como garantir visibilidade com OpenTelemetry
Não é necessário escrever código complexo para telemetria. Ao configurar o SDK do Azure Monitor no seu FastAPI, o Application Insights automaticamente associa os traces ao cloud_RoleInstance utilizando o WEBSITE_INSTANCE_ID do App Service. Com uma consulta simples no Log Analytics, você valida se o balanceamento de carga está ocorrendo:
requests
| where timestamp > ago(15m)
| where name contains "/mcp"
| summarize count() by cloud_RoleInstance
| order by count_ desc
Perguntas Frequentes
-
Por que o modelo stateless é importante para o MCP?
O modelo stateless elimina a dependência de conexões persistentes ou estados em memória, permitindo que qualquer instância do servidor responda a qualquer solicitação de forma independente. Isso é fundamental para permitir o uso de load balancers, garantindo que o tráfego possa ser distribuído entre múltiplos nós sem romper sessões. -
Por que o Azure App Service é recomendado em vez de Azure Functions ou AKS?
O App Service mantém o processo 'Always On', evitando o tempo de aquecimento (cold start) e os limites rígidos de execução comuns em funções serverless. Além disso, oferece escalonamento horizontal via um único parâmetro, integração nativa com deployment slots para blue-green deployments e facilidade na gestão de autenticação (Easy Auth). -
Qual configuração é crítica ao usar o Azure App Service para MCP?
É imperativo desativar o 'ARR Affinity' (clientAffinityEnabled: false) no seu template Bicep ou configuração do recurso. Caso contrário, o load balancer criará cookies de afinidade que prendem o tráfego a uma única instância, invalidando o benefício do escalonamento horizontal.
Artigo originalmente publicado em Azure Updates - Latest from Azure Charts.