Claude Platform Docs
MessagesТуннели MCP

Развёртывание туннелей MCP с помощью Helm

Установите стек туннеля в кластер Kubernetes с помощью Helm-чарта Anthropic.

Helm-чарт Anthropic устанавливает стек туннеля как единый Deployment и подключает его к вашему туннелю: либо к тому, который создаёт для вас setup-хук чарта, либо к существующему туннелю, который вы создали в Console.

Прежде чем начать

Вам понадобится:

  • Туннель. При программном доступе setup-хук чарта создаёт его для вас, если вы не указываете идентификатор туннеля; чтобы вместо этого подключиться к существующему туннелю, создайте его в Console и запишите идентификатор туннеля (tnl_...). Ручная подготовка всегда начинается с туннеля, созданного в Console; вам также понадобятся его токен туннеля и домен туннеля.
  • Способ аутентификации чарта в Tunnels API.
    • Программный доступ (рекомендуется). Компонент setup аутентифицируется через Workload Identity Federation (федерацию удостоверений рабочих нагрузок), получает токен туннеля, генерирует CA, регистрирует его в Anthropic и сохраняет всё в Secret. Вам понадобится правило федерации с областью действия workspace:manage_tunnels.
    • Ручной. Пропустите программный доступ. Вы получите токен туннеля из Console, самостоятельно сгенерируете CA и серверный сертификат, зарегистрируете CA в Console и передадите учётные данные в кластер в виде Secrets.
  • Кластер Kubernetes, в который вы можете выполнять развёртывание с помощью helm и kubectl. На вкладке Без программного доступа также используется openssl (версии 1.1.1 или новее).
  • Исходящее сетевое подключение из кластера к api.anthropic.com (443 TCP) и к границе туннеля (tunnel edge) (7844 TCP и UDP). См. полные сетевые требования.
  • Один или несколько серверов MCP, запущенных и доступных из кластера по адресам, которые вы настроите в gateway.config.routes. Если у вас его ещё нет, используйте пример сервера.

Необязательно: использование примера сервера MCP

Если у вас нет сервера MCP для тестирования, используйте этот минимальный:

kubectl create namespace mcp-tunnel --dry-run=client -o yaml | kubectl apply -f -
kubectl -n mcp-tunnel apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: hello-mcp-src
data:
  hello_server.py: |
    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")
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-mcp
spec:
  replicas: 1
  selector:
    matchLabels: { app: hello-mcp }
  template:
    metadata:
      labels: { app: hello-mcp }
    spec:
      containers:
        - name: hello-mcp
          image: python:3.13-slim
          command: ["sh", "-c", "pip install --quiet mcp && python /app/hello_server.py"]
          volumeMounts:
            - { name: src, mountPath: /app }
          ports:
            - { containerPort: 9000 }
      volumes:
        - name: src
          configMap: { name: hello-mcp-src }
---
apiVersion: v1
kind: Service
metadata:
  name: hello-mcp
spec:
  selector: { app: hello-mcp }
  ports:
    - { port: 9000, targetPort: 9000 }
EOF

В следующих далее шагах установки указано, где добавить соответствующий маршрут.

Установка

