Claude Platform Docs
MessagesTúneis MCP

Implantar túneis MCP com Docker Compose

Instale a pilha de túneis MCP em uma VM usando Docker Compose.

Este guia implanta a pilha de túneis como contêineres reforçados em um único host. A mesma configuração pode ser replicada em vários hosts para disponibilidade.

Antes de começar

Você precisa de:

  • Um túnel. Com acesso programático, o componente de setup cria um para você quando você não fornece um ID de túnel; para anexar a um túnel existente, crie-o no Console e anote o ID do túnel (tnl_...). O provisionamento manual sempre começa a partir de um túnel criado no Console.
  • Uma forma de o host se autenticar na API de Tunnels.
    • Acesso programático (recomendado). Ative Set up programmatic access ao criar o túnel (ou crie a regra de federação diretamente em Settings > Workload identity se você estiver deixando o componente de setup criar o túnel) para que o componente de setup possa se autenticar por meio de Workload Identity Federation. Anote o ID da regra de federação (fdrl_...) e o ID da sua organização.
    • Manual. Pule o acesso programático. Você vai obter o token do túnel no Console, gerar uma CA e um certificado de servidor por conta própria e registrar a CA no Console.
  • Um host com Docker e Docker Compose instalados. O fluxo manual também requer openssl (1.1.1 ou posterior).
  • Conectividade de rede de saída do host para api.anthropic.com (443 TCP) e para a borda do túnel (7844 TCP e UDP). Consulte os requisitos de rede completos.
  • Um ou mais servidores MCP em execução e acessíveis a partir do host nos endereços que você configurará em routes. Se você ainda não tiver um, use o servidor de exemplo.

Opcional: Use um servidor MCP de exemplo

Se você não tiver um servidor MCP disponível para testes, use este mínimo:

mkdir -p mcp-tunnel
cat > mcp-tunnel/hello_server.py <<'EOF'
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-server", host="0.0.0.0", port=9000)


@mcp.tool()
def hello(name: str = "world") -> str:
    """Say hello to someone."""
    return f"Hello, {name}!"


if __name__ == "__main__":
    mcp.run(transport="streamable-http")
EOF

As etapas de instalação a seguir fazem cd para mcp-tunnel/ e indicam onde adicionar o serviço e a rota correspondentes.

Instalar

Este guia fornece uma abordagem de referência usando Docker Compose. Você é responsável por adaptá-la para atender aos requisitos de segurança da sua organização.

Este caminho requer que o host tenha um provedor de identidade OIDC (como um servidor de metadados de VM em nuvem ou SPIFFE). Se não tiver, use a aba Sem acesso programático.

