Metadata-Version: 2.4
Name: kube-lint-mcp
Version: 0.8.1
Summary: MCP server for Kubernetes, Helm, ArgoCD, and FluxCD validation
Project-URL: Homepage, https://github.com/sophotechlabs/kube-lint-mcp
Project-URL: Repository, https://github.com/sophotechlabs/kube-lint-mcp
Project-URL: Issues, https://github.com/sophotechlabs/kube-lint-mcp/issues
Author-email: Artem Muterko <artem@sopho.tech>
License-Expression: MIT
License-File: LICENSE
Keywords: argocd,fluxcd,gitops,helm,kubernetes,mcp,validation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.12
Requires-Dist: mcp>=1.23.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.10; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Description-Content-Type: text/markdown

# kube-lint-mcp

[![CI](https://github.com/sophotechlabs/kube-lint-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/sophotechlabs/kube-lint-mcp/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/sophotechlabs/kube-lint-mcp/branch/main/graph/badge.svg)](https://codecov.io/gh/sophotechlabs/kube-lint-mcp)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/sophotechlabs/kube-lint-mcp/badge)](https://scorecard.dev/viewer/?uri=github.com/sophotechlabs/kube-lint-mcp)
[![PyPI](https://img.shields.io/pypi/v/kube-lint-mcp.svg)](https://pypi.org/project/kube-lint-mcp/)
[![PyPI Downloads](https://img.shields.io/pypi/dm/kube-lint-mcp.svg)](https://pypi.org/project/kube-lint-mcp/)
[![Docker](https://ghcr-badge.egpl.dev/sophotechlabs/kube-lint-mcp/latest_tag?trim=major&label=docker&ignore=latest,sha256%2A)](https://github.com/sophotechlabs/kube-lint-mcp/pkgs/container/kube-lint-mcp)
[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-compatible-purple.svg)](https://modelcontextprotocol.io)

mcp-name: io.github.sophotechlabs/kube-lint-mcp

MCP server that validates Kubernetes manifests, Helm charts, and ArgoCD applications before you commit — preventing deployment and GitOps reconciliation failures.

Works with [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Claude Desktop](https://claude.ai/download), and any [MCP-compatible](https://modelcontextprotocol.io) client.

## How it works

```
You: "Validate the flux manifests in ./k8s/infrastructure/"

Claude: calls list_kube_contexts → presents list → you confirm "staging"
        calls select_kube_context → flux_dryrun

  FluxCD Dry-Run Validation
  Context: staging
  ================================================
  File: infrastructure/redis.yaml
    Client dry-run: PASS
    Server dry-run: PASS

  File: infrastructure/postgres.yaml
    Client dry-run: PASS
    Server dry-run: FAIL
      Error: namespace "db" not found
  ================================================
  Summary: 1 passed, 1 failed

  DO NOT COMMIT - Fix errors first!
```

No flags, no CLI args — the AI agent picks the right tool automatically.

## Prerequisites

- Python 3.12+
- [kubectl](https://kubernetes.io/docs/tasks/tools/) configured with cluster access
- [helm](https://helm.sh/docs/intro/install/) (for Helm chart validation)
- [flux](https://fluxcd.io/flux/installation/) (for Flux operations)
- [argocd](https://argo-cd.readthedocs.io/en/stable/cli_installation/) (for ArgoCD operations — uses `--core` mode, no server auth needed)

## Installation

### pip (requires CLI tools installed separately)

```bash
pip install kube-lint-mcp
```

### Docker (batteries included)

The Docker image ships with kubectl, helm, flux, kubeconform, and argocd — no local installs needed.

```bash
docker pull ghcr.io/sophotechlabs/kube-lint-mcp:latest
```

> **Note**: If your kubeconfig uses external auth plugins (e.g. `gke-gcloud-auth-plugin`, `aws-iam-authenticator`), those binaries are not included in the image. Use the pip install method for those clusters, or embed tokens directly in your kubeconfig.

## Configuration

### Claude Code (pip)

Add to your project's `.mcp.json`:

```json
{
  "mcpServers": {
    "kube-lint": {
      "command": "python",
      "args": ["-m", "kube_lint_mcp"]
    }
  }
}
```

### Claude Code (Docker)

```json
{
  "mcpServers": {
    "kube-lint": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "${HOME}:${HOME}:ro",
        "-e", "KUBECONFIG=${HOME}/.kube/config",
        "ghcr.io/sophotechlabs/kube-lint-mcp:latest"
      ]
    }
  }
}
```

The `$HOME:$HOME:ro` mount preserves absolute paths that MCP clients send to the server. The read-only flag ensures the container cannot modify your files.

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%/Claude/claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "kube-lint": {
      "command": "python",
      "args": ["-m", "kube_lint_mcp"]
    }
  }
}
```

## Tools

### select_kube_context

Pick a cluster context. Stored in memory only — **never mutates your kubeconfig**. Must be called before any validation tool.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `context` | string | yes | Name of the kubectl context to use |

### list_kube_contexts

Show available kubectl contexts with markers for the current (kubeconfig default) and selected (in-memory) context. No parameters.

### flux_dryrun

Validate FluxCD YAML files with both client-side and server-side kubectl dry-run. Catches schema errors, missing CRDs, namespace issues, and deprecated API versions.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | yes | Path to YAML file or directory containing manifests |

```
You: "Validate the flux manifests in k8s/infrastructure/"
```

### kustomize_dryrun

Build a Kustomize overlay and validate the rendered output with kubectl dry-run. Runs the full pipeline: `kustomize build` → client dry-run → server dry-run.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | yes | Path to directory containing kustomization.yaml |

```
You: "Dry-run the staging kustomize overlay in k8s/overlays/staging/"
```

### helm_dryrun

End-to-end Helm chart validation: `helm lint` → `helm template` → client dry-run → server dry-run. Catches chart errors, template rendering issues, and invalid rendered manifests.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `chart_path` | string | yes | Path to Helm chart directory |
| `values_file` | string | no | Path to custom values file |
| `namespace` | string | no | Namespace for rendering |
| `release_name` | string | no | Release name for helm template (default: `release-name`) |

```
You: "Validate the nginx helm chart in charts/nginx/ with staging values"
```

### flux_check

Verify Flux installation health by running `flux check`. Reports controller status and version compatibility. No parameters.

### flux_status

Show Flux reconciliation status for all resources across all namespaces (`flux get all -A`). Useful for checking if resources are synced or stuck. No parameters.

### argocd_app_list

List all ArgoCD applications with sync and health status. Uses `--core` mode — connects via kubeconfig, no ArgoCD server auth needed.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `namespace` | string | no | Namespace where Application CRs live (e.g. `argocd`, `argo-cd`) |

```
You: "List all ArgoCD applications"
```

### argocd_app_get

Get detailed status of a single ArgoCD application including sync/health status, conditions, and per-resource breakdown.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `app_name` | string | yes | Name of the ArgoCD Application |
| `namespace` | string | no | Namespace where the Application CR lives |

```
You: "Show me the status of the my-app ArgoCD application"
```

### argocd_app_diff

Show unified diff between live and desired state of an ArgoCD application. Indicates whether the app is in sync or what would change on the next sync.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `app_name` | string | yes | Name of the ArgoCD Application |
| `namespace` | string | no | Namespace where the Application CR lives |

```
You: "Show me what would change if we sync the my-app ArgoCD application"
```

### yaml_validate

Validate YAML syntax of Kubernetes manifest files. Catches syntax errors, duplicate keys, and tab indentation. **Does not require a cluster connection.**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | yes | Path to YAML file or directory |

### kubeconform_validate

Offline schema validation against Kubernetes JSON schemas. **Does not require a cluster connection.** Catches invalid fields, type mismatches, and missing required fields.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `path` | string | yes | Path to YAML file or directory |
| `kubernetes_version` | string | no | Target K8s version for schema lookup (e.g. `1.29.0`). Default: `master` |
| `strict` | boolean | no | Reject fields not in the schema (default: `false`) |

```
You: "Validate all manifests in k8s/ against Kubernetes 1.29 with strict mode"
```

## Typical workflow

### FluxCD / Helm / Kustomize
1. `list_kube_contexts` — see available clusters
2. `select_kube_context` — target a cluster (in-memory only, never mutates kubeconfig)
3. `flux_dryrun`, `kustomize_dryrun`, or `helm_dryrun` — validate before committing
4. Only commit when all checks pass

### ArgoCD
1. `list_kube_contexts` / `select_kube_context` — pick a cluster
2. `argocd_app_list` — see all apps and their sync/health status
3. `argocd_app_get` — drill into a specific app's resources and conditions
4. `argocd_app_diff` — see what would change on the next sync

For offline validation without a cluster, use `kubeconform_validate` or `yaml_validate` directly — no context selection needed.

## Safety

The server **never mutates your kubeconfig**. Context is held in memory and passed via `--context` flag on every subprocess call. This is a deliberate safety choice for agentic use — the AI cannot accidentally switch your global kubectl context.

All validation tools are **read-only** — they use `kubectl apply --dry-run` which simulates without applying. No resources are created, modified, or deleted.

## Configuration reference

### Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `KUBE_LINT_KUBECTL_TIMEOUT` | `60` | Timeout in seconds for kubectl dry-run operations |
| `KUBE_LINT_HELM_TIMEOUT` | `60` | Timeout for helm lint and template operations |
| `KUBE_LINT_FLUX_TIMEOUT` | `60` | Timeout for flux check and status operations |
| `KUBE_LINT_KUBECONFORM_TIMEOUT` | `120` | Timeout for kubeconform validation |
| `KUBE_LINT_ARGOCD_TIMEOUT` | `60` | Timeout for ArgoCD CLI operations |

Set these in your MCP server config:

```json
{
  "mcpServers": {
    "kube-lint": {
      "command": "python",
      "args": ["-m", "kube_lint_mcp"],
      "env": {
        "KUBE_LINT_KUBECTL_TIMEOUT": "120"
      }
    }
  }
}
```

## Troubleshooting

### "kubectl not found" or "helm not found"

The pip install only installs the Python package. You need kubectl, helm, and flux installed separately and on your `PATH`. The Docker image includes all tools — use it if you don't want to manage CLI installations.

### Docker: "unable to load kubeconfig" or auth errors

Make sure your kubeconfig is accessible inside the container. The `$HOME:$HOME:ro` mount maps your home directory read-only. If your kubeconfig references files outside `$HOME` (e.g. `/etc/kubernetes/`), mount those paths too.

If your kubeconfig uses **auth plugins** (GKE, EKS), the plugin binaries aren't in the Docker image. Either:
- Use the pip install method instead
- Or generate a static token/certificate kubeconfig for the Docker image

### "context not selected" errors

Always call `select_kube_context` (or let the agent call `list_kube_contexts` first) before running any validation tool. The server does not read a default context from kubeconfig — this is intentional for safety.

Exception: `kubeconform_validate` works offline and does not need a context.

### Timeouts on large charts or slow clusters

Increase the relevant timeout via environment variables. For a Helm chart with many templates against a slow API server:

```json
{
  "env": {
    "KUBE_LINT_KUBECTL_TIMEOUT": "120",
    "KUBE_LINT_HELM_TIMEOUT": "120"
  }
}
```

### Server dry-run fails but client dry-run passes

This is expected. Client dry-run validates syntax and schema locally. Server dry-run sends the manifest to the API server which checks additional constraints: namespace existence, CRD availability, admission webhooks, resource quotas. Fix the server-side issue before committing.

### "argocd not found"

Install the ArgoCD CLI: `brew install argocd` (macOS) or download from [releases](https://github.com/argoproj/argo-cd/releases). The Docker image includes the ArgoCD CLI.

### ArgoCD --core mode

All ArgoCD tools use `--core` mode, which connects directly via your kubeconfig — no ArgoCD server authentication is needed. This requires that the ArgoCD CRDs (Application, AppProject) are installed on the cluster.

### kubeconform reports "skipped" resources

Custom Resource Definitions (CRDs) don't have upstream schemas. kubeconform skips resources it can't validate. This is normal for FluxCD, cert-manager, and other CRD-heavy stacks.

## Development

```bash
pip install -e ".[dev]"
make test    # 100% coverage
make lint    # ruff
```

## Contributing

1. Fork the repo
2. Create a feature branch
3. Make sure `make test` and `make lint` pass
4. Open a PR

## License

[MIT](LICENSE)

---

If this tool saves you from a bad deploy, consider [sponsoring](https://github.com/sponsors/sophotechlabs).
