kube-lint-mcp
README.md
# kube-lint-mcp
[](https://github.com/sophotechlabs/kube-lint-mcp/actions/workflows/ci.yml)
[](https://codecov.io/gh/sophotechlabs/kube-lint-mcp)
[](https://scorecard.dev/viewer/?uri=github.com/sophotechlabs/kube-lint-mcp)
[](https://sonarcloud.io/summary/new_code?id=sophotechlabs_kube-lint-mcp)
[](https://pypi.org/project/kube-lint-mcp/)
[](https://pypi.org/project/kube-lint-mcp/)
[](https://github.com/sophotechlabs/kube-lint-mcp/pkgs/container/kube-lint-mcp)
[](https://www.python.org/downloads/)
[](LICENSE)
[](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).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues