ArgoCD

argocd-mcp

The entire ArgoCD API, exposed to LLMs via MCP.
103+ endpoints. Zero hardcoded handlers. Two modes: search or generated tools.

Quick StartHow It WorksOAuthConfiguration


Most ArgoCD MCP servers hardcode a few operations: list apps, sync, get status. When ArgoCD adds a new feature, you wait for the maintainer to add it.

argocd-mcp takes a different approach, inspired by Cloudflare's MCP server which covers 2500+ endpoints with only 2 tools. It reads ArgoCD's OpenAPI spec at startup and exposes every endpoint through just 2 tools: search and execute. New ArgoCD version? Restart the server. Done.

  • 103+ endpoints from ArgoCD's OpenAPI spec, zero hardcoded handlers
  • Two tool modes: search (2 meta-tools) or generated (1 typed tool per endpoint)
  • Works with Claude Desktop, Claude Code, Cursor, or any MCP client
  • No code per endpoint — the OpenAPI spec is the source of truth
  • Two auth modes: static token or OAuth via ArgoCD Dex (per-user RBAC)
  • Read-only mode — disable all write operations with a single flag
  • Resource scoping — restrict which ArgoCD resources are exposed with ALLOWED_RESOURCES
  • Rate limiting — per-user token bucket to protect ArgoCD from excessive calls
  • Prompt templates — pre-packaged workflows for common operations (unhealthy apps, diff, rollback, logs)
  • Audit logging — structured JSON logs for every tool call (user, method, path, status, duration)
  • MCP annotations — tools are annotated as read-only, destructive, or idempotent for proper client categorization
  • Optional semantic search via Ollama embeddings

How It Works

At startup, the server fetches ArgoCD's Swagger spec and parses every endpoint. Then it exposes them to LLMs via one of two modes:

Search mode (default, TOOL_MODE=search)

Two meta-tools handle all 103+ endpoints. The LLM discovers endpoints by searching, then calls them via a generic executor.

graph TD
    A[ArgoCD /swagger.json] -->|Fetch at startup| B[Parse Swagger 2.0]
    B --> C[103+ Endpoints in memory]
    C --> D[search_operations]
    C --> E[execute_operation]
    D -->|LLM discovers endpoints| F[Returns method, path, summary, params]
    E -->|LLM calls API| G[Proxies to ArgoCD with user token]

Generated mode (TOOL_MODE=generated)

One typed MCP tool per endpoint, generated dynamically at startup. The LLM calls argocd_application_sync(name, revision) directly — no search step, no path construction.

graph TD
    A[ArgoCD /swagger.json] -->|Fetch at startup| B[Parse Swagger 2.0]
    B --> C[103+ Endpoints]
    C -->|Generate per endpoint| D[argocd_application_list]
    C --> E[argocd_application_sync]
    C --> F[argocd_cluster_get]
    C --> G[... 100+ more tools]
    D & E & F & G -->|Typed params, 1 call| H[Proxies to ArgoCD]

Which mode to choose?

SearchGenerated
Tools registered2103+
LLM round-trips2 (search → execute)1 (direct call)
Parameter typingRaw JSON stringsTyped individual params
Context usageLow (~200 tokens)Higher (mitigated by client deferred loading)
Best forLightweight clients, constrained contextClaude Code, Claude Desktop, Cursor

Clients like Claude Code and Claude Desktop support deferred tool loading — they only load tool definitions into context when needed, so the 103+ tools don't consume context window upfront.


Quick Start

Helm Chart (Kubernetes)

helm install argocd-mcp oci://ghcr.io/matthisholleville/charts/argocd-mcp \
  --set argocd.baseURL=https://argocd.example.com \
  --set argocd.token=your-token

See all configuration options in charts/argocd-mcp/values.yaml.

Static Token (simple)

Best for local dev, CI/CD, or single-user setups. Uses a static ArgoCD API token.

Claude Code

claude mcp add argocd -s user -- \
  docker run --rm -i \
  -e ARGOCD_BASE_URL=https://argocd.example.com \
  -e ARGOCD_TOKEN=your-token \
  ghcr.io/matthisholleville/argocd-mcp:latest

Claude Desktop

Add to your Claude Desktop MCP config (claude_desktop_config.json):

{
  "mcpServers": {
    "argocd": {
      "command": "docker",
      "args": ["run", "--rm", "-i",
        "-e", "ARGOCD_BASE_URL=https://argocd.example.com",
        "-e", "ARGOCD_TOKEN=your-token",
        "ghcr.io/matthisholleville/argocd-mcp:latest"
      ]
    }
  }
}

OAuth via ArgoCD Dex (per-user RBAC)

Best for multi-user, production setups. Each user authenticates with their own identity via ArgoCD's built-in Dex. No static token needed — the user's Dex id_token is forwarded to ArgoCD, which applies its RBAC policies per user.

Step 1: Start the server

docker run -p 8080:8080 \
  -e ARGOCD_BASE_URL=https://argocd.example.com \
  -e MCP_TRANSPORT=http \
  -e AUTH_MODE=oauth \
  -e DEX_CLIENT_ID=argo-cd-cli \
  -e SERVER_BASE_URL=http://localhost:8080 \
  ghcr.io/matthisholleville/argocd-mcp:latest

