Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is an MCP (Model Context Protocol) server that provides a conversational interface to Argo CD. It allows AI assistants to query unhealthy applications and resources in Argo CD clusters.

**Key technologies:**
- Go 1.25
- [MCP Go SDK](https://github.com/modelcontextprotocol/go-sdk) v1.4.1
- HTTP transport (no stdio transport)
- Argo CD v3 API

## Development Commands

All commands use [Task](https://taskfile.dev/). See `taskfile.yaml` for the full list.

### Building
```bash
# Build binary to $GOPATH/bin/argocd-mcp-server
task build

# Build container image
task build-image

# Build for Linux AMD64 specifically
task build-image-linux-amd64
```

### Testing
```bash
# Run unit tests
task test

# Run linting
task lint

# Run e2e tests (requires Podman and podman-compose)
task test-e2e
```

**E2E test infrastructure:**
- Uses `podman-compose` to orchestrate containers
- Spins up a mock Argo CD server (`test/e2e/argocd-server-mock/`)
- Tests multiple server configurations (standard, unreachable, stateless with load balancer)
- See `compose.yaml` for the full test setup

### Running Locally
```bash
# After building
argocd-mcp-server --argocd-url=<url> --argocd-token=<token> --debug=true --listen=127.0.0.1:8080

# With container
podman run -d --name argocd-mcp-server \
-e ARGOCD_MCP_SERVER_LISTEN_HOST=0.0.0.0 \
-e ARGOCD_URL=<url> \
-e ARGOCD_TOKEN=<token> \
-e ARGOCD_MCP_DEBUG=true \
-p 8080:8080 argocd-mcp-server:latest
Comment on lines +55 to +60

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix inconsistent debug environment variable naming.

Line 59 uses ARGOCD_MCP_DEBUG, but Line 146 documents ARGOCD_MCP_SERVER_DEBUG. This inconsistency can misconfigure local/container debugging.

Suggested doc fix
-  -e ARGOCD_MCP_DEBUG=true \
+  -e ARGOCD_MCP_SERVER_DEBUG=true \

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security."

Also applies to: 140-147

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 55 - 60, The doc has inconsistent env var
names—ARGOCD_MCP_DEBUG (used in the podman run example) vs
ARGOCD_MCP_SERVER_DEBUG (documented later); pick the canonical name (use
ARGOCD_MCP_SERVER_DEBUG), then update every occurrence in this file (including
the podman run example and the section around lines 140–147) so the examples and
docs match; ensure references to ARGOCD_MCP_SERVER_LISTEN_HOST, ARGOCD_URL,
ARGOCD_TOKEN remain unchanged and only the debug variable name is normalized
throughout.

```

## Code Architecture

### Package Structure
```
cmd/
start_server.go # Cobra CLI command, flags, HTTP server setup
main.go # Entry point
internal/
server/
server.go # MCP server initialization, middleware, tool/prompt registration
argocd/
argocd_client.go # HTTP client for Argo CD API
unhealthy_applications.go
unhealthy_application_resources.go
```
Comment on lines +66 to +77

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language tag to fenced code block.

The package-structure code fence (starting at Line 66) is missing a language identifier (markdownlint MD040).

Suggested doc fix
-```
+```text
 cmd/
   start_server.go         # Cobra CLI command, flags, HTTP server setup
 main.go                   # Entry point
 internal/
@@
-```
+```
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
cmd/
start_server.go # Cobra CLI command, flags, HTTP server setup
main.go # Entry point
internal/
server/
server.go # MCP server initialization, middleware, tool/prompt registration
argocd/
argocd_client.go # HTTP client for Argo CD API
unhealthy_applications.go
unhealthy_application_resources.go
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 66-66: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 66 - 77, The fenced package-structure code block in
the README (the triple-backtick block showing the cmd/ and internal/ tree) is
missing a language tag; update the opening fence from ``` to ```text so the
block becomes a ```text code fence to satisfy markdownlint MD040 and render as
plain text (locate the triple-backtick block that lists cmd/, start_server.go,
main.go, internal/, server/, argocd/, etc., and add the "text" language
identifier).


### Key Architectural Patterns

**MCP Server Setup** (`internal/server/server.go`):
1. Creates MCP server with capabilities (tools, prompts)
2. Adds middleware (metrics, logging) via `mcp-common` package
3. Registers prompts and tools from `internal/argocd`
4. Supports stateless mode (disables ListChanged notifications for multi-replica deployments)

**HTTP Transport** (`cmd/start_server.go`):
- `/mcp` - MCP protocol endpoint (uses `mcp.NewStreamableHTTPHandler`)
- `/metrics` - Prometheus metrics
- `/health` - Health check endpoint

**Argo CD Client** (`internal/argocd/argocd_client.go`):
- Wraps `http.Client` with bearer token authentication
- Methods: `GetApplicationsWithContext()`, `GetApplicationWithContext()`
- Supports insecure TLS for development

**Tool Implementation Pattern**:
Each tool/prompt follows this pattern:
1. Define input/output types
2. Generate JSON schemas using `jsonschema-go`
3. Create `mcp.Tool` definition in `init()`
4. Implement handler function: `ToolHandle(logger, client) -> mcp.ToolHandlerFor[Input, Output]`

### Tool Naming Convention

Tools must follow this naming scheme (see `.cursor/skills/validating/SKILL.md`):
- Use snake_case with service prefix
- Format: `{service}_{action}_{resource}`
- Examples: `argocd_list_unhealthy_applications`, `argocd_list_unhealthy_application_resources`

### Stateless Mode

When `--stateless=true`:
- Disables `ListChanged` notifications for tools and prompts
- Required for multi-replica deployments or load balancing
- See `compose.yaml` for stateless configuration with nginx load balancer

## Testing Patterns

**Unit tests** (`internal/argocd/*_test.go`):
- Use `github.com/h2non/gock` to mock HTTP responses from Argo CD
- Test both success and error cases

**E2E tests** (`test/e2e/`):
- Test against containerized MCP server and mock Argo CD
- Verify different deployment scenarios (single instance, unreachable backend, load-balanced stateless)

## Dependencies

**Core MCP dependencies:**
- `github.com/modelcontextprotocol/go-sdk` - MCP protocol implementation
- `github.com/codeready-toolchain/mcp-common` - Shared middleware (metrics, logging)

**Argo CD integration:**
- `github.com/argoproj/argo-cd/v3` - Application types
- `github.com/argoproj/gitops-engine` - Health status types

## Environment Variables

When running the container, the server reads these environment variables:
- `ARGOCD_URL` - Argo CD server URL (required)
- `ARGOCD_TOKEN` - Bearer token for authentication (required)
- `ARGOCD_MCP_SERVER_LISTEN_HOST` - Listen host (default: 127.0.0.1)
- `ARGOCD_MCP_SERVER_LISTEN_PORT` - Listen port (default: 8080)
- `ARGOCD_MCP_SERVER_INSECURE` - Allow insecure TLS (default: false)
- `ARGOCD_MCP_SERVER_DEBUG` - Enable debug logging (default: false)
- `ARGOCD_MCP_SERVER_STATELESS` - Enable stateless mode (default: false)

See `cmd/start_server.go` for flag-to-environment mapping.
Loading