platform-mcp

platform-mcp

MCP server for Argo CD and Vault that allows authenticated users to run CLI commands via GitLab SSO, with confirmation for dangerous operations and secret redaction from model context.

Category
访问服务器

README

platform-mcp

MCP-сервер для инфраструктурных сервисов кластера sonar-prod — Argo CD и Vault — с входом через GitLab SSO.

Зачем

Агенту в редакторе нужен доступ к Argo CD и Vault, но выдавать ему сервисную учётку нельзя: в аудите вместо человека появится общий аккаунт, а права окажутся шире, чем у любого конкретного разработчика.

Этот пакет ставится локально и проводит обычный SSO-вход через браузер — тот же FreeIPA → GitLab → OIDC, что и при входе руками. Дальше он выполняет команды от имени вошедшего пользователя: в аудит-логах Argo CD и Vault виден реальный логин, а права ровно те, что даёт членство в группах GitLab.

Инструмент на сервис ровно один — argocd_exec и vault_exec, принимающие аргументы командной строки. Это осознанный выбор в пользу полноты: под капотом работают официальные CLI, поэтому доступно всё, что умеют они, а не заранее отобранный набор операций. Новый сервис добавляется одной реализацией интерфейса, без придумывания инструмента под каждую команду.

Установка

Шаг 1. Доступ к реестру пакетов

Нужен один раз и для всех способов ниже: пакет лежит в npm registry этого GitLab-проекта, а не в публичном npm. Возьмите токен с правом read_package_registry (личный access token или deploy token проекта) и добавьте в ~/.npmrc:

@sonar:registry=https://git.sonar-corp.ru/api/v4/projects/98/packages/npm/
//git.sonar-corp.ru/api/v4/projects/98/packages/npm/:_authToken=<ваш gitlab токен>

Шаг 2. Подключение к редактору

Claude Code и Cursor — плагином. Репозиторий сам себе каталог плагинов, поэтому достаточно двух команд:

/plugin marketplace add https://github.com/K-manankov/platform-mcp.git
/plugin install platform-mcp

Адрес именно GitHub, а не GitLab, и это не опечатка — см. Почему каталог плагинов на GitHub.

Адреса Argo CD и Vault уже прописаны в плагине — настраивать ничего не нужно. Обновления приезжают сами: плагин запускает сервер через npx -y, то есть всегда последнюю опубликованную версию. Обновить сам плагин — /plugin marketplace update.

Claude Desktop плагины этого формата не устанавливает, поэтому там запись делается вручную. Поставьте пакет глобально:

npm install -g @sonar/platform-mcp

и добавьте в claude_desktop_config.json (Settings → Developer → Edit Config). Путь к node и к серверу — обязательно абсолютные: GUI-приложения на macOS не наследуют PATH из шелла. Свои пути посмотрите командами which node и which platform-mcp:

{
  "mcpServers": {
    "platform": {
      "command": "/opt/homebrew/bin/node",
      "args": ["/opt/homebrew/lib/node_modules/@sonar/platform-mcp/dist/index.js"],
      "env": {
        "ARGOCD_BASE_URL": "https://argocd.infra.sonar-corp.ru",
        "VAULT_ADDR": "https://vault.infra.sonar-corp.ru",
        "PLATFORM_MCP_INSECURE": "true"
      }
    }
  }
}

Argo CD и Vault ставить отдельно не нужно ни в одном из вариантов: сервер сам скачает нужные версии CLI при первом обращении (см. Откуда берутся argocd и vault).

Почему каталог плагинов на GitHub

Claude Desktop подключает каталоги плагинов только с GitHub. Плюс к этому наш GitLab живёт во внутренней сети и снаружи недоступен в принципе, так что до git.sonar-corp.ru он бы и не дотянулся.

Поэтому исходный код остаётся в GitLab, а в github.com/K-manankov/platform-mcp настроено зеркало защищённых веток. Защищена одна ветка — main, и именно она уезжает на GitHub при каждом пуше. Обратной синхронизации нет: правки делаются только в GitLab, GitHub-копия существует ради установки плагина.

Само зеркало ничего не раскрывает лишнего — там тот же публичный npm-пакет и адреса внутренних сервисов, которые всё равно резолвятся только из сети. Секретов в репозитории нет и быть не должно: токены доступа сервер держит в ~/.config/platform-mcp/, а токен реестра пакетов каждый заводит себе сам в ~/.npmrc.

Обновить установленный плагин после изменений:

/plugin marketplace update sonar-infra
/plugin update platform-mcp

Вход

Нужен VPN: имена argocd.infra.sonar-corp.ru и vault.infra.sonar-corp.ru резолвятся только изнутри сети. Снаружи их подхватывает публичный wildcard *.infra.sonar-corp.ru, и запрос молча уезжает не туда — проверка dig +short argocd.infra.sonar-corp.ru должна дать 192.168.88.106.