Компонент setup обменивает спроецированный токен ServiceAccount кластера через ваше правило федерации, получает токен туннеля, генерирует CA и серверный сертификат и регистрирует CA в Anthropic. Ежедневный CronJob обновляет серверный сертификат по мере необходимости, поэтому вам не нужно работать с какими-либо секретами вручную.

  1. Настройте Workload Identity Federation для кластера

    Следуйте руководству Использование WIF с Kubernetes, чтобы зарегистрировать OIDC-издателя вашего кластера и создать правило федерации. Компонент setup работает под собственным ServiceAccount в пространстве имён релиза; точное имя следует соглашению Helm fullname, поэтому для любого имени релиза, отличного от mcp-tunnel, выполните helm template <release> ... | grep -A2 'kind: ServiceAccount', чтобы подтвердить его перед созданием правила. В остальной части этого руководства предполагается имя релиза mcp-tunnel в пространстве имён mcp-tunnel, где ServiceAccount называется mcp-tunnel-setup.

    ПолеЗначение
    Subjectsystem:serviceaccount:mcp-tunnel:mcp-tunnel-setup
    Audienceapi.anthropic.com (значение чарта по умолчанию; без схемы)
    Scopeworkspace:manage_tunnels

    Если туннель находится в рабочем пространстве, отличном от рабочего пространства организации по умолчанию, также добавьте сервисный аккаунт правила в качестве участника этого рабочего пространства в разделе Settings > Workspaces (Tunnels API выполняет авторизацию на основе членства сервисного аккаунта в рабочих пространствах).

    Запишите идентификатор правила (fdrl_...); вы укажете его как api.wif.federationRuleId.

  2. Получите значения по умолчанию

    helm show values \
      oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
      --version 2.0.2 > values.yaml
  3. Настройте подключение к туннелю и маршруты

    Отредактируйте values.yaml и задайте ключи api.wif.* с идентификатором правила федерации и идентификатором организации, а также запись routes для каждого вышестоящего сервера MCP (upstream MCP server):

    values.yaml
    api:
      wif:
        federationRuleId: "fdrl_..."
        organizationId: "00000000-0000-0000-0000-000000000000"
        # Set when the tunnel is in a non-default workspace and the
        # rule's service account is a member of that workspace.
        # workspaceId: "wrkspc_..."
    
    tunnel:
      # Leave empty to have the setup hook create a tunnel during install.
      # Set to attach to an existing tunnel from the Console.
      id: ""
      # Increment to rotate the tunnel token on the next upgrade.
      # See the "Rotate the tunnel token" section.
      tokenVersion: "1"
    
    gateway:
      config:
        routes:
          docs: http://docs-mcp.internal:8080
          search: http://search-mcp.internal:8080

    С этими маршрутами Claude обращается к серверам по адресам docs.<your-tunnel-domain> и search.<your-tunnel-domain>. Некоторые управляемые дистрибутивы Kubernetes выделяют Service CIDR за пределами стандартных частных диапазонов; если ваши маршруты указывают на внутрикластерные Services, добавьте здесь gateway.config.upstream.allowed_ips согласно разделу Проверка IP-адресов вышестоящих серверов.

  4. Проверьте отрендеренные манифесты

    Отрендерите чарт и проверьте результат в соответствии с практиками проверки вашей организации:

    helm template mcp-tunnel \
      oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
      --version 2.0.2 \
      -n mcp-tunnel \
      -f values.yaml > rendered.yaml
  5. Установите

    helm install mcp-tunnel \
      oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
      --version 2.0.2 \
      --namespace mcp-tunnel --create-namespace \
      -f values.yaml

    Компонент setup запускается как Job pre-install-хука Helm, поэтому helm install блокируется до его завершения. При успехе Helm автоматически удаляет Job. Если helm install завершается ошибкой хука, см. раздел Сбои аутентификации компонента setup.

    Когда tunnel.id пуст, компонент setup создаёт туннель в рабочем пространстве, на которое нацелено ваше правило федерации (рабочее пространство организации по умолчанию, если вы не задали api.wif.workspaceId), и сохраняет его идентификатор и домен в Secret mcp-tunnel. Найдите домен, который понадобится вам для проверки, на странице сведений о туннеле в Console в разделе Manage > MCP tunnels или прочитайте его из Secret:

    kubectl -n mcp-tunnel get secret mcp-tunnel \
      -o jsonpath='{.data.tunnel-domain}' | base64 -d

    Повторный запуск компонента setup (во время обновлений или ротации токена) повторно использует идентификатор туннеля, сохранённый в этом Secret; он никогда не создаёт второй туннель.

Проверка развёртывания

Выполните сквозную проверку со стороны Anthropic: используйте https://<route>.<your-tunnel-domain>/<path> в сеансе Managed Agent или в запросе Messages API, где <route> — ключ из gateway.config.routes, а <path> — путь, по которому обслуживает запросы вышестоящий сервер MCP. С примером сервера MCP это https://echo.<your-tunnel-domain>/mcp. Форматы запросов см. в разделе Использование туннелированных серверов MCP.

Если это не удаётся, проверьте логи пода (kubectl -n mcp-tunnel logs deploy/mcp-tunnel -c mcp-proxy и -c cloudflared) и обратитесь к разделу Устранение неполадок.

Необязательная конфигурация

Ограничение исходящего трафика с помощью NetworkPolicy

Входящий трафик к поду прокси по умолчанию запрещён (networkPolicy.ingress.enabled: true). Чтобы дополнительно ограничить исходящий трафик пода, установите networkPolicy.egress.enabled: true и заполните networkPolicy.egress.mcpServers селекторами меток подов или диапазонами CIDR, охватывающими ваши вышестоящие серверы MCP. Исходящий трафик от cloudflared к границе туннеля разрешается отдельно через networkPolicy.egress.cloudflaredEgressCIDRs.

