platform-mcp
This server provides MCP tools for secure CLI management of Argo CD, Vault, and Keycloak, with SSO login and safety restrictions.
Argo CD:
argocd_execrunsargocdcommands (e.g., app list/sync/logs, proj list).argocd_logininitiates GitLab SSO;argocd_auth_statuschecks session;argocd_logoutclears it. Mutating ops require confirmation; infra apps are blocked.Vault:
vault_execrunsvaultcommands (e.g., kv list/get/put, policy read).vault_logininitiates GitLab SSO;vault_auth_statusshows role/policies;vault_logoutclears session. Secret values are redacted by default; writes require confirmation.Keycloak:
keycloak_exec,keycloak_login(FreeIPA SSO), status, and logout may be available, depending on the schema.
Security: arguments as arrays (no injection); dangerous/overriding commands blocked; server injects auth securely; secrets redacted; large outputs truncated; CLI binaries auto‑downloaded and verified; confirmation required for mutating ops.
Enables execution of Argo CD CLI commands against a configured Argo CD server, including listing and syncing applications, with authentication via GitLab SSO.
Enables execution of Vault CLI commands against a configured Vault server, including reading and managing secrets, with authentication via GitLab SSO.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@platform-mcpshow me the list of Argo CD applications"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
platform-mcp
MCP server for the infrastructure services of the sonar-prod cluster — Argo CD, Vault, and
Keycloak — with SSO login (GitLab for Argo/Vault, FreeIPA for Keycloak).
Why
The agent in the editor needs access to Argo CD, Vault, and Keycloak, but giving it a service account is not an option: the audit trail would show a shared account instead of a person, and the permissions would be broader than those of any individual developer.
This package is installed locally and performs a regular SSO login through the browser. It then executes commands on behalf of the logged-in user: the audit logs show the real login, and the permissions are exactly those granted by group membership.
There is exactly one tool per service — argocd_exec, vault_exec, and keycloak_exec,
which accept command-line arguments. Under the hood are the official CLIs (argocd,
vault, kcadm), so everything they can do is available. A new service is added with a
single interface implementation.
Related MCP server: mcp-read-only-argocd
Installation
Step 1. Access to the package registry
Needed once and for all methods below: the package lives in the npm registry of this GitLab project,
not in public npm. Get a token with the read_package_registry permission (a personal access token
or a project deploy token) and add it to ~/.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 токен>Step 2. Connecting to the editor
Claude Code and Cursor — via the plugin. The repository is itself a plugin catalog, so two commands are enough:
/plugin marketplace add https://github.com/K-manankov/platform-mcp.git
/plugin install platform-mcpThe address is GitHub, not GitLab, and that is not a typo — see Why the plugin catalog is on GitHub.
The Argo CD, Vault, and Keycloak addresses are already set in the plugin — nothing to configure.
Updates arrive on their own: the plugin starts the server via npx -y, meaning it always uses the
latest published version. To update the plugin itself — /plugin marketplace update.
Claude Desktop does not install plugins of this format, so there the entry is made manually. Install the package globally:
npm install -g @sonar/platform-mcpand add it to claude_desktop_config.json (Settings → Developer → Edit Config). The path to
node and to the server must be absolute: GUI applications on macOS do not inherit PATH
from the shell. Check your paths with which node and 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",
"KEYCLOAK_BASE_URL": "https://auth.infra.sonar-corp.ru",
"PLATFORM_MCP_INSECURE": "true"
}
}
}
}Argo CD, Vault, and Keycloak do not need to be installed separately in any of the options: the server
itself downloads the required CLI versions on first use (see
Where the CLIs come from). For kcadm, the machine must have
Java 17+.
Why the plugin catalog is on GitHub
Claude Desktop only connects plugin catalogs from GitHub. In addition, our GitLab lives
on the internal network and is not reachable from outside at all, so it would not even reach git.sonar-corp.ru.
That is why the source code stays in GitLab, while
github.com/K-manankov/platform-mcp has a
mirror of protected branches configured. Only one branch is protected — main, and that is exactly what goes to GitHub on
every push. There is no reverse sync: changes are made only in GitLab; the GitHub copy
exists for plugin installation purposes.
The mirror itself does not expose anything extra — it contains the same public npm package and the addresses
of internal services, which still only resolve from inside the network. There are no secrets in the repository
and there should not be: the server keeps access tokens in ~/.config/platform-mcp/, and the package registry
token is set up by each person themselves in ~/.npmrc.
To update the installed plugin after changes:
/plugin marketplace update sonar-infra
/plugin update platform-mcpLogin
VPN is required: the names argocd.infra.sonar-corp.ru, vault.infra.sonar-corp.ru, and
auth.infra.sonar-corp.ru only resolve from inside the network. From outside, the public
wildcard *.infra.sonar-corp.ru catches them, and the request silently goes somewhere else — the check
dig +short argocd.infra.sonar-corp.ru should return 192.168.88.106.
The easiest way is to log in right from the dialog: ask the agent to call argocd_login,
vault_login, or keycloak_login, open the link it gives you, and complete the login.
No need to restart the editor.
The same from the terminal, if the package is installed globally:
export ARGOCD_BASE_URL=https://argocd.infra.sonar-corp.ru
export VAULT_ADDR=https://vault.infra.sonar-corp.ru
export KEYCLOAK_BASE_URL=https://auth.infra.sonar-corp.ru
export PLATFORM_MCP_INSECURE=true # пока нет настоящих сертификатов, см. TLS
platform-mcp login # во все настроенные сервисы подряд
platform-mcp login keycloak # только в одинA browser will open: for Argo CD and Vault — GitLab SSO, for Keycloak — FreeIPA in the realm
master (client platform-mcp-cli, see bootstrap in infra). Sessions are stored in
~/.config/platform-mcp/ with 0600 permissions and are shared across all editors: log in once,
and you are logged in everywhere.
Over SSH or in a devcontainer where there is no browser:
platform-mcp login --no-browserThe link from the output must be opened on your own machine; the port 8085 (Argo CD), 8250 (Vault),
or 8280 (Keycloak) must be forwarded to the host where the command is running.
Logging in as a Vault administrator
A regular login goes to the oidc mount point, where the policy is granted based on membership in a
subgroup. Full storage permissions live in a separate oidc-admin mount and are only available
to Owners of the infra/k8s group — why that is is described in
platform/vault-config/40-groups.yaml:
VAULT_OIDC_MOUNT=oidc-admin platform-mcp login vaultConfiguration
Changing anything is optional — the addresses are already set in the plugin.
Cursor. Plugins → Configure for platform-mcp: Argo CD, Vault, and Keycloak URLs,
PLATFORM_MCP_INSECURE, and the Vault OIDC mount (oidc — regular login, oidc-admin — full
permissions for Owners of infra/k8s). The defaults match the sonar-prod cluster.
Claude Code and manual config. If you need something different (your own instance, oidc-admin, your own
restrictions), override with environment variables in the editor config or put them in
~/.config/platform-mcp/config.json:
{
"argocdUrl": "https://argocd.infra.sonar-corp.ru",
"vaultUrl": "https://vault.infra.sonar-corp.ru",
"keycloakUrl": "https://auth.infra.sonar-corp.ru",
"vaultOidcMount": "oidc",
"policy": {
"requireConfirmation": true,
"denyVaultPaths": ["kv/infra/"]
}
}It is enough to set the address of at least one service — the rest simply will not appear in the list of tools.
If there is no session or it has expired, the tools return a clear error, and the agent can call
argocd_login / vault_login / keycloak_login right from the dialog — no need to restart the editor.
These tools open a browser and immediately return the link, without waiting for the
login to complete: a person takes minutes going through SSO, while the request timeout for MCP clients is usually
60 seconds. The result is checked with a separate *_auth_status call.
Commands
platform-mcp # MCP-сервер поверх stdio (так его запускает редактор)
platform-mcp login [сервис] # интерактивный вход, --no-browser для headless
platform-mcp status [сервис] # кто вошёл и до какого момента действует токен
platform-mcp logout [сервис] # удалить сохранённую сессиюThe service is argocd, vault, or keycloak; without it, the command applies to all configured services.
Tools
For each service: <service>_exec, <service>_login, <service>_auth_status,
<service>_logout.
argocd_exec, vault_exec, and keycloak_exec accept args — an array of command-line
arguments:
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"] }
keycloak_exec { "args": ["get", "realms"] }
keycloak_exec { "args": ["get", "users", "-r", "sonar-prod", "-q", "username=alice"] }For Vault, start with vault_auth_status: the policies immediately show whether KV access is available.
["token","lookup"] is the CLI canonical form (not lookup-self). sys/mounts is often 403 for regular
OIDC users — do not use it for discovery. Exit code 2 from kv list usually means "empty or no list
ACL", not "try a different mount".
Arguments are always passed as an array and never joined into a string: the shell is not
involved, so ; and $(...) in arguments remain plain text.
The address and token are substituted by the server. Flags that override them (--server,
--auth-token, --config, --core for Argo CD; -address, -tls-skip-verify for Vault;
--server, --config, --no-config for Keycloak) are forbidden — otherwise the working token from the
child process environment could be sent to a foreign host.
Confirmation of dangerous operations
Read-only commands execute immediately. For Argo CD and Vault, everything else requires user confirmation.
Any command that is not recognized as read-only is considered mutating: the list of verbs is closed on the safe side, so an unfamiliar command will fall under confirmation rather than slip past it.
If the client supports MCP elicitation, a regular dialog appears. If not, a fallback scheme works: the first call returns a description of the consequences and a one-time token; the second call with that token performs the operation. The token lives for 5 minutes and is tied to the specific arguments, so "confirmed one thing, executed another" will not pass, and the agent cannot invent it on its own.
Keycloak is an exception: mutations execute immediately, but a warning is added to the response
to the agent — the config goes through CR/operator, and manual edits via kcadm may be overwritten
by the operator during sync. Manifests in Git are preferred.
The following are completely forbidden:
login and logout (
argocd login,vault login,kcadm config …) — the session is managed by the server itself;commands that never finish:
vault server|agent|proxy|monitor,argocd app logs --follow;argocd admin— managing Argo CD itself;vault operator seal|step-down|init|rekey|generate-root|migrate— failure of any of them takes down the entire storage;modifying Argo CD infrastructure applications (
argocd,vault,keycloak,cert-manager,ingress-nginx, …): they are managed from Git via merge requests, not from a dialog with the agent. Reading them is allowed.
The lists are configurable in config.json (policy.denyApplications, policy.denyVaultPaths).
This is protection against agent mistakes, not a security boundary. A member of the
infra/k8sgroup is already an Argo CD administrator (g, infra/k8s, role:admin) and can do the same through the UI. Real permission limits can only be achieved by separating roles inargocd-rbac-cmand Vault policies.
Secrets do not enter the model context
Secret values are stripped from responses, while key names and metadata remain:
Vault — values from
kv get,readon a KV path, andunwrap. Responses fromkv list,kv metadata get,policy read,sys/mountsare not touched: they contain no secrets, and stripping would make them useless.Argo CD —
dataandstringDataofSecretresources, including inside themanifest,liveState,targetStatefields, where Argo CD returns manifests as strings with JSON inside.base64is not encryption.
Workarounds are closed: vault kv get -field=password prints the bare value bypassing JSON, and
-format=table gives nothing to strip from — both are rejected with an explanation.
If the values are genuinely needed in the dialog:
export PLATFORM_MCP_ALLOW_SECRET_VALUES=trueA deliberate opt-in: after it, secret contents go to the model provider. By default, view secrets directly in Vault.
Additionally: responses longer than 100 KB are truncated with a hint on how to narrow the request, and the output is marked as data from the cluster — manifests, annotations, and logs are written by people, and the agent must not follow instructions encountered there.
Where argocd, vault, and kcadm come from
The server does not work through a hand-written REST client but through the official CLIs: Argo CD
has no Node client at all, Vault's official one is a Go library and the same binary, and the
Keycloak Admin API uses kcadm from the distribution. Feature completeness is therefore equal to that of the CLI.
You do not need to install them manually:
If
argocd/vault/kcadm(kcadm.sh) is already inPATH— that one is used, nothing is downloaded.Otherwise, on first use, a pinned version is downloaded from the official releases (
github.com/argoproj/argo-cd,releases.hashicorp.com,github.com/keycloak/keycloak) for the current platform. For Keycloak — the entire zip distribution (~170 MB):kcadmis a Java script, not a standalone Go binary.The checksum is verified before unpacking and before
chmod +x. Without this step, everything would boil down to "download from the internet and execute".The file is placed in
~/.config/platform-mcp/bin/and reused from then on.
For kcadm, the machine needs Java 17+ (java in PATH or JAVA_HOME). Without it,
the server returns a clear error.
The download happens on first use, not in postinstall: postinstall scripts are
widely disabled (npm ci --ignore-scripts), and the installation would silently remain incomplete.
The versions are pinned in src/config.ts and match those deployed in the cluster
(Argo CD v3.4.5, Vault 2.0.3, Keycloak 26.6.4). When the cluster is updated, they need to be
bumped here as well.
TLS
argocd.infra.sonar-corp.ru, vault.infra.sonar-corp.ru, and auth.infra.sonar-corp.ru
currently have no real certificates: the Ingress has no certificate secret specified, so
ingress-nginx serves its default self-signed one (CN=Kubernetes Ingress Controller Fake Certificate,
SAN ingress.local).
Until that changes, an explicit opt-in is required:
export PLATFORM_MCP_INSECURE=trueIt disables certificate validation for Node (OIDC login) and prints a warning on every run. The connection remains encrypted, but the server's authenticity is not confirmed, and access tokens travel over this channel. kcadm has skip certificate validation enabled when there's no truststore in the config (warning in CLI stderr).
NODE_EXTRA_CA_CERTS won't help here: the certificate's SAN (ingress.local) doesn't match the hostname, so name validation will fail even with a trusted root CA.
After proper certificates are issued, the option needs to be removed. If they're signed by an internal CA, pointing to the root one is enough — variables are inherited by child CLIs:
export NODE_EXTRA_CA_CERTS=/path/to/internal-ca.pem # для самого сервера (Node)
export SSL_CERT_FILE=/path/to/internal-ca.pem # для argocd и vault (Go)How it works
редактор ──stdio──▶ platform-mcp ──argv+env──▶ argocd ──▶ Argo CD
(OIDC, политика, vault ──▶ Vault
вырезание секретов) kcadm ──▶ KeycloakArgo CD. Login is Authorization Code + PKCE via Dex. The public client argo-cd-cli is used, which Argo CD registers in Dex automatically along with the redirect URI http://localhost:8085/auth/callback, so there's no need to change argocd-cm for setup. Argo CD accepts id_token as Bearer, not access_token — the latter is opaque in Dex and isn't validated by the API server. The token is refreshed via a refresh token.
The CLI is launched with --grpc-web: ingress-nginx proxies plain HTTP/1.1 to argocd-server (configs.params.server.insecure: true), and raw gRPC doesn't reach it.
Vault. The flow is simpler: PKCE isn't needed because Vault itself exchanges the code for a token — the OAuth app secret is stored in it. The client only needs to raise a listener on http://localhost:8250/oidc/callback (it's pre-registered in allowedRedirectURIs) and return code, state, and client_nonce. The state parameter is generated by Vault itself and placed inside the issued link — that's where it's taken from to validate the redirect. The token is renewed via auth/token/renew-self while it's renewable.
Keycloak. Authorization Code + PKCE via the public client platform-mcp-cli in the master realm (set up once in bootstrap, redirect http://localhost:8280/oidc/callback). Login is via FreeIPA. The access_token (Admin API) is placed in the session. Before kcadm, the server writes a private kcadm.config to ~/.config/platform-mcp/ — not the shared ~/.keycloak/kcadm.config.
Tokens are passed to child processes only via the environment (Argo/Vault) or via a private config file (Keycloak): in argv they'd be visible in ps to any process of the user. The environment isn't inherited entirely — the CLI gets exactly what it needs, without secrets of neighboring services.
Sessions are stored in their own files, not in ~/.config/argocd/config, ~/.vault-token, and ~/.keycloak/kcadm.config: the provider rotates the token on refresh, and a shared file would cause the regular CLIs in the terminal and this server to invalidate each other's sessions.
Development
npm install
npm run build
npm testTests cover command classification and prohibitions, secret redaction, one-time confirmation tokens, the absence of a shell when launching the CLI, and a custom ZIP unpacker (needed because HashiCorp delivers vault as an archive, and Node has no built-in unpacker).
Plugin
The repository is both a plugin catalog and the plugin itself:
.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 — с обёрткой mcpServersThe server description is duplicated in two forms, and that's not carelessness. Claude Code reads .mcp.json as a flat "name → server" map: with the mcpServers wrapper it silently doesn't pick up the server — the plugin installs and shows as enabled, but no tools appear. Cursor, on the other hand, takes the file by path from mcpServers in its plugin.json, and working plugins for it use the wrapped form. command/args and env keys match; Cursor's env values are ${VAR} placeholders (the variables schema in plugin.json, Configure in the UI), Claude's are literal defaults. npm run check:manifests keeps the forms from diverging.
The server code isn't copied into the plugin: both files launch the published package via npx, so the plugin stays a few small files and doesn't require a rebuild when the server changes.
You can verify changes before pushing by connecting the directory from a local path:
/plugin marketplace add /путь/к/platform-mcp
/plugin install platform-mcpPublishing
CI (.gitlab-ci.yml) publishes the package to this project's GitLab npm registry automatically on a tag like vX.Y.Z; authentication is via the built-in CI_JOB_TOKEN, no personal tokens are needed in CI.
The version is duplicated in the plugin manifests and needs to be bumped there too:
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-tagsCI will catch a mismatch: the test job checks versions in the three manifests and the consistency of the two server descriptions, and publish checks the tag version against package.json. Without this, the plugin would remain "unchanged" for the user with a fresh server: both Claude Code and Cursor decide whether to update the plugin by its version.
There's no separate place to publish the plugin: a push to main goes to GitHub via a protected-branch mirror, and users pick up changes via /plugin marketplace update. Note that the plugin is installed from a branch, not a tag: as soon as a change lands in main, it's already available to everyone — even if the version hasn't been released with a tag yet.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP (Model Context Protocol) server that integrates with the ArgoCD API, enabling AI assistants and large language models to manage ArgoCD applications and resources through natural language interactions.1012MIT
- AlicenseAqualityBmaintenanceA secure MCP server providing read-only access to Argo CD instances using browser session cookies, enabling querying of applications, projects, clusters, and repositories.14MIT
- AlicenseNot gradedqualityFmaintenanceA Model Context Protocol (MCP) server that enables secure execution of shell commands with a dynamic approval system, audit logging, and command revocation.41Apache 2.0
- AlicenseNot gradedqualityAmaintenanceMCP server for interacting with GitLab API, supporting dynamic tool selection and enterprise-grade security.10MIT
Related MCP Connectors
Go MCP server for GitLab: 2 dynamic tools reach 1000+ REST/GraphQL actions. Free/CE, no paid tier.
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/K-manankov/platform-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server