Skip to main content
Glama

Kube Check

CI npm downloads OpenSSF Scorecard License: MIT

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/v1 also needs pathType and backend.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, not always), quantities (512Mi, not 512mb), 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

Install in Cursor Install in VS Code Install in Goose

Needs Node.js 20 or newer. No account or key.

Claude Code

claude mcp add kube-check -- npx -y kube-check-mcp

Claude 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-mcp

Hosted (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

api_versions

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.

check_manifests

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.

field_help

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.com and endoflife.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 (yes is a boolean, so value: yes in 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, null fields 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 tools
api_versionsWhich apiVersion does a kind need?A
Read-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 manifestsA
Read-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?A
Read-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

    A3.9/5.0

    Scored across 3 tools

    Disambiguation4/5

    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).

    Naming Consistency3/5

    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.

    Tool Count4/5

    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.

    Completeness4/5

    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

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      Enables 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.
      3
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables 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
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables 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