MCP server for Kubernetes cluster interaction with comprehensive resource management, execution, and discovery capabilities
kubernetes-mcp demonstrates solid definition quality with well-structured tool names, comprehensive parameter descriptions, and clear error-handling guidance. Tool naming follows the verb_noun pattern consistently (list_*, get_*, apply_*, patch_*, exec_*, etc.). All 12 tools have detailed descriptions (194-450+ chars, exceeding the 194-char baseline median). Parameter schemas are present with type definitions and descriptions. However, output schemas are not explicitly documented in the visible source code, and some tools lack structured error recovery examples. The server shows strong adherence to composition patterns (single responsibility per tool, proper tool chaining with IDs) and security awareness (no credentials in parameters, read-only vs write operations clearly marked via 'Risk' field). The use of yq_expressions for output filtering is pragmatic but adds complexity for LLM consumption. Per-tool analysis reveals consistent quality across the board.
Create-or-update (upsert) a Kubernetes resource from a YAML or JSON manifest. Behaviour: tries to Create the resource; if it already exists, falls back to Update. The resource type is detected automatically from the manifest's 'apiVersion' / 'kind', resolved against the cluster's discovery API via the RESTMapper, so CRDs and irregular plurals (StorageClass, NetworkPolicy, ...) work transparently. Limitations: - Single-document manifests only. Multi-document YAML separated by '---' is NOT supported; pass each document in a separate call. - This is a 'replace'-style update, not server-side strategic merge. For surgical changes prefer 'patch_resource'. Use 'diff_manifest' first if you want to preview the change without applying it.
Preview the changes that 'apply_manifest' would make, WITHOUT applying them. Compares the desired manifest against the current cluster state and reports field-level additions / removals / modifications. Server-managed fields that would otherwise show up as constant noise are stripped from BOTH sides before the comparison: the 'status' subtree, metadata fields ('resourceVersion', 'uid', 'generation', 'creationTimestamp', 'managedFields', 'finalizers', 'ownerReferences', 'deletionTimestamp'), the 'kubectl.kubernetes.io/last-applied-configuration' annotation, plus controller-assigned immutable fields ('Service.spec.clusterIP/clusterIPs/ ipFamilies/ipFamilyPolicy', 'PersistentVolumeClaim.spec.volumeName'). If the resource does not yet exist, the tool reports that it would be CREATED. The resource type is resolved from the manifest's 'apiVersion' / 'kind' via the cluster's RESTMapper, so CRDs and irregular plurals work transparently. Single-document manifests only; multi-doc YAML separated by '---' is rejected with an explicit error (one call per document).
Run a one-shot, non-interactive command inside a running container and return its stdout and stderr. Constraints: - Non-interactive (no TTY, no stdin). Anything that requires user input or paging will block until timeout. - Default timeout 30 seconds, configurable via 'timeout_seconds' up to 300. - Combined stdout+stderr is capped at 1 MiB; output beyond that is truncated with a clear marker. - The container must already exist (Pod in Running phase). - When the command exits with a non-zero status, the result is reported as an error (IsError=true) but the captured output is still included. Typical uses: 'cat /etc/config.yaml', 'env', 'ps aux', 'ls /var/log'. Avoid 'top', 'tail -f', 'sh' and similar interactive sessions.
Output schemas not explicitly documented in source code. While parameter input schemas are well-defined, the return structure of each tool (list items, field names, types) is not formalized in visible schema definitions.
yq_expressions parameter (array of strings) adds flexibility but introduces complexity for LLM consumption. LLMs may struggle to compose valid yq syntax, leading to tool misuse. Consider either removing this optional filtering or providing strongly-typed alternative outputs.
switch_context documentation warns of state mutation but no explicit compensation pattern for multi-user HTTP deployments. No undo_context or context_stack pattern visible. Warning text suggests the issue but offers no recovery guide.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 67 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 52 | - | v1 |
Return a small summary of the targeted cluster: server version, API host, node count, namespace count, and the human description configured for the MCP context. Useful as a smoke test before running anything destructive, and to confirm which physical cluster a context points at.
Return the name and human description of the MCP context currently selected as default. This is the context used by every other tool when its 'context' parameter is empty. To change it use 'switch_context'. To see all available contexts use 'list_contexts'.
Retrieve container logs from a Pod. Always combine 'tail_lines' or 'since_seconds' with this tool unless you are sure the log volume is small. A chatty container can return megabytes per second, which the model is not the right place to handle. For multi-container Pods you must set 'container'. To inspect logs from a crashed container that has been restarted, set 'previous: true'.
List the API resources actually served by the cluster, including CRDs. Use this to discover the exact 'group' / 'version' / 'resource' tuple to pass to other tools (get_resource, list_resources, ...). Returns one entry per (Kind, Version) pair with its plural name, group, version, namespaced flag and supported verbs. If 'list_resources' fails with "the server could not find the requested resource", run this tool first to confirm the GVR exists.
List the API groups served by the cluster and the versions available within each group, including which version is the preferred one. Use this when you don't know whether a CRD ships 'v1', 'v1beta1', or both. For the actual resources within a group prefer 'list_api_resources'.
List the MCP contexts (Kubernetes clusters) configured on this server. Each entry includes the context name, its human description from the server configuration, and whether it is the currently active default. Use this to pick a value for the 'context' parameter of other tools, or for 'switch_context'.
List the namespaces in the cluster, with phase, age, and whether the MCP authorization layer allows operating on each one. The 'allowed' field reflects this MCP server's namespace allow/deny lists for the current context, NOT Kubernetes RBAC. A namespace can be 'allowed: true' here and still reject your call due to RBAC. For full Namespace objects (labels, annotations, ...) use 'list_resources' with resource='namespaces'.
Apply a partial change to an existing Kubernetes resource. Prefer this over 'apply_manifest' when you only want to change a few fields (image tag, replica count not via scale, annotation, ...). Choose 'patch_type' carefully: - 'strategic': Strategic Merge Patch. Works only on built-in Kubernetes types and understands list-merge semantics (e.g. patching a single container by name). The default for most kubectl operations. - 'merge': RFC 7396 JSON Merge Patch. Works on any resource including CRDs. Replaces lists entirely (does not merge them by key). - 'json': RFC 6902 JSON Patch. An array of operations like [{"op":"replace","path":"/spec/replicas","value":3}]. Most precise.
Change the MCP default context (Kubernetes cluster) used by every other tool when its 'context' parameter is empty. WARNING: this changes process-wide state. In an HTTP deployment with several clients connected to the same MCP server, every other caller will start seeing tools default to the new context as soon as this returns. To avoid accidents prefer passing 'context' explicitly to every destructive tool ('apply_manifest', 'delete_resource', 'delete_resources', 'patch_resource', 'scale_resource', 'restart_rollout', 'undo_rollout', 'exec_command') instead of relying on the active context.
exec_command 1 MiB output truncation is mentioned but no explicit error classification or recovery guidance for truncated output. LLM should know whether to retry with tail_lines or accept partial results.
No explicit tool annotations (readOnlyHint, destructiveHint, idempotentHint) visible in source definitions. Risk field (READ_ONLY, WRITE) exists in metadata but is not MCP-standard annotation format.