Проще всего войти прямо из диалога: попросите агента вызвать argocd_login или vault_login, откройте выданную ссылку и завершите вход через GitLab. Перезапускать редактор не нужно.

То же самое из терминала, если пакет установлен глобально:

export ARGOCD_BASE_URL=https://argocd.infra.sonar-corp.ru
export VAULT_ADDR=https://vault.infra.sonar-corp.ru
export PLATFORM_MCP_INSECURE=true   # пока нет настоящих сертификатов, см. TLS

platform-mcp login          # в оба сервиса подряд
platform-mcp login vault    # только в один

Откроется браузер, дальше обычный вход через GitLab. Сессии лягут в ~/.config/platform-mcp/ с правами 0600 и общие для всех редакторов: войдя один раз, вы вошли везде.

По SSH или в devcontainer, где браузера нет:

platform-mcp login --no-browser

Ссылку из вывода нужно открыть на своей машине; порт 8085 (Argo CD) или 8250 (Vault) при этом должен быть проброшен на хост, где запущена команда.

Вход администратором Vault

Обычный вход идёт в точку монтирования oidc, где политика выдаётся по членству в подгруппе. Полные права на хранилище живут в отдельном mount'е oidc-admin и достаются только Owner'ам группы infra/k8s — почему так, описано в platform/vault-config/40-groups.yaml:

VAULT_OIDC_MOUNT=oidc-admin platform-mcp login vault

Настройка

Менять что-либо необязательно — адреса уже прописаны в плагине. Если нужно другое (свой инстанс, вход в Vault через oidc-admin, свои запреты), настройки можно переопределить переменными окружения в конфиге редактора либо положить в ~/.config/platform-mcp/config.json:

{
  "argocdUrl": "https://argocd.infra.sonar-corp.ru",
  "vaultUrl": "https://vault.infra.sonar-corp.ru",
  "vaultOidcMount": "oidc",
  "policy": {
    "requireConfirmation": true,
    "denyVaultPaths": ["kv/infra/"]
  }
}

Достаточно задать адрес хотя бы одного сервиса — второй просто не появится в списке инструментов.

Если сессии нет или она истекла, инструменты вернут понятную ошибку, а агент сможет вызвать argocd_login / vault_login прямо из диалога — перезапускать редактор не нужно. Эти инструменты открывают браузер и сразу возвращают ссылку, не дожидаясь завершения входа: человек ходит по SSO минуты, а таймаут запроса у MCP-клиентов обычно 60 секунд. Результат проверяется отдельным вызовом argocd_auth_status / vault_auth_status.

Команды

platform-mcp                    # MCP-сервер поверх stdio (так его запускает редактор)
platform-mcp login [сервис]     # интерактивный вход, --no-browser для headless
platform-mcp status [сервис]    # кто вошёл и до какого момента действует токен
platform-mcp logout [сервис]    # удалить сохранённую сессию

Сервис — argocd или vault; без него команда применяется ко всем настроенным.

Инструменты

На каждый сервис: <сервис>_exec, <сервис>_login, <сервис>_auth_status, <сервис>_logout.

argocd_exec и vault_exec принимают args — массив аргументов командной строки:

argocd_exec { "args": ["app", "list", "-o", "json"] }
argocd_exec { "args": ["app", "sync", "team-a-api"] }
vault_auth_status   # сначала: username, role, policies
vault_exec  { "args": ["token", "lookup"] }
vault_exec  { "args": ["kv", "list", "kv/teams"] }
vault_exec  { "args": ["kv", "get", "kv/teams/team-a/postgres"] }

Для Vault начинайте с vault_auth_status: по policies сразу видно, есть ли доступ к KV. ["token","lookup"] — канон CLI (не lookup-self). sys/mounts у обычных OIDC-пользователей часто 403 — не используйте для discovery. Exit code 2 у kv list обычно значит «пусто или нет list ACL», а не «нужно пробовать другой mount».

Аргументы всегда передаются массивом и никогда не склеиваются в строку: shell не участвует, поэтому ; и $(...) в аргументах остаются обычным текстом.

Адрес и токен подставляет сервер. Флаги, которые их переопределяют (--server, --auth-token, --config, --core у Argo CD; -address, -tls-skip-verify у Vault), запрещены — иначе рабочий токен из окружения дочернего процесса можно было бы отправить на чужой хост.

Подтверждение опасных операций

Читающие команды выполняются сразу. Всё остальное требует подтверждения пользователя.

Мутирующей считается любая команда, которая не опознана как читающая: список глаголов замкнут в безопасную сторону, поэтому незнакомая команда попадёт под подтверждение, а не проскочит мимо него.

