TemplatetypescriptExpressintermediateโœ“ Production ReadyFreeโœ… Code Verified

Production Argo CD MCP Server Template (TypeScript)

A production-ready TypeScript MCP server template for integrating AI agents with Argo CD GitOps workflows. Uses Express with Streamable HTTP transport, API key authentication for the MCP endpoint, and Argo CD API token auth for upstream calls. Includes Zod validation, Pino structured logging, rate limiting, health monitoring, Docker, GitHub Actions CI, and a focused set of read-first Argo CD tools.

๐Ÿ“– 18 min readโš™๏ธ Setup: 25 minutesutilities
argocdargo-cdmcpmcp-servermodel-context-protocoltypescriptexpresskubernetesgitopsdevops

Files(23)

{
  "name": "argo-cd-mcp-server",
  "version": "1.0.0",
  "description": "Production Argo CD MCP Server โ€” TypeScript, Express, Streamable HTTP",
  "main": "dist/server.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "dev": "ts-node-dev --respawn --transpile-only src/server.ts",
    "lint": "eslint 'src/**/*.ts'",
    "typecheck": "tsc --noEmit",
    "test": "jest --runInBand --forceExit",
    "test:coverage": "jest --runInBand --forceExit --coverage"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "1.10.2",
    "axios": "1.7.9",
    "express": "4.19.2",
    "express-rate-limit": "7.4.1",
    "pino": "9.5.0",
    "pino-http": "10.3.0",
    "uuid": "10.0.0",
    "zod": "^3.23.8",
    "zod-to-json-schema": "3.23.5"
  },
  "devDependencies": {
    "@eslint/eslintrc": "3.1.0",
    "@types/express": "4.17.21",
    "@types/jest": "29.5.13",
    "@types/node": "22.9.1",
    "@types/supertest": "6.0.2",
    "@types/uuid": "10.0.0",
    "@typescript-eslint/eslint-plugin": "8.15.0",
    "@typescript-eslint/parser": "8.15.0",
    "eslint": "9.15.0",
    "jest": "29.7.0",
    "pino-pretty": "13.0.0",
    "supertest": "7.0.0",
    "ts-jest": "29.2.5",
    "ts-node-dev": "2.0.0",
    "typescript": "5.7.2"
  },
  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "node",
    "testMatch": [
      "**/__tests__/**/*.test.ts"
    ],
    "moduleNameMapper": {
      "^@/(.*)$": "<rootDir>/src/$1"
    },
    "collectCoverageFrom": [
      "src/**/*.ts",
      "!src/__tests__/**"
    ]
  },
  "engines": {
    "node": ">=20.0.0"
  },
  "license": "MIT"
}

Interactive tester

Test Your Server

Enter a deployed HTTP MCP server URL and API key to run live browser checks.

No signup

Use the public MCP endpoint, not a dashboard URL or local stdio command.

The key stays in this browser check and is sent to the endpoint you enter.

For local servers, use the local testing guide or MCP Inspector. This online tester works best with deployed HTTP MCP servers.

Production Argo CD MCP Server Template (TypeScript)

Overview

This template gives you a production-ready Model Context Protocol (MCP) server that bridges AI agents โ€” such as Claude Desktop, Cursor, or Windsurf โ€” with your Argo CD GitOps platform. Instead of copy-pasting kubectl commands or clicking through the Argo CD UI, your AI agent can query application health, sync status, Kubernetes resources, and events directly through natural language. The server wraps the official Argo CD REST API and exposes a curated set of safe, read-first tools that make day-to-day GitOps workflows faster.

The template is intentionally conservative. Read operations are enabled by default. The one write operation included โ€” sync_application โ€” ships with explicit validation, a dry-run guard, and prominent warnings, because pushing a sync in production is a real-world consequence. Destructive operations such as delete_application are deliberately omitted. This posture makes the server suitable for team environments where not every AI assistant session should carry full Argo CD admin rights.

Who is this for? Platform engineers, SRE teams, and developers who manage Kubernetes workloads with Argo CD and want to give their AI coding assistants real, live context about deployment state โ€” without standing up a heavy integration or risking accidental changes to production clusters.

What You'll Learn

  • How to scaffold a TypeScript MCP server using the official @modelcontextprotocol/sdk package with Streamable HTTP transport
  • How to protect an MCP endpoint with API key authentication middleware in Express
  • How to call an authenticated upstream REST API (Argo CD) from MCP tool handlers with proper token hygiene
  • How to define and validate MCP tool input schemas using Zod and convert them to JSON Schema for the SDK
  • How to implement structured JSON logging with Pino, including request correlation IDs and configurable log levels
  • How to apply express-rate-limit to an MCP HTTP endpoint and return correct 429 responses
  • How to write a /health endpoint that checks upstream API reachability and returns machine-readable JSON status
  • How to write Jest + Supertest integration tests that cover auth rejection, health checks, and tool execution
  • How to build a multi-stage Docker image that produces a lean production container from a TypeScript source tree
  • How to wire up a GitHub Actions CI pipeline with lint, type-check, test, and Docker build steps
  • How to manage secrets safely: never logging tokens, never returning them in tool responses, using least-privilege Argo CD tokens
  • How to configure MCP clients (Claude Desktop, Cursor, Windsurf, Continue) to talk to a self-hosted HTTP MCP server

