Proteger servidores MCP em Aplicativos de Contêiner do Azure

Este artigo explica como autenticar e proteger servidores MCP em execução no Aplicativos de Contêiner do Azure. A abordagem difere dependendo se você hospeda um aplicativo de contêiner autônomo ou usa o servidor MCP gerenciado pela plataforma em sessões dinâmicas.

Pré-requisitos

Visão geral dos modelos de autenticação

Aplicativos de Contêiner do Azure dá suporte a dois modelos de autenticação para servidores MCP. A tabela a seguir resume as principais diferenças.

Aspecto Aplicativo de contêiner autônomo Sessões dinâmicas MCP
Mecanismo de autenticação Autenticação integrada dos Aplicativos de Contêineres com Microsoft Entra ID Chave de API através do x-ms-apikey cabeçalho
Tipo de token Token de portador OAuth 2.0 Cadeia de caracteres de chave de API opaca
Provedor de identidade Microsoft Entra ID Azure Resource Manager
Rotação de chave/token Gerenciado por Microsoft Entra ID Regenerar por meio da API Azure Resource Manager
Escopo de autorização Configurável por aplicativo Nível do pool de sessões
Criptografia de transporte TLS (entrada de Aplicativos de Contêiner) TLS (ponto de extremidade de sessões de Aplicativos de Contêiner)

Aplicativo de contêiner autônomo com autenticação Microsoft Entra ID

Ao implantar seu próprio servidor MCP como um aplicativo de contêiner, você possui a camada de autenticação. Use o recurso de autenticação integrada de apps de contêiner apoiado por Microsoft Entra ID.

Configurar a autenticação interna

As etapas a seguir registram um aplicativo Microsoft Entra ID e habilitam a autenticação interna em seu aplicativo de contêiner.

  1. Registre um aplicativo no Microsoft Entra ID:

    APP_ID=$(az ad app create \
        --display-name "mcp-server-auth" \
        --sign-in-audience AzureADMyOrg \
        --query appId -o tsv)
    
  2. Crie um principal de serviço:

    az ad sp create --id $APP_ID
    
  3. Defina o URI da ID do Aplicativo e exponha um escopo de API. Essas configurações são necessárias para que os clientes possam solicitar tokens de acesso para o servidor MCP.

    az ad app update --id $APP_ID --identifier-uris "api://$APP_ID"
    
    OBJECT_ID=$(az ad app show --id $APP_ID --query id -o tsv)
    SCOPE_ID=$(uuidgen)
    
    az rest --method PATCH \
        --uri "https://graph.microsoft.com/v1.0/applications/$OBJECT_ID" \
        --headers "Content-Type=application/json" \
        --body "{
            \"api\": {
                \"oauth2PermissionScopes\": [{
                    \"id\": \"$SCOPE_ID\",
                    \"adminConsentDescription\": \"Access the MCP server\",
                    \"adminConsentDisplayName\": \"Access MCP Server\",
                    \"isEnabled\": true,
                    \"type\": \"User\",
                    \"userConsentDescription\": \"Access the MCP server\",
                    \"userConsentDisplayName\": \"Access MCP Server\",
                    \"value\": \"access_as_user\"
                }]
            }
        }"
    
  4. Adicionar um segredo do cliente:

    CLIENT_SECRET=$(az ad app credential reset --id $APP_ID --query password -o tsv)
    TENANT_ID=$(az account show --query tenantId -o tsv)
    
  5. Habilite a autenticação interna no aplicativo de contêiner:

    az containerapp auth microsoft update \
        --name <CONTAINER_APP_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --client-id $APP_ID \
        --client-secret $CLIENT_SECRET \
        --tenant-id $TENANT_ID \
        --issuer "https://login.microsoftonline.com/$TENANT_ID/v2.0" \
        --yes
    
  6. Defina a ação não autenticada para exigir logon:

    az containerapp auth update \
        --name <CONTAINER_APP_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --unauthenticated-client-action Return401
    

Conectar-se de um cliente MCP com um token de portador

Quando o servidor MCP exigir um token de portador, configure a recuperação de token em seu cliente MCP. O exemplo a seguir mostra uma configuração de .vscode/mcp.json para GitHub Copilot:

{
    "servers": {
        "my-mcp-server": {
            "type": "http",
            "url": "https://<CONTAINER_APP_NAME>.<REGION>.azurecontainerapps.io/mcp",
            "headers": {
                "Authorization": "Bearer ${input:mcpBearerToken}"
            }
        }
    },
    "inputs": [
        {
            "id": "mcpBearerToken",
            "type": "promptString",
            "description": "Enter your bearer token for the MCP server",
            "password": true
        }
    ]
}

Tip

Para desenvolvimento, obtenha um token usando-o az account get-access-token --resource api://$APP_ID --query accessToken -o tsv e cole-o quando solicitado. Para fluxos de trabalho automatizados, integre-se ao sistema de gerenciamento de tokens da sua organização.

Configurar o CORS

Os clientes MCP que se conectam de ambientes baseados na Web precisam de cabeçalhos CORS. Use o seguinte comando para configurar o CORS em seu aplicativo de contêiner:

az containerapp ingress cors update \
    --name <CONTAINER_APP_NAME> \
    --resource-group <RESOURCE_GROUP> \
    --allowed-origins "https://vscode.dev" "https://github.dev" \
    --allowed-methods "GET" "POST" "OPTIONS" \
    --allowed-headers "Content-Type" "Authorization" "Mcp-Session-Id" \
    --max-age 3600

