kubernetools MCP Server
официальныйHelp AI agents write accurate, up-to-date Kubernetes manifests by giving them the official Kubernetes API reference, so they can look up kinds, fields, and nested types with current specs across the latest and three previous Kubernetes versions
Документация
kubernetools/mcp-server
Образ контейнера для MCP-сервера kubernetools.
Реестр: ghcr.io/kubernetools/mcp-server
Быстрый старт
Анонимный режим (локальное использование)
Аутентификация не требуется; все подключения ограничиваются по частоте на уровне бесплатного тарифа для каждого исходного IP-адреса.
podman run -d \
-p 3000:3000 \
-e K8S_VERSIONS=v1.33 \
ghcr.io/kubernetools/mcp-server:latest
С аутентификацией по API-ключу
# 1. Create a key store file
echo '[{"key":"mykey","tier":"free"}]' > keys.json
# 2. Start the server
podman run -d \
-p 3000:3000 \
-v "$(pwd)/keys.json:/keys.json:ro" \
-e K8S_VERSIONS=v1.33,v1.34,v1.35,v1.36 \
-e KEY_STORE_PATH=/keys.json \
ghcr.io/kubernetools/mcp-server:latest
Конфигурация
| Параметр | Переменная окружения | Описание |
|---|---|---|
| Версии Kubernetes | K8S_VERSIONS | Список версий для предварительной загрузки через запятую (например, v1.33,v1.34). По умолчанию: v1.33. |
| Токен GitHub | GITHUB_TOKEN | Персональный токен доступа (дополнительные разрешения не требуются). Необязательный параметр; повышает лимит частоты запросов к GitHub API с 60 до 5 000 запросов/ч — рекомендуется при загрузке нескольких версий. |
| Хранилище ключей | KEY_STORE_PATH | Путь к JSON-файлу с API-ключами (смонтируйте его в контейнер). Если не указан, сервер работает в анонимном режиме: аутентификация не требуется, и все подключения ограничиваются по частоте на уровне бесплатного тарифа для каждого исходного IP-адреса. |
| Разрешённые хосты | ALLOWED_HOSTS | Список допустимых значений заголовка Host через запятую (например, mcp.example.com,mcp.example.com:443). Если не указан, проверка хоста отключена — подходит только для локальной разработки. В production-среде всегда задавайте этот параметр для предотвращения атак с повторной привязкой DNS. |
| Перенаправление из браузера | BROWSER_REDIRECT_URL | URL для перенаправления обычных GET-запросов из браузера. MCP-клиенты определяются по Accept: text/event-stream; браузеры вместо этого получают 307 на этот URL. Если не указан, GET-запросы из браузера возвращают 400. |
| Уровень логирования | RUST_LOG | Фильтр уровня логирования (например, info, debug, mcp=debug). |
| Порт | --publish | Сервер слушает порт 3000. |
Аутентификация
Хранилище API-ключей
Хранилище ключей представляет собой плоский JSON-массив, загружаемый один раз при запуске:
[
{ "key": "free-key-abc", "tier": "free" },
{ "key": "paid-key-xyz", "tier": "paid" }
]
Каждый запрос должен содержать ключ в заголовке Authorization:
Authorization: Bearer free-key-abc
Запросы без действительного ключа получают 401 Unauthorized.
Анонимный режим
Если KEY_STORE_PATH не задан, сервер работает без аутентификации. Все подключения принимаются и ограничиваются по частоте на уровне бесплатного тарифа для каждого исходного IP-адреса. Удобно для локального использования; не открывайте публичный доступ.
Тарифы и ограничения частоты
| Тариф | Лимит |
|---|---|
free | 10 запросов/минуту, всплеск 10 |
paid | ~1 000 запросов/секунду, всплеск 1 000 (фактически безлимитный) |
Запросы, превышающие лимит, получают 429 Too Many Requests. Лимиты отслеживаются для каждого API-ключа, а не для IP-адреса.
Подключение MCP-клиента
Сервер реализует транспорт MCP Streamable HTTP. Конечная точка:
http://<host>:<port>/[?version=<k8s-version>]
Параметр запроса version выбирает версию Kubernetes для сессии. Если не указан, используется первая загруженная версия. При указании неизвестной версии возвращается 400 Bad Request.
Claude Desktop
Добавьте следующее в claude_desktop_config.json:
{
"mcpServers": {
"kubernetools": {
"url": "http://localhost:3000/?version=v1.36",
"headers": {
"Authorization": "Bearer mykey"
}
}
}
}
Доступные инструменты
list_resources
Облегчённое обнаружение — возвращает по одной записи на ресурс, отсортированной по (group, kind, api_version). Используйте этот инструмент в первую очередь для поиска имён типов (kind).
Необязательные фильтры: group (например, "apps", "core"), api_version (например, "v1").
get_resource
Полная информация о ресурсе — поля, spec, status и поля списков — достаточная для написания манифеста за один вызов. Обязательный параметр: kind. Необязательные: group, api_version (по умолчанию — самая последняя версия).
Поля с непустым type_ref и пустым sub_fields следует детализировать с помощью get_type.
get_type
Детализация отдельного составного типа, на который ссылается type_ref в выводе get_resource. Обязательный параметр: type_name (например, "Container", "PodFailurePolicy").
Типичный поток запросов
list_resources → discover kind names and groups
└─ get_resource(kind="Deployment") → see all top-level fields + spec/status
└─ get_type(type_name="...") → drill into any complex type_ref
Проверка работоспособности
GET /healthz на порту 3000.
- Возвращает
503 Service Unavailable(тело:loading) во время загрузки документации Kubernetes API. - Возвращает
200 OK(тело:ok) после готовности сервера.
Эта конечная точка не требует аутентификации и не имеет ограничений по частоте.
Используйте её для проб запуска, готовности и живости:
startupProbe:
httpGet:
path: /healthz
port: 3000
failureThreshold: 30 # allow up to 5 min for version loading
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
port: 3000
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 10
Ответы с ошибками
| HTTP-статус | Причина |
|---|---|
307 Temporary Redirect | GET-запрос из браузера, когда задан BROWSER_REDIRECT_URL |
400 Bad Request | GET-запрос из браузера, когда BROWSER_REDIRECT_URL не задан, или параметр version указывает версию, не загруженную при запуске |
401 Unauthorized | Отсутствует или недействителен заголовок Authorization: Bearer <key> |
429 Too Many Requests | Превышен лимит частоты для тарифа ключа |
Ошибки уровня MCP (неизвестное имя инструмента, отсутствует обязательный аргумент, тип не найден) возвращаются как содержимое ошибки MCP внутри обычного ответа 200.
Примеры
Несколько версий Kubernetes
podman run -d \
-p 3000:3000 \
-v "$(pwd)/keys.json:/keys.json:ro" \
-e K8S_VERSIONS=v1.33,v1.34,v1.35,v1.36 \
-e GITHUB_TOKEN=ghp_... \
-e KEY_STORE_PATH=/keys.json \
ghcr.io/kubernetools/mcp-server:latest
Production-настройка с проверкой хоста
podman run -d \
-p 3000:3000 \
-v "$(pwd)/keys.json:/keys.json:ro" \
-e K8S_VERSIONS=v1.36 \
-e KEY_STORE_PATH=/keys.json \
-e ALLOWED_HOSTS=mcp.example.com,mcp.example.com:443 \
-e BROWSER_REDIRECT_URL=https://example.com/docs \
ghcr.io/kubernetools/mcp-server:latest
Отладочное логирование
podman run -d \
-p 3000:3000 \
-e K8S_VERSIONS=v1.33 \
-e RUST_LOG=debug \
ghcr.io/kubernetools/mcp-server:latest
Привязка к конкретному релизу
podman run -d \
-p 3000:3000 \
-e K8S_VERSIONS=v1.33 \
ghcr.io/kubernetools/mcp-server:0.1.0
Образ
Собран на основе registry.access.redhat.com/hi/core-runtime:2.42-openssl — минимального, бездистрибутивного рантайма glibc + OpenSSL. Без оболочки и менеджера пакетов.