Architecture

AI Agent (Claude / Cursor / Windsurf)
        โ”‚
        โ”‚  HTTP POST /mcp  (Bearer API Key)
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚           Express Application           โ”‚
โ”‚                                         โ”‚
โ”‚  Rate Limiter โ†’ Auth Middleware         โ”‚
โ”‚        โ”‚                                โ”‚
โ”‚        โ–ผ                                โ”‚
โ”‚  MCP Streamable HTTP Transport          โ”‚
โ”‚        โ”‚                                โ”‚
โ”‚        โ–ผ                                โ”‚
โ”‚  MCP Server (Tool Router)               โ”‚
โ”‚    โ”œโ”€โ”€ list_applications                โ”‚
โ”‚    โ”œโ”€โ”€ get_application                  โ”‚
โ”‚    โ”œโ”€โ”€ get_application_health           โ”‚
โ”‚    โ”œโ”€โ”€ get_application_sync_status      โ”‚
โ”‚    โ”œโ”€โ”€ list_application_resources       โ”‚
โ”‚    โ”œโ”€โ”€ get_application_events           โ”‚
โ”‚    โ”œโ”€โ”€ refresh_application              โ”‚
โ”‚    โ””โ”€โ”€ sync_application  โš ๏ธ write       โ”‚
โ”‚        โ”‚                                โ”‚
โ”‚  Argo CD API Client                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚  HTTPS + Argo CD API Token
             โ–ผ
      Argo CD Server (REST API)
             โ”‚
             โ–ผ
    Kubernetes Cluster(s)

Project Structure

argo-cd-mcp-server/
โ”œโ”€โ”€ .env.example
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ eslint.config.js
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ tsconfig.json
โ”œโ”€โ”€ tsconfig.eslint.json
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ server.ts
    โ”œโ”€โ”€ config.ts
    โ”œโ”€โ”€ logger.ts
    โ”œโ”€โ”€ auth.ts
    โ”œโ”€โ”€ health.ts
    โ”œโ”€โ”€ __tests__/
    โ”‚   โ””โ”€โ”€ auth.test.ts
    โ”œโ”€โ”€ argocd/
    โ”‚   โ”œโ”€โ”€ types.ts
    โ”‚   โ””โ”€โ”€ client.ts
    โ””โ”€โ”€ tools/
        โ”œโ”€โ”€ index.ts
        โ”œโ”€โ”€ listApplications.ts
        โ”œโ”€โ”€ getApplication.ts
        โ”œโ”€โ”€ getApplicationHealth.ts
        โ”œโ”€โ”€ getApplicationSyncStatus.ts
        โ”œโ”€โ”€ listApplicationResources.ts
        โ”œโ”€โ”€ getApplicationEvents.ts
        โ”œโ”€โ”€ refreshApplication.ts
        โ””โ”€โ”€ syncApplication.ts

Prerequisites

  • Node.js 20 or later
  • npm 10 or later
  • A running Argo CD instance (v2.8+) with network access from this server
  • An Argo CD API token (see Argo CD Token Setup section in the README)
  • Docker (optional, for containerised deployment)

Quick Start

# 1. Clone / copy the template
git clone https://github.com/your-org/argo-cd-mcp-server.git
cd argo-cd-mcp-server

# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env
# Edit .env โ€” set ARGOCD_SERVER_URL, ARGOCD_TOKEN, MCP_API_KEY

# 4. Build TypeScript
npm run build

# 5. Start the server
npm start

# 6. Verify health
curl http://localhost:3000/health

# 7. Run tests
npm test

Features

  • Streamable HTTP transport โ€” compatible with all MCP clients that support HTTP-based servers
  • API key auth โ€” every request to /mcp must carry a valid Authorization: Bearer <key> header
  • Argo CD REST API client โ€” typed, reusable client with token injection and TLS options
  • 8 Argo CD tools โ€” list apps, get app detail, health, sync status, resources, events, refresh, and (opt-in) sync
  • Zod input validation โ€” all tool inputs are validated before any upstream API call is made
  • Pino structured logging โ€” JSON output with correlation IDs, redacted secrets, configurable LOG_LEVEL
  • Rate limiting โ€” configurable via RATE_LIMIT_WINDOW_MS and RATE_LIMIT_MAX
  • Health endpoint โ€” GET /health checks Argo CD API reachability, returns structured JSON
  • Multi-stage Dockerfile โ€” builder stage compiles TypeScript; production stage runs only dist/
  • docker-compose.yml โ€” one-command local stack
  • Jest + Supertest tests โ€” covers health, auth rejection, and tool execution
  • GitHub Actions CI โ€” lint, type-check, test, and Docker build on every push

Works With

  • Claude Desktop โ€” add server to claude_desktop_config.json under mcpServers
  • Claude Code โ€” use claude mcp add with --transport http
  • Cursor โ€” add under Settings โ†’ MCP โ†’ Add Server
  • Windsurf โ€” configure in mcp_config.json
  • Continue โ€” add as an MCP provider in config.json