Os seguintes cabeçalhos são fundamentais para permitir:

  • Content-Type: necessário para solicitações de JSON-RPC
  • Authorization: necessário para autenticação de token de portador
  • Mcp-Session-Id: usado por clientes MCP para sessões com estado

Observação

O GitHub Copilot conecta-se a servidores MCP remotos a partir do aplicativo da área de trabalho do VS Code, e não por meio de um navegador. O CORS só será necessário se você pretender dar suporte a clientes MCP baseados em navegador ou VS Code para a Web. Os tutoriais autônomos usam origens CORS curinga para simplificar; na produção, restrinja às origens confiáveis específicas, como mostrado aqui.

Recomendações de segurança para servidores MCP autônomos

Aplique as práticas recomendadas a seguir para proteger o servidor MCP autônomo.

  • Restrições de rede: use restrições de IP ou integração de rede virtual para limitar o acesso a IPs de clientes conhecidos.
  • Limitação de taxa: implemente a limitação de taxa no código do aplicativo ou coloque o Gerenciamento de API do Azure na frente do aplicativo.
  • Validação de entrada: valide todos os argumentos da ferramenta no código do servidor MCP. As entradas da ferramenta MCP são JSON arbitrários. Trate-os como não confiáveis.
  • Design sem estado: prefira servidores MCP sem estado para evitar riscos de sequestro de sessão. Na maioria dos SDKs do MCP, isso significa desabilitar a geração de ID de sessão do lado do servidor (por exemplo, sessionIdGenerator: undefined em TypeScript ou stateless_http=True no Python).
  • Sondas de integridade: Configure as sondas de integridade em um ponto de extremidade separado (como /healthz), não no ponto de extremidade MCP. Os pontos de extremidade MCP esperam solicitações POST via JSON-RPC e retornam erros para consultas GET simples.

Sessões dinâmicas com autenticação de chave de API

Importante

O servidor MCP gerenciado pela plataforma para sessões dinâmicas está em versão prévia. A versão da API 2025-02-02-preview e as propriedades mcpServerSettings estão sujeitas a alterações.

O servidor MCP gerenciado pela plataforma em sessões dinâmicas usa a autenticação de chave de API. A chave tem como escopo o pool de sessões e concede acesso a todas as ferramentas e sessões nele.

Fluxo de autenticação de chave de API

As etapas a seguir descrevem como a autenticação de chave de API funciona para sessões dinâmicas.

  1. O cliente envia uma solicitação JSON-RPC com o x-ms-apikey cabeçalho.
  2. O proxy do pool de sessão valida a chave no plano de controle Azure.
  3. Se a chave for válida, a solicitação será encaminhada para a sessão. Caso contrário, um erro de autenticação será retornado.

Recuperar a chave de API

Use o comando a seguir para buscar a chave de API para o pool de sessões.

API_KEY=$(az rest --method POST \
    --uri "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.App/sessionPools/<SESSION_POOL_NAME>/fetchMCPServerCredentials" \
    --uri-parameters api-version=2025-02-02-preview \
    --query "apiKey" -o tsv)

Girar e armazenar em cache a chave de API

Você pode regenerar a chave de API a qualquer momento. A plataforma armazena em cache os resultados de validação por até cinco minutos, portanto, as chaves válidas anteriormente podem continuar funcionando após a regeneração até que o cache expire.

Para alternar a chave de API, chame a ação regenerateCredentials no pool de sessões:

az rest --method POST \
    --uri "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.App/sessionPools/<SESSION_POOL_NAME>/regenerateCredentials" \
    --uri-parameters api-version=2025-02-02-preview

Após a regeneração, recupere a nova chave usando fetchMCPServerCredentials como mostrado anteriormente.

Recomendações de segurança para sessões dinâmicas

Aplique as seguintes práticas recomendadas para proteger a implantação do MCP em sessões dinâmicas.

  • Escopo da chave de API: a chave de API concede acesso a todo o pool de sessões. Qualquer cliente com a chave pode criar ambientes e executar código. Não compartilhe a chave com partes não confiáveis.
  • Environment isolation: cada sessão é executada em um contêiner isolado Hyper-V. A execução de código em uma sessão não pode acessar os dados de outra sessão.
  • Saída de rede: Controlar se as sessões podem acessar a Internet usando sessionNetworkConfiguration.status. Defina como EgressDisabled se as sessões não precisarem de acesso à rede externa.
  • Tempo de vida da sessão: configure coolDownPeriodInSeconds para destruir automaticamente sessões ociosas. Essa configuração limita a janela de exposição se uma sessão estiver comprometida.
  • Secret storage: armazene a chave de API em Azure Key Vault ou segredos do Container Apps em vez de em arquivos de código ou configuração.

Incompatibilidades comuns de autenticação

Um erro comum é usar o cabeçalho de chave de API (x-ms-apikey) com um aplicativo de contêiner autônomo ou usar um token de portador com o ponto de extremidade MCP das sessões. A tabela a seguir mostra o que acontece quando você os mistura.

Mismatch Resultado
x-ms-apikey cabeçalho enviado para o aplicativo autônomo O cabeçalho é ignorado; a solicitação passa pela autenticação interna e retorna 401 se a autenticação estiver habilitada
Authorization: Bearer enviado ao MCP das sessões A validação de chave falha e retorna 401
Token de portador solicitado sem um escopo de API exposto. Falha na aquisição do token ou o token não tem uma audiência válida, resultando em 401

Verifique se a configuração do cliente MCP corresponde ao modelo de hospedagem implantado.