Kube Check
Summary: Kube Check answers Kubernetes API and manifest questions for any 1.19-to-newest version without a cluster — three read-only tools.
check_manifests— Validate YAML/JSON manifests (multi-document, up to 50 files) against a target Kubernetes version (default: newest): removed/deprecated APIs with replacements, unknown or misspelt fields, wrong types and enum values, invalid quantities, and things the API server refuses beyond the schema (invalid names, selectors matching no pods, requests above limits, probes with two handlers, mounts of missing volumes).check_manifests— Enforce Pod Security Standards (baseline by default;restrictedornone) and surface risks like unpinned images, missing requests/limits and secrets in env; custom resources are checked against their CRD in the files or the CRDs catalog (cert-manager, Argo, Istio, Prometheus, hundreds more).check_manifests— Returns compact JSON with file, line, rule, path, message and fix for every finding, errors first, capped at 200 findings with the rest counted.api_versions— For kinds (Ingress) or apiVersion/kind pairs (batch/v1beta1/CronJob), see the apiVersions a given version serves, which one to use, and when older ones were deprecated and removed, including the replacement.field_help— Look up what a field of a kind means and accepts (description, type, allowed values, required sub-fields, nested fields) via a dotted path; omit it for the kind's top level, or usesearchto find fields by words.Shared behavior — Read-only and idempotent, no cluster, account or key needed; every tool takes an optional
kubernetes_version; manifests never leave the process (only schemas/version data are fetched over HTTPS).
Checks Argo custom resources against their CRDs, either from the supplied manifests or from a built-in CRD catalog, validating apiVersion/kind, fields, types, and schema for Argo resources.
Checks Istio custom resources against their CRDs, either from the supplied manifests or from a built-in CRD catalog, validating apiVersion/kind, fields, types, and schema for Istio resources.
Validates Kubernetes manifests (YAML or JSON, multi-document) against a chosen Kubernetes version from 1.19 to newest, checking removed/deprecated APIs and replacements, unknown or misspelt fields, schema and type errors, API server admission rules such as name/label/selector validity, Pod Security Standards, and common risks without needing a cluster.
Checks Prometheus custom resources against their CRDs, either from the supplied manifests or from a built-in CRD catalog, validating apiVersion/kind, fields, types, and schema for Prometheus resources.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Kube Check check k8s/deploy.yaml against Kubernetes 1.29 for deprecated APIs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Kube Check
Agents write Kubernetes manifests from memory, and memory is several versions old: extensions/v1beta1
Ingresses (gone since 1.22), batch/v1beta1 CronJobs (gone since 1.25), imagePullPolicy: always,
memory: 512mb, a selector that does not match the pod labels. The cluster refuses them at deploy
time, or worse, accepts them and runs something else. Kube Check checks manifests against the API of
the Kubernetes version you run or are upgrading to, without a cluster:
APIs: what that version serves, what was removed (with the replacement, and the other fields that must change: an Ingress moving to
networking.k8s.io/v1also needspathTypeandbackend.service), and what is deprecated there, for 1.19 to the newest release.Fields: unknown or misspelt fields with the one meant, wrong types, enumerated values the OpenAPI document leaves out (
Always, notalways), quantities (512Mi, not512mb), and what the API server refuses beyond the schema: names, labels, selectors that match no pods, requests above limits, probes with two handlers, mounts of volumes that do not exist.Custom resources: checked against their CRD when it is in the files, else the CRDs catalog (cert-manager, Argo, Istio, Prometheus and hundreds more).
Pod Security Standards: baseline by default, restricted on request, check by check as Pod Security admission applies them; plus risks such as unpinned images, missing requests and secrets written into env.
Every finding has its file, line, rule and fix. Look up any field's meaning, or which apiVersion a kind needs, in the same version. No cluster or key needed.
Built and maintained by Arhan Canli.
Install
Needs Node.js 20 or newer. No account or key.
Claude Code
claude mcp add kube-check -- npx -y kube-check-mcpClaude Desktop: download kube-check-mcp-<version>.mcpb from the latest release and open it. The bundle is signed; verify it with gh attestation verify <file> --repo arhancanli/kube-check-mcp.
Any other client (Windsurf, Zed, Cline, Continue and others), in its MCP config file:
{
"mcpServers": {
"kube-check": {
"command": "npx",
"args": [
"-y",
"kube-check-mcp"
]
}
}
}Docker
docker build -t kube-check-mcp https://github.com/arhancanli/kube-check-mcp.git && docker run -i --rm kube-check-mcpHosted (Streamable HTTP): node src/server.mjs --http serves stateless MCP at POST /mcp (port from PORT, default 3000).
Related MCP server: k8s-traps
Example
An agent calls check_manifests with:
{
"files": [
{
"path": "k8s/app.yaml",
"content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: Web_App\n labels:\n app: web\nspec:\n replicas: 2\n selector:\n matchLabels:\n app: web\n template:\n metadata:\n labels:\n app: website\n spec:\n containers:\n - name: web\n image: nginx\n imagePullPolicy: always\n port:\n - containerPort: 80\n resources:\n requests:\n memory: 512mb\n cpu: \"2\"\n limits:\n cpu: \"1\"\n env:\n - name: DB_PASSWORD\n value: hunter2\n - name: DEBUG\n value: yes\n securityContext:\n privileged: true\n---\napiVersion: extensions/v1beta1\nkind: Ingress\nmetadata:\n name: web\nspec:\n rules:\n - host: example.com\n http:\n paths:\n - path: /\n backend:\n serviceName: web\n servicePort: 80\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: web\nspec:\n selector:\n app: web\n ports:\n - port: 80\n targetPort: http\n---\napiVersion: batch/v1beta1\nkind: CronJob\nmetadata:\n name: cleanup\nspec:\n schedule: \"0 3 * *\"\n jobTemplate:\n spec:\n template:\n spec:\n containers:\n - name: c\n image: busybox:1.36\n---\napiVersion: policy/v1beta1\nkind: PodSecurityPolicy\nmetadata:\n name: restricted\nspec: {}\n"
}
]
}and gets back (recorded from the live server on 2026-09-27):
{
"kubernetes_version": "1.37",
"objects": 5,
"counts": {
"error": 12,
"warning": 5
},
"findings": [
{
"file": "k8s/app.yaml",
"line": 4,
"object": "Deployment/Web_App",
"severity": "error",
"rule": "invalid-name",
"path": "metadata.name",
"message": "The Deployment name \"Web_App\" is invalid: lowercase letters, digits, '-' and '.', starting and ending with a letter or digit."
},
{
"file": "k8s/app.yaml",
"line": 9,
"object": "Deployment/Web_App",
"severity": "error",
"rule": "selector-mismatch",
"path": "spec.selector",
"message": "The selector does not match the pod template's labels (app=website): the API server refuses it.",
"fix": "make spec.template.metadata.labels contain every selector label"
},
{
"file": "k8s/app.yaml",
"line": 20,
"object": "Deployment/Web_App",
"severity": "error",
"rule": "schema",
"path": "spec.template.spec.containers[0].imagePullPolicy",
"message": "\"always\" is not an allowed value",
"did_you_mean": "Always",
"allowed": [
"Always",
"IfNotPresent",
"Never"
]
},
{
"file": "k8s/app.yaml",
"line": 21,
"object": "Deployment/Web_App",
"severity": "error",
"rule": "schema",
"path": "spec.template.spec.containers[0].port",
"message": "unknown property \"port\"",
"did_you_mean": "ports"
},
{
"file": "k8s/app.yaml",
"line": 25,
"object": "Deployment/Web_App",
"severity": "error",
"rule": "schema",
"path": "spec.template.spec.containers[0].resources.requests.memory",
"message": "\"512mb\" is not a quantity: write 512Mi (powers of 1024) or 512M (powers of 1000); units are Ki Mi Gi Ti Pi Ei or k M G T P E, and m means thousandths",
... (127 more lines)Tools
Tool | What it does |
| For Kubernetes kinds (Ingress) or apiVersion/kind pairs (batch/v1beta1/CronJob): the apiVersions a version serves (default: newest), the one to use, and when older ones were deprecated and removed. A named apiVersion gets its status there: served, deprecated or removed, with the replacement. |
| Checks Kubernetes manifests (YAML/JSON, multi-document) against a Kubernetes version (default: newest): removed or deprecated APIs with replacements, unknown or wrong fields, what the API server refuses, Pod Security (baseline; restricted on request), risks. Custom resources via their CRD. Findings have file, line, fix. Render Helm/Kustomize first. |
| What a field of a Kubernetes kind means and accepts, from the version's API (default: newest): description, type, allowed values, required sub-fields and the fields under it. field is a dotted path (spec.template.spec.containers[].resources); omit it for the kind's top level. search finds fields by words instead (search: 'rolling update surge'). |
How it behaves
Read-only: no tool changes anything outside this process. Manifests never leave it; only schemas and version data are downloaded.
Network: HTTPS only, to
raw.githubusercontent.comandendoflife.date, with a deadline, a size cap and bounded retries. Sources: each version's API definitions from kubernetes-json-schema (generated from Kubernetes' own OpenAPI document; one 1.5 MB file per version, fetched once and kept), removal and deprecation history from Pluto (Apache-2.0), custom resource schemas from the CRDs catalog (MIT), and the release list from endoflife.date. Nothing is logged except unexpected failures (to stderr, without your inputs).Read as kubectl reads: YAML 1.1 (
yesis a boolean, sovalue: yesin env is refused, as the API server refuses it), every document of a file, List objects split, comment-only documents (Helm's disabled templates) skipped,nullfields treated as unset.Whether an apiVersion is served comes from that version's own definitions; Pluto's table only adds when it was deprecated and removed, and a deprecation is reported only when the version also serves a newer API to move to. A field the CRDs catalog's schema does not know is a warning, not an error, unless it is a near miss of a known field: the installed CRD may be newer.
Patterns written for Go's regular expressions (
(?i),\z,[[:alpha:]]) are translated; one that still cannot run in JavaScript is not checked rather than failing the whole schema.Results are compact JSON with a matching output schema: errors first, then warnings, then notes; at most 200 findings are listed and the rest counted.
Benchmark
Not yet measured.
Performance
Measured 2026-09-27 from Dubai, home connection against the live upstream, Node 24.19.0 (bench/perf.json, scripts/perf.mjs in the factory).
Call | First call | Repeat | Result size |
check_manifests: a Deployment with eight mistakes, a removed Ingress, CronJob and PodSecurityPolicy | 906 ms | 2.7 ms | 5,625 chars |
check_manifests: a clean Deployment, Service and Ingress under the restricted Pod Security level | 907 ms | 2.6 ms | 67 chars |
check_manifests: a CRD with its resource, a cert-manager Certificate and a pod, restricted | 867 ms | 2.9 ms | 3,186 chars |
check_manifests: manifests written for 1.24, checked for the upgrade to 1.25 | 748 ms | 1.9 ms | 663 chars |
check_manifests: the same manifests on 1.24, where they are only deprecated | 578 ms | 2.4 ms | 696 chars |
api_versions: six kinds and apiVersions | 696 ms | 0.7 ms | 2,010 chars |
field_help: a Deployment's rolling update surge | 1088 ms | 0.9 ms | 826 chars |
field_help: search a Pod's fields for 'termination grace' | 1015 ms | 1.9 ms | 1,085 chars |
First call: a fresh server process, including the TLS connection and the upstream's own time. Repeat: the same call again, answered from the in-process cache, so it shows this server's own overhead.
Tool definitions the model reads on every turn (name, description, input schema): 2,212 characters. The full tool list, with the output schemas and annotations clients use to validate results, is 3,614 characters.
More MCP servers by Arhan Canli
Actions Check: Checks GitHub Actions workflows: outdated actions, old Node runtimes, retired runners, injection.
Config Check: Validates config files against their official schemas: tsconfig, compose, workflows, 1,400+ more.
Cron Check: Explains cron expressions, lists next run times in any time zone, converts between cron dialects.
Dockerfile Check: Checks Dockerfiles: build-breaking mistakes, base image tags that exist, digests, platforms, EOL.
Domain Health: Email and domain checks: SPF lookup limits, DKIM keys, DMARC, DNS records, registration expiry.
End of Life: Is this version still supported? EOL dates, latest patch and upgrade target for 470+ products.
Internet Standards: RFC sections, status, obsoleted-by chains, errata and IANA registries for coding agents.
License Check: Open source license answers: SPDX ids, copyleft, and whether a dependency's license fits yours.
The whole collection, 12 more
License
MIT, Copyright (c) 2026 Arhan Canli.
Available Tools
3 toolsapi_versionsWhich apiVersion does a kind need?ARead-onlyIdempotent
For Kubernetes kinds (Ingress) or apiVersion/kind pairs (batch/v1beta1/CronJob): the apiVersions a version serves (default: newest), the one to use, and when older ones were deprecated and removed. A named apiVersion gets its status there: served, deprecated or removed, with the replacement.
Inputs: kinds (required), kubernetes_version. Returns: results, kubernetes_version
check_manifestsCheck Kubernetes manifestsARead-onlyIdempotent
Checks Kubernetes manifests (YAML/JSON, multi-document) against a Kubernetes version (default: newest): removed or deprecated APIs with replacements, unknown or wrong fields, what the API server refuses, Pod Security (baseline; restricted on request), risks. Custom resources via their CRD. Findings have file, line, fix. Render Helm/Kustomize first.
Inputs: files (required), pod_security, kubernetes_version. Returns: counts, objects, findings, kubernetes_version
field_helpWhat does this Kubernetes field do?ARead-onlyIdempotent
What a field of a Kubernetes kind means and accepts, from the version's API (default: newest): description, type, allowed values, required sub-fields and the fields under it. field is a dotted path (spec.template.spec.containers[].resources); omit it for the kind's top level. search finds fields by words instead (search: 'rolling update surge').
Inputs: kind (required), field, search, kubernetes_version. Returns: kind, apiVersion, kubernetes_version
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
The three tools target distinct activities: API version lifecycle lookup (api_versions), manifest validation (check_manifests), and field schema documentation (field_help). There is mild overlap between api_versions and check_manifests since both surface deprecated/removed APIs, but the descriptions make the boundary clear (lookup vs. file-level validation).
All names are snake_case, which is good, but the patterns differ: api_versions is a noun phrase, check_manifests is verb_noun, and field_help is noun_noun. Readable but no single predictable convention.
Three focused tools is on the lean side but each covers a distinct, well-motivated capability for Kubernetes manifest checking. No filler tools and no obvious redundancy.
The surface covers the key lifecycle needs: API version/deprecation status, manifest validation with fixes, and field documentation including CRDs and Helm/Kustomize-aware behavior. Minor gaps like live-cluster validation or explicit schema browsing are acceptable for the stated scope.
Related MCP Connectors
kube-linter audit for Kubernetes manifests — 63 checks: security, availability, RBAC, network.
Fail-closed policy guardrails for AI agents running kubectl, terraform, helm, and argocd.
Four IaC audits in one call: Compose, Dockerfile, GitHub Actions, Kubernetes. 131 checks.
Multi-CI security scanner with a live threat-intel feed of compromised CI components
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server to lint and validate Kubernetes-related manifests(Helm, FluxCD, ArgoCD, Kustomize, etc.)73 PyPIMIT
- AlicenseAqualityCmaintenanceEnables AI agents to audit Kubernetes manifests for configuration traps that pass linters but silently break production, via read-only tools to audit YAML, list known traps, and explain trap details.3MIT
- AlicenseNot gradedqualityBmaintenanceEnables read-only inspection of Kubernetes resources and Terraform plans, retrieval of policy findings, and schema and policy validation of manifests and patches without applying changes.MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to audit, generate, debug, and learn Kubernetes, OpenShift, ROSA, Helm, and RHACS/StackRox configurations through read-only-first tools, playbooks, cited local knowledge, and hardened manifest generation that runs offline unless network access is explicitly enabled.Apache 2.0