Устранение неполадок туннелей MCP
Диагностика проблем с подключением, TLS, проверкой IP-адресов и маршрутизацией OAuth в стеке туннеля.
Запрос через туннель может завершиться ошибкой на одном из трёх уровней; диагностируйте их по порядку: исходящее соединение с границей туннеля (tunnel edge), внутренний TLS (inner TLS) от Anthropic к вашему прокси, затем маршрутизация и проверка IP-адресов в направлении вышестоящего сервера MCP (upstream MCP server).
Краткая справка
| Симптом | Причина | Исправление |
|---|---|---|
| Туннель не отображается в средстве выбора + MCP Server агента | В средстве выбора перечислены только туннели из рабочего пространства сессии, у которых есть хотя бы один активный сертификат. | Зарегистрируйте сертификат CA или откройте сессию в рабочем пространстве, в котором был создан туннель. |
Вызывающая сторона видит HTTP 500; cloudflared пишет в журнал No ingress rules were defined | У cloudflared нет локальной цели. | Добавьте --url http://localhost:8080 и network_mode: "service:mcp-proxy" в сервис cloudflared. |
Прокси пишет в журнал no route for host | tunnel_domain не совпадает с назначенным доменом, или config.yaml был отредактирован без перезапуска. | Установите tunnel_domain в точности равным домену, показанному на странице сведений о туннеле, затем перезапустите прокси (docker compose restart mcp-proxy). |
Прокси пишет в журнал IP validation failed: <ip> is not a private address | Вышестоящий сервер MCP разрешается в адрес вне RFC1918. | См. Проверка IP-адресов вышестоящего сервера. |
Прокси завершается с ошибкой cannot unmarshal !!seq into map[string]string | routes задан как список YAML. | Используйте routes: { name: http://host:port }. |
Прокси завершается с ошибкой open /data/tls.key: permission denied | Ключ имеет права 0600; контейнер прокси запускается не от root. | chmod 644 data/tls.key. |
curl https://<proxy>:8080 завершается ошибкой wrong version number | Ожидаемо; слушатель принимает незашифрованный WebSocket. TLS выполняется внутри потока WS. | Вместо этого проверяйте через Managed Agent или Messages API. |
В следующих разделах рассматриваются сбои, для устранения которых недостаточно исправления в одну строку.
OAuth не работает за списком разрешённых исходных IP-адресов
Потоки OAuth завершаются ошибкой, когда список разрешённых исходных IP-адресов (source-IP allowlist) вашего сервера авторизации блокирует доступ бэкенда Anthropic к /token, /register и конечным точкам обнаружения. Если вы предпочитаете не добавлять диапазоны исходящих адресов Anthropic в список разрешённых, вы можете направить вызовы OAuth между бэкендами через туннель, сохранив обращённую к браузеру конечную точку /authorize на вашем существующем публичном имени хоста.
Добавьте маршрут прокси для сервера авторизации
routes: mcp: http://your-mcp-server:8080 auth: http://your-auth-server:8080Перезапустите прокси после редактирования
routes(docker compose restart mcp-proxyилиhelm upgrade).Отдавайте метаданные обнаружения с разделёнными конечными точками
Ответ
/.well-known/oauth-authorization-serverвашего сервера авторизации должен указыватьauthorization_endpointна ваше существующее имя хоста из списка разрешённых, а всё остальное — на туннель:{ "issuer": "https://auth.<tunnel-domain>", "authorization_endpoint": "https://<your-allowlisted-host>/authorize", "token_endpoint": "https://auth.<tunnel-domain>/token", "registration_endpoint": "https://auth.<tunnel-domain>/register", "code_challenge_methods_supported": ["S256"] }Направьте сервер MCP на издателя в туннеле
Ответ
/.well-known/oauth-protected-resourceвашего сервера MCP должен ссылаться на имя хоста туннеля как на свой сервер авторизации:{ "resource": "https://mcp.<tunnel-domain>", "authorization_servers": ["https://auth.<tunnel-domain>"] }
При такой конфигурации браузер пользователя обращается к /authorize на вашем существующем имени хоста (что ваш список разрешённых уже допускает), а бэкенд Anthropic получает доступ к /token, /register и документам обнаружения через туннель.
Сбои аутентификации компонента настройки
Компонент настройки (setup component) — Helm Job или сервис Compose setup — аутентифицируется в Tunnels API, обменивая OIDC JWT через ваше правило федерации. Если обмен завершается ошибкой, см. раздел Устранение неполадок при неудачном обмене в справочнике по Workload Identity Federation; режимы сбоев (subject, audience, issuer, JWKS, срок действия) те же самые.
Причины, специфичные для туннелей:
- Значение audience по умолчанию в чарте —
api.anthropic.com(без схемы). Если audience вашего правила —https://api.anthropic.com, установитеapi.wif.audienceсоответствующим образом. - Ответ
403от Tunnels API после успешного обмена означает, что область действия (scope) правила не включаетworkspace:manage_tunnels, или сервисный аккаунт правила не является участником рабочего пространства туннеля. Задайте область действия и добавьте сервисный аккаунт в рабочее пространство.
В Helm компонент настройки запускается как Job-хук pre-install. При сбое Job остаётся для изучения (kubectl logs job/mcp-tunnel-setup -n mcp-tunnel). Helm не управляет ресурсами хуков, поэтому удалите его перед повторной попыткой:
helm uninstall mcp-tunnel -n mcp-tunnel
kubectl -n mcp-tunnel delete job mcp-tunnel-setupТуннель не подключается
Сначала проверьте журналы cloudflared. Распространённые причины:
TUNNEL_TOKENотсутствует, истёк или скопирован неправильно.- Брандмауэр блокирует исходящий TCP/UDP-трафик на порт 7844 к границе туннеля.
cloudflared также может записывать в журнал предупреждения о размерах буфера приёма UDP; это подсказка по настройке QUIC, а не ошибка.
Ошибки сертификатов
Когда Anthropic отклоняет сертификат прокси во время внутреннего TLS, прокси пишет в журнал tls handshake failed. Убедитесь, что:
- Срок действия сертификата сервера не истёк.
- Subject Alternative Name сертификата соответствует
*.<tunnel-domain>. - Подписывающий CA зарегистрирован в Anthropic для этого туннеля.
Полные правила проверки см. в требованиях к сертификатам.
Проверка IP-адресов вышестоящего сервера
Для защиты от SSRF прокси по умолчанию устанавливает соединения только с адресами из частных диапазонов RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). Для соединения от прокси к вышестоящему серверу поддерживается только IPv4. (Диапазон исходящих адресов от cloudflared к границе туннеля в разделе Сетевые требования относится к другому участку маршрута.)
Если прокси пишет в журнал IP validation failed: <ip> is not a private address, имя хоста вышестоящего сервера разрешилось в адрес вне этого набора. В Kubernetes некоторые управляемые дистрибутивы выделяют Service CIDR вне RFC1918; если kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}' возвращает адрес вне частных диапазонов, узнайте Service CIDR вашего кластера и добавьте его.
Если адрес легитимен, добавьте самый узкий покрывающий его CIDR в upstream.allowed_ips. Установка allowed_ips заменяет значение RFC1918 по умолчанию, а не расширяет его, поэтому включите частные диапазоны, которые используют ваши другие вышестоящие серверы MCP:
upstream:
allowed_ips:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 127.0.0.0/8 # loopback, for local testing onlyWas this page helpful?