Если клиент поддерживает MCP elicitation, появляется обычный диалог. Если нет — работает запасная схема: первый вызов возвращает описание последствий и одноразовый токен, второй вызов с этим токеном выполняет операцию. Токен живёт 5 минут и привязан к конкретным аргументам, поэтому «подтвердил одно, выполнил другое» не пройдёт, а придумать его самостоятельно агент не может.

Отдельно запрещены совсем:

  • вход и выход (argocd login, vault login) — сессией управляет сам сервер;
  • команды, которые не завершаются: vault server|agent|proxy|monitor, argocd app logs --follow;
  • argocd admin — управление самим Argo CD;
  • vault operator seal|step-down|init|rekey|generate-root|migrate — отказ любой из них кладёт хранилище целиком;
  • изменение инфраструктурных приложений Argo CD (argocd, vault, cert-manager, ingress-nginx, …): они едут из Git через merge request, а не из диалога с агентом. Читать их можно.

Списки настраиваются в config.json (policy.denyApplications, policy.denyVaultPaths).

Это защита от ошибок агента, а не граница безопасности. Участник группы infra/k8s и так администратор Argo CD (g, infra/k8s, role:admin) и может сделать то же самое через UI. Реально ограничить права можно только разделением ролей в argocd-rbac-cm и политиками Vault.

Секреты не попадают в контекст модели

Значения секретов вырезаются из ответов, а имена ключей и метаданные остаются:

  • Vault — значения из kv get, read по KV-пути и unwrap. Ответы kv list, kv metadata get, policy read, sys/mounts не трогаются: там нет секретов, и вырезание сделало бы их бесполезными.
  • Argo CD — data и stringData у ресурсов Secret, в том числе внутри полей manifest, liveState, targetState, где Argo CD отдаёт манифесты строками с JSON внутри. base64 — это не шифрование.

Обходные пути закрыты: vault kv get -field=password печатает голое значение мимо JSON, а -format=table не даёт из чего вырезать — оба отклоняются с объяснением.

Если значения действительно нужны в диалоге:

export PLATFORM_MCP_ALLOW_SECRET_VALUES=true

Осознанный опт-ин: после него содержимое секретов уезжает провайдеру модели. По умолчанию смотрите секреты в Vault напрямую.

Дополнительно: ответы длиннее 100 КБ обрезаются с подсказкой, чем сузить запрос, а вывод помечается как данные из кластера — манифесты, аннотации и логи пишут люди, и встреченные там указания агент выполнять не должен.

Откуда берутся argocd и vault

Сервер работает не через самописный REST-клиент, а через официальные CLI: у Argo CD Node-клиента нет вовсе, а у Vault официальный — это Go-библиотека и тот же бинарник. Полнота возможностей при этом равна полноте CLI.

Ставить их вручную не нужно:

  1. Если argocd/vault уже есть в PATH — используется он, ничего не скачивается.
  2. Иначе при первом обращении скачивается закреплённая версия с официальных релизов (github.com/argoproj/argo-cd, releases.hashicorp.com) под текущую платформу.
  3. Контрольная сумма сверяется до распаковки и до chmod +x. Без этого шага всё свелось бы к «скачать из интернета и выполнить».
  4. Файл кладётся в ~/.config/platform-mcp/bin/ и переиспользуется дальше.

Скачивание происходит при первом использовании, а не в postinstall: postinstall-скрипты повсеместно отключают (npm ci --ignore-scripts), и установка молча оставалась бы неполной.

Версии закреплены в src/config.ts и совпадают с развёрнутыми в кластере (Argo CD v3.4.5, Vault 2.0.3). При обновлении кластера их нужно поднять здесь же.

TLS

У argocd.infra.sonar-corp.ru и vault.infra.sonar-corp.ru сейчас нет настоящих сертификатов: в обоих Ingress секрет с сертификатом не указан, поэтому ingress-nginx отдаёт свой дефолтный самоподписанный (CN=Kubernetes Ingress Controller Fake Certificate, SAN ingress.local).

Пока это так, нужен явный опт-ин:

export PLATFORM_MCP_INSECURE=true

Он отключает проверку сертификата и печатает предупреждение при каждом запуске. Соединение остаётся шифрованным, но подлинность сервера не подтверждается, а по этому каналу ходят токены доступа.

NODE_EXTRA_CA_CERTS здесь не поможет: SAN сертификата (ingress.local) не совпадает с именем хоста, поэтому проверка имени провалится даже с доверенным корневым CA.

После выпуска нормальных сертификатов опцию нужно убрать. Если они подписаны внутренним CA, достаточно указать корневой — переменные наследуются дочерними CLI:

export NODE_EXTRA_CA_CERTS=/path/to/internal-ca.pem   # для самого сервера (Node)
export SSL_CERT_FILE=/path/to/internal-ca.pem         # для argocd и vault (Go)