O componente de setup usa Workload Identity Federation para buscar o token do túnel, gerar uma CA e um certificado de servidor e registrar a CA na Anthropic.

  1. Prepare o diretório de implantação

    mkdir -p mcp-tunnel/{config,data}
    cd mcp-tunnel
    sudo chown 65532:65532 data

    Os contêineres são executados como o UID não-root 65532 e precisam de acesso de escrita a data/.

  2. Escreva o docker-compose.yaml

    O arquivo compose fixa as imagens por digest SHA-256, executa cada contêiner como não-root com um sistema de arquivos somente leitura, remove todas as capabilities do Linux e desativa a escalada de privilégios.

    cat > docker-compose.yaml <<'EOF'
    services:
      setup:
        image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:efb27b299d627e4134815663cb8896641eeaee025d734c0f695582b4df38f013
        entrypoint: ["/setup"]
        command:
          - init
          - --api-url=https://api.anthropic.com
          - --output=dir:/data
          - --token-version=1
        environment:
          - TUNNEL_ID
          - ANTHROPIC_FEDERATION_RULE_ID
          - ANTHROPIC_ORGANIZATION_ID
          - ANTHROPIC_WORKSPACE_ID
          - ANTHROPIC_IDENTITY_TOKEN
        volumes:
          - ./data:/data
        user: "65532:65532"
        read_only: true
        security_opt:
          - no-new-privileges:true
        cap_drop:
          - ALL
        profiles: ["setup"]
    
      cloudflared:
        image: cloudflare/cloudflared@sha256:6b599ca3e974349ead3286d178da61d291961182ec3fe9c505e1dd02c8ac31b0
        command: tunnel --no-autoupdate run --url http://localhost:8080
        environment:
          - TUNNEL_TOKEN
        # Compartilha o netns do proxy para que localhost:8080 o alcance.
        network_mode: "service:mcp-proxy"
        restart: unless-stopped
        user: "65532:65532"
        read_only: true
        security_opt:
          - no-new-privileges:true
        cap_drop:
          - ALL
        stop_grace_period: 30s
        logging:
          options:
            max-size: "10m"
            max-file: "3"
    
      mcp-proxy:
        image: us-docker.pkg.dev/anthropic-public-registry/images/mcp-proxy@sha256:efb27b299d627e4134815663cb8896641eeaee025d734c0f695582b4df38f013
        volumes:
          - ./config/mcp-proxy.yaml:/etc/mcp-gateway/config.yaml:ro
          - ./data:/data:ro
        restart: unless-stopped
        user: "65532:65532"
        read_only: true
        security_opt:
          - no-new-privileges:true
        cap_drop:
          - ALL
        stop_grace_period: 30s
        logging:
          options:
            max-size: "10m"
            max-file: "3"
    EOF

    Se você estiver usando o servidor MCP de exemplo, adicione-o como um serviço:

    cat >> docker-compose.yaml <<'EOF'
    
      hello-mcp:
        image: python:3.13-slim
        working_dir: /app
        volumes:
          - ./hello_server.py:/app/hello_server.py:ro
        command: sh -c "pip install --quiet mcp && python hello_server.py"
        restart: unless-stopped
    EOF
  3. Provisione o túnel

    Defina os identificadores. Deixe TUNNEL_ID sem definir para que o componente de setup crie um túnel; defina-o para anexar a um túnel existente do Console:

    # export TUNNEL_ID=tnl_...   # defina para anexar a um túnel existente
    export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
    export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000

    Se sua regra de federação tiver escopo em um workspace diferente do padrão da sua organização, defina também ANTHROPIC_WORKSPACE_ID=wrkspc_...; caso contrário, o componente de setup usa o workspace padrão. Um túnel criado automaticamente é criado nesse workspace.

    Defina ANTHROPIC_IDENTITY_TOKEN como um JWT OIDC do provedor de identidade deste host. Siga o guia de WIF para o seu provedor para registrar o emissor, definir o subject da regra e emitir o token; a audience da regra deve corresponder à audience que você solicita ao emitir.

    Execute o componente de setup:

    docker compose run --rm setup

    setup init é idempotente sobre data/: executá-lo novamente reutiliza o ID do túnel e a CA já armazenados ali e nunca cria um segundo túnel. Uma nova CA é gerada e registrada somente quando data/ está vazio ou TUNNEL_ID mudou; nesse caso, aplica-se o limite de dois certificados ativos, então revogue um no Console primeiro se ambos os slots estiverem ocupados.

    Consulte Falhas de autenticação do componente de setup se ocorrer erro.

    Recupere o domínio do seu túnel e exporte-o para as etapas posteriores:

    export TUNNEL_DOMAIN=$(sudo cat data/tunnel-domain)
    echo "$TUNNEL_DOMAIN"
  4. Escreva a configuração do proxy

    tunnel_domain é obrigatório: o proxy o usa para remover o sufixo de domínio dos hostnames recebidos antes de procurar o subdomínio em routes. routes é um mapa plano de subdomínio para URL upstream, não uma lista.

    cat > config/mcp-proxy.yaml <<EOF
    listen_addr: ":8080"
    log_level: info
    shutdown_timeout: 30s
    tunnel_domain: ${TUNNEL_DOMAIN}
    tls:
      cert_file: /data/tls.crt
      key_file: /data/tls.key
    routes:
      echo: http://hello-mcp:9000
    EOF

    A rota echo: aponta para o servidor MCP de exemplo; substitua-a por (ou adicione) suas próprias rotas. Consulte a referência de configuração do proxy para todos os campos disponíveis.

  5. Inicie a implantação

    export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
    docker compose up -d

O arquivo compose lê TUNNEL_TOKEN do ambiente do host sem valor padrão, portanto o export deve ser repetido em cada novo shell e após uma reinicialização.

Para uma implantação com várias VMs, copie o diretório mcp-tunnel/ para cada host, defina TUNNEL_TOKEN e execute docker compose up -d. No fluxo programático, TUNNEL_TOKEN é $(sudo cat data/tunnel-token); no fluxo manual, é o valor que você copiou do Console. O mesmo token de túnel e os mesmos certificados funcionam em todas as réplicas.

Verifique a implantação

Verifique de ponta a ponta chamando um servidor MCP upstream a partir do lado da Anthropic: consulte Use os servidores MCP tunelados. Com o servidor MCP de exemplo, a URL roteada é https://echo.<your-tunnel-domain>/mcp. Se a verificação falhar, consulte Solução de problemas.

Atualizações

Execute os comandos desta seção de dentro do diretório de implantação mcp-tunnel/.

Rotacione o token do túnel

Com acesso programático, incremente --token-version no comando do serviço setup, defina os identificadores de Workload Identity Federation, emita um novo JWT OIDC e execute novamente o componente de setup:

# Edite docker-compose.yaml: incremente o inteiro no argumento
# --token-version do serviço setup (por exemplo, de --token-version=1 para
# --token-version=2). O binário de setup se recusa a rotacionar quando o valor
# não mudou.

# export TUNNEL_ID=tnl_...   # defina apenas se você o definiu durante a instalação
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000
# export ANTHROPIC_WORKSPACE_ID=wrkspc_...   # se sua regra tiver escopo de workspace
# Gere novamente o ANTHROPIC_IDENTITY_TOKEN conforme o guia do provedor WIF para seu
# ambiente (ele terá expirado desde a instalação).
export ANTHROPIC_IDENTITY_TOKEN=...

docker compose run --rm setup

export TUNNEL_TOKEN=$(sudo cat data/tunnel-token)
docker compose up -d cloudflared

O argumento --token-version é editado em docker-compose.yaml em vez de ser passado na linha de comando, para que o novo valor persista em execuções futuras do componente de setup. O componente de setup se autentica com Workload Identity Federation; não há token de API a revogar.

Sem acesso programático, clique em Rotate token na página de detalhes do túnel no Console, depois atualize a variável de ambiente TUNNEL_TOKEN em cada host e reinicie o cloudflared (docker compose up -d cloudflared).

Renovação de certificado

Você é responsável por monitorar a expiração e renovar o certificado de servidor antes que ele expire.

Com acesso programático:

docker compose run --rm setup renew-cert --output=dir:/data

Os argumentos da CLI substituem o command do serviço setup (os argumentos de init), mas mantêm seu entrypoint, então isso executa /setup renew-cert --output=dir:/data.

Sem acesso programático, assine um novo certificado de servidor com sua CA existente (a CA registrada no Console não muda) e substitua data/tls.crt. Defina TUNNEL_DOMAIN primeiro se você estiver executando isso a partir de um novo shell.

export TUNNEL_DOMAIN=YOUR_TUNNEL_DOMAIN_HERE
openssl req -new -key data/tls.key -out /tmp/server.csr \
  -subj "/CN=${TUNNEL_DOMAIN}"
openssl x509 -req -in /tmp/server.csr \
  -CA data/ca.crt -CAkey data/ca.key -CAcreateserial \
  -out data/tls.crt -days 90 \
  -extfile data/tls.ext

Em qualquer um dos fluxos, o proxy consulta periodicamente tls.cert_file e o recarrega automaticamente, portanto nenhuma reinicialização é necessária.

Próximos passos

Anexe um servidor MCP upstream a um Managed Agent ou à Messages API.

Orientações de reforço, rotação de credenciais e resposta a violações.

Diagnostique problemas de conectividade, TLS e roteamento.

Was this page helpful?