Example Claude Desktop configuration

{
  "mcpServers": {
    "argocd": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost:3000/mcp"],
      "env": {
        "MCP_REMOTE_HEADER_AUTHORIZATION": "Bearer your-mcp-api-key"
      }
    }
  }
}

Configuration

VariableDescriptionRequired
PORTTCP port the Express server listens onOptional (default 3000)
LOG_LEVELPino log level: trace debug info warn errorOptional (default info)
MCP_API_KEYSecret key that MCP clients must send as Bearer tokenRequired
ARGOCD_SERVER_URLBase URL of your Argo CD server, e.g. https://argocd.example.comRequired
ARGOCD_TOKENArgo CD API token (never logged or returned to clients)Required
ARGOCD_INSECURE_TLSSet true to skip TLS verification (dev/self-signed only)Optional (default false)
ARGOCD_NAMESPACEDefault Argo CD namespace filter for queriesOptional (default argocd)
RATE_LIMIT_WINDOW_MSRate limit window in millisecondsOptional (default 60000)
RATE_LIMIT_MAXMax requests per window per IPOptional (default 60)
ENABLE_SYNC_TOOLSet true to enable the sync_application write toolOptional (default false)
NODE_ENVdevelopment or productionOptional (default production)

Deployment

# Build
docker build -t argo-cd-mcp-server:latest .

# Run
docker run -d \
  --name argo-cd-mcp \
  -p 3000:3000 \
  --env-file .env \
  argo-cd-mcp-server:latest

Docker Compose (local dev)

docker compose up --build

Railway

npm install -g @railway/cli
railway login
railway new
railway up
# Set env vars in the Railway dashboard

Fly.io

npm install -g flyctl
fly launch --name argo-cd-mcp-server
fly secrets set MCP_API_KEY=xxx ARGOCD_TOKEN=yyy ARGOCD_SERVER_URL=https://argocd.example.com
fly deploy

Argo CD Token Setup

  1. Log in to Argo CD: argocd login argocd.example.com
  2. Create a dedicated service account: argocd account create mcp-server
  3. Grant read-only RBAC in argocd-rbac-cm ConfigMap:
policy.csv: |
  p, role:mcp-readonly, applications, get, */*, allow
  p, role:mcp-readonly, applications, list, */*, allow
  p, role:mcp-readonly, clusters, get, *, allow
  g, mcp-server, role:mcp-readonly
  1. If you need sync, add the sync action to the role:
  p, role:mcp-readonly, applications, sync, */*, allow
  1. Generate the token: argocd account generate-token --account mcp-server
  2. Copy the token value into ARGOCD_TOKEN in your .env.

โš ๏ธ Never commit the token. Use environment variables or a secrets manager.

Production Checklist

  • MCP_API_KEY is a strong random value (32+ chars), stored in a secrets manager
  • ARGOCD_TOKEN is scoped to the minimum required RBAC permissions
  • ARGOCD_INSECURE_TLS is false in production
  • ENABLE_SYNC_TOOL is false unless your team has reviewed the sync workflow
  • LOG_LEVEL is info or warn in production (not debug or trace)
  • Rate limiting values are tuned for your expected agent call volume
  • The container runs as a non-root user (the Dockerfile enforces this)
  • Health endpoint is wired up to your load balancer / Kubernetes liveness probe
  • TLS is terminated at the ingress layer โ€” do not expose port 3000 directly
  • GitHub Actions CI passes on the main branch before any deploy
  • Docker image is scanned for CVEs before pushing to production
  • Logs are shipped to a centralised log aggregator (Datadog, Loki, etc.)
  • Argo CD token rotation procedure is documented and scheduled
  • NODE_ENV=production is set so stack traces are not leaked in error responses
  • Resource limits (CPU/memory) are set on the Kubernetes Deployment or Docker container

Testing

# Run all tests
npm test

# Run with coverage
npm run test:coverage

# Manual health check
curl http://localhost:3000/health

# Manual MCP call โ€” list applications
curl -X POST http://localhost:3000/mcp \
  -H "Authorization: Bearer your-mcp-api-key" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_applications","arguments":{}}}'

Troubleshooting

SymptomLikely CauseFix
401 Unauthorized on /mcpWrong or missing MCP_API_KEYCheck Authorization: Bearer <key> header matches .env
health shows argocd: unreachableARGOCD_SERVER_URL wrong or network blockedVerify URL, firewall, and TLS cert
403 from Argo CD toolsToken lacks RBAC permissionsReview argocd-rbac-cm policy
TLS errors connecting to Argo CDSelf-signed certSet ARGOCD_INSECURE_TLS=true for dev only
sync_application tool not foundENABLE_SYNC_TOOL not setSet ENABLE_SYNC_TOOL=true and restart
Rate limit 429Too many requestsIncrease RATE_LIMIT_MAX or reduce agent call frequency

Further Reading

โœ… Template ready. What's next?

  1. 1.Copy or download the template above
  2. 2.Deploy your MCP server (Railway, Vercel)
  3. 3.Test your deployment
  4. 4.Verify production readiness