ToolHive поднят — через него поднимается MCP-сервер для Kubernetes. Одна задача = один MR: только MCP, без внешней экспозиции и без OIDC.
Сервер: containers/kubernetes-mcp-server, а не mkp из реестра ToolHive
Первый вариант был ghcr.io/stackloklabs/mkp/server (сервер k8s из реестра ToolHive) — просто потому, что он в реестре. Сравнение не в его пользу, поэтому переключились:
containers/kubernetes-mcp-server
stackloklabs/mkp
Звёзды / форки
2104 / 439
59 / —
Последний коммит
2026-09-17
2026-09-11
Лицензия, язык
Apache-2.0, Go
Apache-2.0, Go
Read-only режим
есть (--read-only, --disable-destructive)
нет
Отключение наборов инструментов
есть (--toolsets)
нет
Скрыть ресурс от инструментов
есть (denied_resources, disabled_tools)
нет
Гайд по деплою с read-only SA
есть (docs/getting-started-kubernetes.md)
нет
Официальный Helm-чарт
есть, с OAuth
нет
Сообщество
канал в CNCF Slack, мейнтейнеры Red Hat
внутри Stacklok
Ключевое: у mkp нет ни одного «безопасного» режима — единственная граница там RBAC. У этого сервера есть штатный --read-only (полный запрет create/update/delete), --toolsets и фильтрация инструментов, то есть защита не одной, а двумя-тремя независимыми линиями.
Что сделано
kubernetes/apps/ai/mcp-k8s/ks.yaml — Flux Kustomization с targetNamespace: ai и dependsOn: [toolhive-operator]. Зависимость внутри своего ns, поэтому namespace в dependsOn нет — поле понадобится, когда зависимость будет в другом ns (Dragonfly CR в ai → оператор в database).
app/serviceaccount.yaml — SA mcp-k8s. Нужен явно: по CRD spec.serviceAccount означает «уже существующий», иначе оператор создаст свой.
app/rbac.yaml — ClusterRoleBinding на встроенную view + небольшой ClusterRole на кластерные объекты и метрики.
app/mcpserver.yaml — MCPServer mcp-k8s.
Права
Базовое чтение — встроенная роль view, а не самодельный список с resources: ["*"]: она покрывает namespaced-ресурсы (включая pods/log) и не включает secrets, а это именно то, что нужно — cluster-secrets, токен Proxmox CSI и прочая креда агенту не нужны. view описывает только namespaced-объекты, поэтому кластерное (nodes, namespaces, persistentvolumes, storage-классы) и метрики (metrics.k8s.io, чтобы работал top) добавлены отдельным ClusterRole. Записи и pods/exec нет нигде.
Поверх этого на самом сервере включён --read-only, а --toolsets core убирает наборы helm, tekton, kubevirt, kiali и netobserv — чарты в кластере ставит Flux, агенту там делать нечего.
Образ
quay.io/containers/kubernetes_mcp_server:v0.0.66@sha256:6d650f4bd6ac303ad82713c997e73a2d001602f9bf17392c9b9a0e30e29c6423 — тег проверен в API quay (от 2026-07-31, manifest list на 4 архитектуры). У чартов проекта образ на quay, ghcr-зеркала нет: если из кластера quay окажется медленным или недоступным, закрываем это proxy-cache проектом в нашем Harbor, но это уже отдельная задача.
Важно про аутентификацию
oidcConfigRef не задан, значит прокси ToolHive работает без аутентификации: любой, кто достучится до порта, получит API под правами SA. Поэтому наружу сервер не выводим (ни LB-IP, ни HTTPRoute) — пока агент вне кластера, адрес внутрикластерный. Внешний доступ появится вместе с OIDC после Authelia; тогда же имеет смысл denied_resources в TOML, чтобы прятать ресурсы на уровне инструментов, а не только правами.
kubectl kustomize kubernetes/apps/ai/mcp-k8s/app — SA, ClusterRole, два binding, MCPServer.
Дальше
searxng в ai + Dragonfly CR там же с dependsOn: [{name: dragonfly-operator, namespace: database}].
Authelia → OIDC для прокси ToolHive (и заодно для Hermes-дашборда и Vault).
ToolHive поднят — через него поднимается MCP-сервер для Kubernetes. Одна задача = один MR: только MCP, без внешней экспозиции и без OIDC.
**Сервер: containers/kubernetes-mcp-server, а не mkp из реестра ToolHive**
Первый вариант был `ghcr.io/stackloklabs/mkp/server` (сервер `k8s` из реестра ToolHive) — просто потому, что он в реестре. Сравнение не в его пользу, поэтому переключились:
| | containers/kubernetes-mcp-server | stackloklabs/mkp |
|---|---|---|
| Звёзды / форки | 2104 / 439 | 59 / — |
| Последний коммит | 2026-09-17 | 2026-09-11 |
| Лицензия, язык | Apache-2.0, Go | Apache-2.0, Go |
| Read-only режим | есть (`--read-only`, `--disable-destructive`) | нет |
| Отключение наборов инструментов | есть (`--toolsets`) | нет |
| Скрыть ресурс от инструментов | есть (`denied_resources`, `disabled_tools`) | нет |
| Гайд по деплою с read-only SA | есть (docs/getting-started-kubernetes.md) | нет |
| Официальный Helm-чарт | есть, с OAuth | нет |
| Сообщество | канал в CNCF Slack, мейнтейнеры Red Hat | внутри Stacklok |
Ключевое: у mkp нет ни одного «безопасного» режима — единственная граница там RBAC. У этого сервера есть штатный `--read-only` (полный запрет create/update/delete), `--toolsets` и фильтрация инструментов, то есть защита не одной, а двумя-тремя независимыми линиями.
**Что сделано**
- `kubernetes/apps/ai/mcp-k8s/ks.yaml` — Flux Kustomization с `targetNamespace: ai` и `dependsOn: [toolhive-operator]`. Зависимость внутри своего ns, поэтому `namespace` в `dependsOn` нет — поле понадобится, когда зависимость будет в другом ns (Dragonfly CR в `ai` → оператор в `database`).
- `app/serviceaccount.yaml` — SA `mcp-k8s`. Нужен явно: по CRD `spec.serviceAccount` означает «уже существующий», иначе оператор создаст свой.
- `app/rbac.yaml` — ClusterRoleBinding на встроенную `view` + небольшой ClusterRole на кластерные объекты и метрики.
- `app/mcpserver.yaml` — MCPServer `mcp-k8s`.
**Права**
Базовое чтение — встроенная роль `view`, а не самодельный список с `resources: ["*"]`: она покрывает namespaced-ресурсы (включая `pods/log`) и **не** включает secrets, а это именно то, что нужно — `cluster-secrets`, токен Proxmox CSI и прочая креда агенту не нужны. `view` описывает только namespaced-объекты, поэтому кластерное (`nodes`, `namespaces`, `persistentvolumes`, storage-классы) и метрики (`metrics.k8s.io`, чтобы работал `top`) добавлены отдельным ClusterRole. Записи и `pods/exec` нет нигде.
Поверх этого на самом сервере включён `--read-only`, а `--toolsets core` убирает наборы helm, tekton, kubevirt, kiali и netobserv — чарты в кластере ставит Flux, агенту там делать нечего.
**Образ**
`quay.io/containers/kubernetes_mcp_server:v0.0.66@sha256:6d650f4bd6ac303ad82713c997e73a2d001602f9bf17392c9b9a0e30e29c6423` — тег проверен в API quay (от 2026-07-31, manifest list на 4 архитектуры). У чартов проекта образ на quay, ghcr-зеркала нет: если из кластера quay окажется медленным или недоступным, закрываем это proxy-cache проектом в нашем Harbor, но это уже отдельная задача.
**Важно про аутентификацию**
`oidcConfigRef` не задан, значит прокси ToolHive работает **без аутентификации**: любой, кто достучится до порта, получит API под правами SA. Поэтому наружу сервер не выводим (ни LB-IP, ни HTTPRoute) — пока агент вне кластера, адрес внутрикластерный. Внешний доступ появится вместе с OIDC после Authelia; тогда же имеет смысл `denied_resources` в TOML, чтобы прятать ресурсы на уровне инструментов, а не только правами.
**Проверено**
- `kubectl kustomize kubernetes/apps/ai` — собирается, Flux Kustomization рендерится в ns `ai`.
- `kubectl kustomize kubernetes/apps/ai/mcp-k8s/app` — SA, ClusterRole, два binding, MCPServer.
**Дальше**
- searxng в `ai` + Dragonfly CR там же с `dependsOn: [{name: dragonfly-operator, namespace: database}]`.
- Authelia → OIDC для прокси ToolHive (и заодно для Hermes-дашборда и Vault).
MCP-сервер k8s из реестра ToolHive: ghcr.io/stackloklabs/mkp/server:0.4.3, transport streamable-http.
Отдельный SA mcp-k8s и ClusterRole mcp-k8s-readonly (только get/list/watch).
Core-группа перечислена поимённо, чтобы не открывать secrets; остальные группы явным списком,
потому что apiGroups: [*] включает и core-группу. Наружу не выводим: без oidcConfigRef прокси
ToolHive неаутентифицирован.
У mkp нет ни одного безопасного режима, только RBAC. У containers/kubernetes-mcp-server есть
штатный --read-only, --toolsets и denied_resources, официальный гайд по read-only SA и чарт.
Образ quay.io/containers/kubernetes_mcp_server:v0.0.66 с дайджестом (тег проверен в API quay).
RBAC: вместо самодельного списка — встроенная view (secrets в неё не входят) + отдельный
ClusterRole на кластерные объекты и метрики. Аргументы: --port 8080 --read-only --toolsets core.
Some checks are pending
Flate / Flate - Success (pull_request) Blocked by required conditions
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
ToolHive поднят — через него поднимается MCP-сервер для Kubernetes. Одна задача = один MR: только MCP, без внешней экспозиции и без OIDC.
Сервер: containers/kubernetes-mcp-server, а не mkp из реестра ToolHive
Первый вариант был
ghcr.io/stackloklabs/mkp/server(серверk8sиз реестра ToolHive) — просто потому, что он в реестре. Сравнение не в его пользу, поэтому переключились:--read-only,--disable-destructive)--toolsets)denied_resources,disabled_tools)Ключевое: у mkp нет ни одного «безопасного» режима — единственная граница там RBAC. У этого сервера есть штатный
--read-only(полный запрет create/update/delete),--toolsetsи фильтрация инструментов, то есть защита не одной, а двумя-тремя независимыми линиями.Что сделано
kubernetes/apps/ai/mcp-k8s/ks.yaml— Flux Kustomization сtargetNamespace: aiиdependsOn: [toolhive-operator]. Зависимость внутри своего ns, поэтомуnamespaceвdependsOnнет — поле понадобится, когда зависимость будет в другом ns (Dragonfly CR вai→ оператор вdatabase).app/serviceaccount.yaml— SAmcp-k8s. Нужен явно: по CRDspec.serviceAccountозначает «уже существующий», иначе оператор создаст свой.app/rbac.yaml— ClusterRoleBinding на встроеннуюview+ небольшой ClusterRole на кластерные объекты и метрики.app/mcpserver.yaml— MCPServermcp-k8s.Права
Базовое чтение — встроенная роль
view, а не самодельный список сresources: ["*"]: она покрывает namespaced-ресурсы (включаяpods/log) и не включает secrets, а это именно то, что нужно —cluster-secrets, токен Proxmox CSI и прочая креда агенту не нужны.viewописывает только namespaced-объекты, поэтому кластерное (nodes,namespaces,persistentvolumes, storage-классы) и метрики (metrics.k8s.io, чтобы работалtop) добавлены отдельным ClusterRole. Записи иpods/execнет нигде.Поверх этого на самом сервере включён
--read-only, а--toolsets coreубирает наборы helm, tekton, kubevirt, kiali и netobserv — чарты в кластере ставит Flux, агенту там делать нечего.Образ
quay.io/containers/kubernetes_mcp_server:v0.0.66@sha256:6d650f4bd6ac303ad82713c997e73a2d001602f9bf17392c9b9a0e30e29c6423— тег проверен в API quay (от 2026-07-31, manifest list на 4 архитектуры). У чартов проекта образ на quay, ghcr-зеркала нет: если из кластера quay окажется медленным или недоступным, закрываем это proxy-cache проектом в нашем Harbor, но это уже отдельная задача.Важно про аутентификацию
oidcConfigRefне задан, значит прокси ToolHive работает без аутентификации: любой, кто достучится до порта, получит API под правами SA. Поэтому наружу сервер не выводим (ни LB-IP, ни HTTPRoute) — пока агент вне кластера, адрес внутрикластерный. Внешний доступ появится вместе с OIDC после Authelia; тогда же имеет смыслdenied_resourcesв TOML, чтобы прятать ресурсы на уровне инструментов, а не только правами.Проверено
kubectl kustomize kubernetes/apps/ai— собирается, Flux Kustomization рендерится в nsai.kubectl kustomize kubernetes/apps/ai/mcp-k8s/app— SA, ClusterRole, два binding, MCPServer.Дальше
ai+ Dragonfly CR там же сdependsOn: [{name: dragonfly-operator, namespace: database}].View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.