Настройка прокси

Поля в gateway.config.* передаются напрямую в файл конфигурации прокси. Распространённые настройки включают upstream.allowed_ips, log_level и upstream.tls. Полный список полей см. в справочнике по конфигурации прокси. Чарт всегда задаёт listen_addr, tls.cert_file и tls.key_file; их установка в gateway.config не имеет эффекта.

Использование собственного OIDC-токена

По умолчанию чарт проецирует токен Kubernetes ServiceAccount для компонента setup. Чтобы использовать токен от другого поставщика удостоверений (например, SPIFFE, Vault или sidecar облачного SDK), смонтируйте его с помощью setup.extraVolumes и setup.extraVolumeMounts. Затем укажите в api.wif.tokenFile путь монтирования. Чарт устанавливает ANTHROPIC_IDENTITY_TOKEN_FILE в этот путь, и компонент setup читает токен оттуда.

Обновления

Всегда передавайте --version в helm upgrade, чтобы случайно не загрузить более новый чарт.

Обновление с чарта 1.x

Чарт 2.0.0 переносит идентификатор туннеля из api.wif.tunnelId в tunnel.id. Перед обновлением отредактируйте ваш values.yaml: перенесите значение tnl_... в tunnel.id и удалите api.wif.tunnelId. Оставить tunnel.id незаданным безопасно (компонент setup при повторном запуске повторно использует идентификатор туннеля, уже сохранённый в Secret mcp-tunnel), но явный перенос сохраняет точность вашего values.yaml. Также обновите область действия вашего правила федерации с org:manage_tunnels на workspace:manage_tunnels в Console.

Изменение конфигурации

Для рутинных изменений, таких как маршруты, количество реплик или NetworkPolicy:

helm upgrade mcp-tunnel \
  oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
  --version 2.0.2 \
  -n mcp-tunnel \
  -f values.yaml

Ротация токена туннеля

При программном доступе увеличьте tunnel.tokenVersion в values.yaml и выполните обновление с --set setup.force=true. Компонент setup повторно запускается при обновлениях только принудительно:

helm upgrade mcp-tunnel \
  oci://us-docker.pkg.dev/anthropic-public-registry/charts/mcp-tunnel \
  --version 2.0.2 \
  -n mcp-tunnel \
  -f values.yaml \
  --set setup.force=true

Компонент setup аутентифицируется с помощью Workload Identity Federation; токена API, который нужно было бы отзывать, нет.

Без программного доступа нажмите Rotate token на странице сведений о туннеле в Console, затем обновите Secret mcp-tunnel-token:

kubectl -n mcp-tunnel create secret generic mcp-tunnel-token \
  --from-literal=tunnel-token='eyJ...' --dry-run=client -o yaml | kubectl apply -f -
kubectl -n mcp-tunnel rollout restart deploy/mcp-tunnel

Обновление сертификата

Чарт предоставляет автоматизацию, но вы по-прежнему несёте ответственность за отслеживание срока действия и подтверждение завершения обновления.

При программном доступе обновление сертификата происходит автоматически. Чарт развёртывает CronJob (названный по Helm fullname с суффиксом -cert-renew), который ежедневно запускает setup renew-cert (по расписанию serverCert.cronSchedule, по умолчанию 0 0 * * * UTC). Задание ничего не делает, если до истечения срока действия сертификата остаётся больше serverCert.renewBefore (по умолчанию 30 дней). Обновление выполняется локально: задание подписывает новый сертификат с помощью CA, уже сохранённого в Secret, не выполняет вызовов API и нуждается только в Kubernetes RBAC, который предоставляет чарт. Прокси выполняет горячую перезагрузку сертификата из смонтированного Secret, поэтому перезапуск Deployment не требуется.

Без программного доступа CronJob отсутствует. Из каталога mcp-tunnel/, который вы сохранили после установки, подпишите новый серверный сертификат существующим CA (не генерируйте CA заново):

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

kubectl -n mcp-tunnel create secret generic mcp-tunnel-cert \
  --from-file=tls.crt=data/tls.crt --from-file=tls.key=data/tls.key \
  --dry-run=client -o yaml | kubectl apply -f -

Прокси выполняет горячую перезагрузку сертификата из смонтированного Secret.

Следующие шаги

Подключите вышестоящий сервер MCP к Managed Agent или Messages API.

Рекомендации по усилению защиты, ротация учётных данных и реагирование на взлом.

Диагностика проблем с подключением, TLS и маршрутизацией.

Was this page helpful?