Как это устроено

редактор ──stdio──▶ platform-mcp ──argv+env──▶ argocd ──▶ Argo CD
                    (OIDC, политика,  vault  ──▶ Vault
                     вырезание секретов)

Argo CD. Вход — Authorization Code + PKCE через Dex. Используется public-клиент argo-cd-cli, которого Argo CD регистрирует в Dex автоматически вместе с redirect URI http://localhost:8085/auth/callback, поэтому менять argocd-cm для установки не нужно. Argo CD принимает как Bearer именно id_token, а не access_token — последний у Dex непрозрачный и API-сервером не проверяется. Токен обновляется по refresh-токену.

CLI запускается с --grpc-web: ingress-nginx проксирует в argocd-server обычный HTTP/1.1 (configs.params.server.insecure: true), и чистый gRPC до него не доходит.

Vault. Поток проще: PKCE не нужен, потому что код на токен меняет сам Vault — секрет OAuth-приложения хранится в нём. От клиента требуется поднять listener на http://localhost:8250/oidc/callback (он заранее прописан в allowedRedirectURIs) и вернуть code, state и client_nonce. Параметр state генерирует сам Vault и кладёт внутрь выданной ссылки — оттуда он и берётся для проверки редиректа. Токен продлевается через auth/token/renew-self, пока renewable.

Токены передаются дочерним процессам только через окружение: в argv они были бы видны в ps любому процессу пользователя. Окружение не наследуется целиком — CLI получает ровно то, что ему нужно, без секретов соседних сервисов.

Сессии хранятся в собственных файлах, а не в ~/.config/argocd/config и ~/.vault-token: провайдер ротирует токен при обновлении, и общий файл приводил бы к тому, что обычные argocd/vault в терминале и этот сервер инвалидировали бы сессии друг другу.

Разработка

npm install
npm run build
npm test

Тесты покрывают классификацию команд и запреты, вырезание секретов, одноразовые токены подтверждения, отсутствие shell при запуске CLI и собственный распаковщик ZIP (он нужен потому, что HashiCorp отдаёт vault архивом, а встроенного распаковщика в Node нет).

Плагин

Репозиторий одновременно и каталог плагинов, и сам плагин:

.claude-plugin/marketplace.json      каталог для Claude Code
.cursor-plugin/marketplace.json      каталог для Cursor
plugins/platform-mcp/
  .claude-plugin/plugin.json         манифест для Claude Code
  .cursor-plugin/plugin.json         манифест для Cursor
  .mcp.json                          сервер для Claude Code — ПЛОСКАЯ карта
  mcp.json                           тот же сервер для Cursor — с обёрткой mcpServers

Описание сервера продублировано в двух формах, и это не небрежность. Claude Code читает .mcp.json как плоскую карту «имя → сервер»: с обёрткой mcpServers он молча не подхватывает сервер — плагин ставится и числится включённым, но инструментов не появляется. Cursor же берёт файл по пути из mcpServers в своём plugin.json, и рабочие плагины для него используют форму с обёрткой. Чтобы не гадать за оба клиента, каждому дан файл в его форме, а npm run check:manifests следит, чтобы содержимое не разъехалось.

Код сервера в плагин не копируется: оба файла запускают опубликованный пакет через npx, поэтому плагин остаётся несколькими небольшими файлами и не требует пересборки при изменениях сервера.

Проверить изменения до пуша можно, подключив каталог с локального пути:

/plugin marketplace add /путь/к/platform-mcp
/plugin install platform-mcp

Публикация

CI (.gitlab-ci.yml) публикует пакет в GitLab npm registry этого проекта автоматически по тегу вида vX.Y.Z, аутентификация — через встроенный CI_JOB_TOKEN, личных токенов в CI не требуется.

Версия продублирована в манифестах плагина, и её нужно поднимать там же:

npm version <major|minor|patch> --no-git-tag-version   # только package.json
# поправить version в обоих plugins/platform-mcp/*/plugin.json
npm run check:manifests                                # сверить
git commit -am "0.X.Y" && git tag v0.X.Y && git push --follow-tags

Расхождение поймает CI: задание test сверяет версии в трёх манифестах и согласованность двух описаний сервера, а publish — версию из тега с package.json. Без этого плагин у пользователя остался бы «неизменившимся» при свежем сервере: и Claude Code, и Cursor решают, обновлять ли плагин, по его version.

Отдельно выкладывать плагин никуда не нужно: пуш в main уезжает на GitHub зеркалом защищённых веток, и пользователи подхватывают изменения через /plugin marketplace update. Обратите внимание, что плагин ставится из ветки, а не из тега: как только правка попала в main, она уже доступна всем — даже если версия ещё не выпущена тегом.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选