Step 2: Connect your MCP client

Claude Code

claude mcp add --transport http --callback-port 9382 argocd http://localhost:8080/mcp

Then run /mcp inside Claude Code to authenticate via the browser.

Claude Desktop

Claude Desktop requires a publicly accessible URL (the OAuth redirect goes through claude.ai). Expose the server via a reverse proxy or ngrok, then set SERVER_BASE_URL accordingly.

Add the public URL as a remote MCP server in Settings > Connectors (e.g. https://mcp.example.com/mcp). Claude Desktop handles the OAuth flow automatically.

Required: ArgoCD Dex configuration

The argo-cd-cli Dex client needs the callback URLs for your MCP clients registered as redirect URIs. Add a staticClients override in your ArgoCD dex.config:

staticClients:
  - id: argo-cd-cli
    name: Argo CD CLI
    public: true
    redirectURIs:
      - http://localhost
      - http://localhost:8085/auth/callback
      - http://localhost:9382/callback
      - https://claude.ai/api/mcp/auth_callback
Redirect URIUsed by
http://localhostArgoCD CLI (argocd login --sso)
http://localhost:8085/auth/callbackArgoCD CLI (legacy)
http://localhost:9382/callbackClaude Code (--callback-port 9382)
https://claude.ai/api/mcp/auth_callbackClaude Desktop

ArgoCD auto-registers argo-cd-cli at startup and prepends it to the client list. Dex uses the last definition when there are duplicate IDs, so our override wins safely (ref).

Note: The argo-cd-cli client is public (no secret), so this override is safe — unlike overriding argo-cd which has an internal secret (ref).

How it works under the hood:

  • The MCP server acts as an OAuth proxy to ArgoCD's Dex
  • Uses the argo-cd-cli public client (no secret needed)
  • The Dex id_token (with aud: argo-cd-cli) is swapped into the access_token field and forwarded as Bearer to ArgoCD
  • ArgoCD validates the token against Dex's JWKS and applies per-user RBAC
  • Each user only sees the applications and resources they have access to

Semantic Search (optional)

Enable Ollama-powered vector search for better results on natural language queries:

docker compose up --build -d  # Starts Ollama + argocd-mcp with embeddings

Set EMBEDDINGS_ENABLED=true, OLLAMA_URL, and EMBEDDINGS_MODEL (defaults to nomic-embed-text).


Read-Only Mode (optional)

Set DISABLE_WRITE=true to prevent any disruptive action on your cluster. When enabled:

  • Write endpoints are hiddenPOST, PUT, PATCH, DELETE operations are filtered out from the search index, so the LLM never discovers them.
  • Write execution is blocked — even if a caller manually crafts an execute_operation request with a write method, it is rejected.
  • Read operations work normallyGET, HEAD, OPTIONS are unaffected.

This is ideal for production environments, demos, or any setup where you want LLMs to observe but never modify your ArgoCD resources.

# Claude Code
claude mcp add argocd -s user -- \
  docker run --rm -i \
  -e ARGOCD_BASE_URL=https://argocd.example.com \
  -e ARGOCD_TOKEN=your-token \
  -e DISABLE_WRITE=true \
  ghcr.io/matthisholleville/argocd-mcp:latest

Resource Scoping (optional)

Set ALLOWED_RESOURCES to restrict which ArgoCD resource types the LLM can discover and call. This filters both search results and blocks execution of out-of-scope endpoints.

# Only expose application and version endpoints
ALLOWED_RESOURCES=ApplicationService,VersionService

Composes with DISABLE_WRITE:

# Read-only access to applications only
DISABLE_WRITE=true
ALLOWED_RESOURCES=ApplicationService

Available resource tags (from ArgoCD's OpenAPI spec):

TagEndpoints
AccountService6
ApplicationService31
ApplicationSetService6
CertificateService3
ClusterService7
GPGKeyService4
NotificationService3
ProjectService12
RepoCredsService8
RepositoryService17
SessionService3
SettingsService2
VersionService1

Matching is case-insensitive (applicationservice works).


Generated Tools Mode (optional)

Set TOOL_MODE=generated to create one MCP tool per ArgoCD endpoint at startup. Instead of searching then executing, the LLM calls typed tools directly:

# Claude Code
claude mcp add argocd -s user -- \
  docker run --rm -i \
  -e ARGOCD_BASE_URL=https://argocd.example.com \
  -e ARGOCD_TOKEN=your-token \
  -e TOOL_MODE=generated \
  ghcr.io/matthisholleville/argocd-mcp:latest
How generated tools work

Each endpoint's operationId is converted to a snake_case tool name with argocd_ prefix:

operationIdTool name
ApplicationService_Syncargocd_application_sync
ClusterService_Getargocd_cluster_get
ApplicationSetService_Listargocd_application_set_list

Parameters are typed individually — no raw JSON needed for common cases:

argocd_application_sync(
  name:      "frontend"      ← path param (required)
  revision:  "HEAD"          ← body param, flattened
  dryRun:    true            ← body param, flattened
  strategy:  '{"apply":{}}'  ← nested object stays JSON string
)

Tools are annotated with MCP hints (readOnlyHint, destructiveHint, idempotentHint) so clients like Claude Desktop categorize them correctly (read vs write/delete).

DISABLE_WRITE and ALLOWED_RESOURCES are enforced at startup — forbidden tools are simply not generated. The LLM cannot even see them.


Rate Limiting (optional)

Protect ArgoCD from excessive API calls by setting RATE_LIMIT. Only execute_operation is rate limited — search is local and not affected.

RATE_LIMIT=10              # 10 requests/sec per user
RATE_LIMIT_BURST=20        # allow short bursts up to 20
How rate limiting works

Rate limiting uses a token bucket per user. Each user gets a bucket that refills at RATE_LIMIT tokens per second, with a maximum of RATE_LIMIT_BURST tokens. When the bucket is empty, requests are rejected until tokens refill.

Auth modeBucket keyBehavior
OAuthUser email from JWTEach user has an independent limit
Static tokenShared "static-token" keyAll clients share one bucket

Note: In static token mode, an aggressive LLM can starve other clients. Prefer OAuth mode in multi-user production setups.

When a request is rate limited:

  • The call never reaches ArgoCD — rejected before the proxy
  • An audit log entry is emitted with blocked: true
  • The LLM receives a clear error: "rate limit exceeded: too many requests, please slow down"

If RATE_LIMIT_BURST is not set, it defaults to the RATE_LIMIT value. Set RATE_LIMIT=0 (or omit it) to disable rate limiting entirely.


Prompt Templates

Pre-packaged workflows for common ArgoCD operations. MCP clients (Claude Desktop, Cursor) show these as selectable prompts in their UI.

PromptDescriptionArguments
unhealthy-appsFind all apps with degraded health or out-of-sync status
sync-statusDashboard-style overview of all apps
app-diffShow what would change on syncappName (required)
rollbackShow history and rollback to a previous revisionappName (required)
app-logsFetch and analyze container logsappName (required), container (optional)

Each prompt guides the LLM through a step-by-step workflow using search_operations and execute_operation. No additional tools are needed.


Audit Logging

Audit logging is enabled by default. Every search_operations and execute_operation call emits a structured JSON log entry to stderr:

{"time":"2026-03-22T10:00:00Z","level":"INFO","msg":"audit","tool":"execute_operation","method":"GET","path":"/api/v1/applications","blocked":false,"duration_ms":142,"status_code":200,"user":"[email protected]"}

Each entry includes:

  • toolsearch_operations or execute_operation
  • user — email from the OAuth token (empty in static token mode)
  • method / path — the ArgoCD API call (execute) or query (search)
  • status_code — upstream HTTP response code
  • blockedtrue if the call was rejected by DISABLE_WRITE or ALLOWED_RESOURCES
  • duration_ms — round-trip time in milliseconds
  • error — error message (logged at ERROR level when present)

Set AUDIT_LOG=false to disable.


Configuration

VariableRequiredDefaultDescription
ARGOCD_BASE_URLYesArgoCD server URL
ARGOCD_TOKENWhen AUTH_MODE=tokenArgoCD API token
AUTH_MODENotokentoken (static) or oauth (Dex SSO)
DEX_CLIENT_IDWhen AUTH_MODE=oauthargo-cd-cliDex client ID
SERVER_BASE_URLWhen AUTH_MODE=oauthhttp://localhost:8080Public URL of this server
ARGOCD_SPEC_URLNo{base}/swagger.jsonOverride spec URL
MCP_TRANSPORTNostdiostdio or http
MCP_ADDRNo:8080HTTP listen address
ARGOCD_TLS_INSECURENofalseSkip TLS certificate verification (set true for self-signed certs)
TOOL_MODENosearchsearch (2 meta-tools) or generated (1 tool per endpoint)
DISABLE_WRITENofalseBlock all write operations (POST, PUT, PATCH, DELETE)
ALLOWED_RESOURCESNoComma-separated list of resource tags to expose (e.g. ApplicationService,VersionService)
RATE_LIMITNo0 (disabled)Max execute_operation requests per second per user
RATE_LIMIT_BURSTNosame as RATE_LIMITMax burst size before throttling
AUDIT_LOGNotrueStructured JSON audit log for every tool call
EMBEDDINGS_ENABLEDNofalseEnable Ollama vector search
OLLAMA_URLNohttp://localhost:11434/apiOllama API URL
EMBEDDINGS_MODELNonomic-embed-textOllama embedding model

Build from source

make build
ARGOCD_BASE_URL=https://argocd.example.com ARGOCD_TOKEN=xxx ./bin/argocd-mcp

License

MIT

We install and manage your MCP server

Our team configures, deploys and maintains MCP servers tailored to your infrastructure.

  • Professional installation & configuration
  • Integration with your existing systems
  • Ongoing technical support & maintenance
  • Custom security & auditing

Response within 24h · No commitment

Quick MCP enquiry

Related in Cloud Service - Secure MCP Servers