Skip to main content
Glama
BenedatLLC

Kubernetes Tools MCP Server

by BenedatLLC

Kubernetes Tools

Unit Tests

This package provides a collection of Kubernetes functions to be used by Agents. They can be passed directly to an agent as tools or placed behind an MCP server (included). Some use cases include:

  • Chat with your kubernetes cluster via GitHub CoPilot or Cursor.

  • Build agents to monitor your cluster or perform root cause analysis.

  • Vibe-code a custom chat UI.

  • Use in non-agentic automations.

  • Snapshot a live cluster to a file and replay it as a test fixture, with no cluster needed — see Capturing and replaying a cluster.

Methodology

Our goal is to focus on quality over quantity -- providing well-documented and strongly typed tools. We believe that this is a critical in enabling agents to make effective use of tools, beyond simple demos.

These are built on top of the kubernetes Python API (https://github.com/kubernetes-client/python). There are three styles of tools provided here:

  1. There are tools that mimic the output of kubectl commands (e.g. get_pod_summaries, which is equivalent to kubectl get pods). Strongly-typed Pydantic models are used for the return values of these tools.

  2. There are tools that return strongly typed Pydantic models that attempt to match the associated Kubernetes client types (see https://github.com/kubernetes-client/python/tree/master/kubernetes/docs). Lesser used fields may be omitted from these models. An example of this case is get_pod_container_statuses.

  3. In some cases we simply call to_dict() on the class returned by the API (defined in https://github.com/kubernetes-client/python/tree/master/kubernetes/client/models). The return type is dict[str,Any], but we document the fields in the function's docstring. get_pod_spec is an example of this type of tool.

Currently, the priority is on functions that do not modify the state of the cluster. We want to focus first on the monitoring / RCA use cases. When we do add tools to address other use cases, they will be kept separate from the read-only tools so you can still build "safe" agents.

Related MCP server: kubeview-mcp

Installation

Via pip:

pip install k8stools

Via uv:

uv add k8stools

This installs three commands: k8s-mcp-server (the MCP server), k8s-mcp-client (a client for manual testing), and k8s-capture-state (snapshot a cluster to a replayable file).

What changed in each release is in the changelog.

Permissions

The tools only read, with the get and list verbs. A read-only ClusterRole that covers every tool:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: k8stools-reader
rules:
- apiGroups: [""]
  resources: [namespaces, nodes, pods, pods/log, events, services, configmaps,
              persistentvolumeclaims]
  verbs: [get, list]
- apiGroups: [apps]
  resources: [deployments, replicasets, statefulsets, daemonsets, controllerrevisions]
  verbs: [get, list]
- apiGroups: [batch]
  resources: [jobs, cronjobs]
  verbs: [get, list]

get_cluster_info also reads the server version (/version), which every authenticated user can read by default. No tool reads Secrets: get_workload_history names the Secrets a workload uses, from its pod template, without reading them.

Current tools

These are the tools we define:

  • get_cluster_info - which cluster the tools are answering from: kubeconfig context, API server URL and version, or the capture being replayed

  • get_namespaces - get a list of namespaces, like kubectl get namespace

  • get_node_summaries - get a list of nodes, like kubectl get nodes -o wide (includes capacity/allocatable/conditions/taints/labels)

  • get_pod_summaries - get a list of pods, like kubectl get pods -o wide, with each pod's controlling owner (e.g. DaemonSet/otel-collector-agent)

  • get_pod_container_statuses - return the status for each of the container in a pod

  • get_pod_events - return the events for a pod

  • get_pod_spec - retrieves the spec for a given pod

  • get_logs_for_pod_and_container - retrieves logs from a pod and container (supports tail, since_seconds, and previous). See Previous-instance log semantics for when previous=True returns the same text as previous=False — it is Kubernetes behavior, not a bug.

  • get_deployment_summaries - get a list of deployments, like kubectl get deployments

  • get_replicaset_summaries - get a deployment's replica sets with their revision numbers and images. A deployment's replica sets are its change history: use this to see when a workload last changed and what the change was.

  • get_workload_history - what changed in a Deployment, StatefulSet or DaemonSet, and when: each retained revision of its pod template compared with the one before (images, resources, probes, command/args, env var names, volumes, scheduling), plus the ConfigMaps and Secrets it references. It states what history cannot show.

  • get_service_summaries - get a list of services, like kubectl get services (includes selector/labels/annotations)

  • get_configmap_summaries - get a list of ConfigMaps, like kubectl get configmaps

  • get_configmap - retrieve the full contents of a single ConfigMap

  • get_statefulset_summaries - get a list of StatefulSets, like kubectl get statefulsets

  • get_daemonset_summaries - get a list of DaemonSets, like kubectl get daemonsets -o wide (includes node selector and images)

  • get_cronjob_summaries - get a list of CronJobs, like kubectl get cronjobs

  • get_job_summaries - get a list of Jobs, like kubectl get jobs

  • get_logs_for_job - retrieve logs from a Job's most-recent pod

  • get_logs_for_cronjob - retrieve logs from a CronJob's most-recent run

  • get_pvc_summaries - get a list of PersistentVolumeClaims, like kubectl get pvc (resolves mounting pods)

  • get_events - list cluster/namespace-wide events with server-side filtering

We also define a set of associated "print_" functions that are helpful in debugging:

  • print_namespaces

  • print_node_summaries

  • print_pod_summaries

  • print_pod_container_statuses

  • print_pod_events

  • print_pod_spec

  • print_deployment_summaries

  • print_workload_history

  • print_service_summaries

  • print_configmap_summaries

  • print_configmap

  • print_statefulset_summaries

  • print_daemonset_summaries

  • print_cronjob_summaries

  • print_job_summaries

  • print_pvc_summaries

  • print_events

Using the tools

Directly use in an agent

The core tools are in k8stools.k8s_tools. Here's an example usage in an agent:

from pydantic_ai.agent import Agent
from k8stools.k8s_tools import TOOLS
from k8stools.redaction import wrap_with_redaction

agent = Agent(
        model="openai:gpt-4.1",
        system_prompt=SYSTEM_PROMPT,
        tools=[wrap_with_redaction(fn) for fn in TOOLS],
)

result = agent.run_sync("What is the status of the pods in my cluster?")
print(result.output)

The tools use KUBECONFIG (or ~/.kube/config) and its current context. To pin a cluster instead, call configure before the first tool call:

from k8stools import k8s_tools

k8s_tools.configure(kubeconfig="~/.kube/prod.yaml", context="prod-eu")

See Selecting a cluster for how the selection is resolved.

⚠️ Redaction is not automatic outside the k8stools MCP server. The functions in TOOLS (and mock_tools.TOOLS) return raw values: ConfigMap contents, env values in pod specs, container logs and command-line args, exactly as the API returns them. Only k8s-mcp-server and k8s-capture-state apply redaction for you. If you hand TOOLS to an agent, or build your own MCP server from them, wrap each one with wrap_with_redaction as above, or anything secret-shaped in your cluster goes straight into the model's context. See Where redaction applies.

Using via MCP

The script k8s-mcp-server provides an MCP server for the same set of tools. Here are the command line arguments for the server:

usage: k8s-mcp-server [-h] [--transport {streamable-http,stdio}] [--host HOST] [--port PORT]
                      [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--debug]
                      [--kubeconfig PATH] [--context NAME] [--mock] [--state-file FILE]
                      [--state-time {advancing,frozen}] [--no-redact]

Run the MCP server.

options:
  -h, --help            show this help message and exit
  --transport {streamable-http,stdio}
                        Transport to use for MCP server [default: stdio]
  --host HOST           Hostname for HTTP service [default: 127.0.0.1]
  --port PORT           Port for HTTP service [default: 8000]
  --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
                        Log level [default: INFO]
  --debug               Enable debug mode [default: False]
  --kubeconfig PATH     Kubeconfig file to use [default: KUBECONFIG, then ~/.kube/config]
  --context NAME        Kubeconfig context to use [default: K8STOOLS_CONTEXT, then the
                        kubeconfig's current-context]. A kubeconfig or context that is given but
                        cannot be loaded stops the server rather than falling back to another
                        cluster.
  --mock                Run mock versions of the tools that don't need a cluster
  --state-file FILE     Serve a captured cluster snapshot from FILE (implies --mock)
  --state-time {advancing,frozen}
                        Replay clock for a captured snapshot [default: advancing]
  --no-redact           Disable secret redaction of tool output (on by default)

Selecting a cluster

Each server answers from exactly one cluster, chosen at startup:

Kubeconfig file

Context

1st

--kubeconfig PATH

--context NAME

2nd

KUBECONFIG

K8STOOLS_CONTEXT

3rd

~/.kube/config

the file's current-context

With none of these given and no usable kubeconfig, the server falls back to the in-cluster service account, as when it runs in a pod.

The server logs the binding when it starts:

WARNING:root:Bound to cluster: context 'prod-eu' at https://prod-eu.example:6443 (kubeconfig: /home/me/.kube/prod.yaml)

and the get_cluster_info tool reports it to an agent, so an agent can check which cluster it is talking to without leaving MCP.

A few rules keep a server from quietly answering from the wrong cluster:

  • An explicit selection never falls back. If a --kubeconfig, --context or K8STOOLS_CONTEXT is given but cannot be loaded (a missing file, a misspelled context), the server exits with an error. It does not fall back to in-cluster config, which in a pod would silently mean that pod's cluster.

  • The binding is made once. Every tool shares it, and it does not follow later changes to the kubeconfig: running kubectl config use-context does not repoint a server that is already running.

  • --kubeconfig and --context are rejected with --mock or --state-file, which serve a capture rather than a cluster.

To serve two clusters, run two servers:

k8s-mcp-server --transport=streamable-http --port=8001 --context prod-eu
k8s-mcp-server --transport=streamable-http --port=8002 \
    --kubeconfig ~/.kube/eks.yaml --context staging

Use MCP with the stdio transport

The stdio transport is best for use with local Coding Agents, like GitHub CoPilot or Cursor. It is the default, so you can run the k8s-mcp-server script without arguments. Here's an example mcp.json configuration:

{
   "servers": {
      "k8stools-stdio": {
         "command": "${workspaceFolder}/.venv/bin/k8s-mcp-server",
         "args": [
         ],
         "envFile": "${workspaceFolder}/.envrc"
      }
   }
}

This assumes the following:

  1. The Python virtual environment is expected to be in .venv under the root of your VSCode workspace

  2. You have installed the k8stools package into your workspace

  3. The environment file .envrc contains any variables you need defined. In particular, you may need to set KUBECONFIG to point to your kubectl config file, and K8STOOLS_CONTEXT to pin a context (or pass --kubeconfig / --context in args).

Use MCP with the streamable HTTP transport

The streamable http transport is enabled with the command line option --transport=streamable-http. It will start an HTTP server which listens on the specified address and port (defaulting to 127.0.0.1 and 8000, respectively). This transport is best for cases where you want remote access to your MCP server.

Here's a short example that starts the server and then does a sanity test using curl to get the tool information:

# start the server
 $ k8s-mcp-server --transport=streamable-http
[07/21/25 19:55:13] INFO     Starting with 18 tools on transport streamable-http          mcp_server.py:59
INFO:     Started server process [6649]
INFO:     Waiting for application startup.
INFO     StreamableHTTP session manager started         streamable_http_manager.py:111
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

# Now, open another terminal window and test it
$ curl -v \
     -H "Content-Type: application/json" \
     -H "Accept: application/json, text/event-stream" \
     -d '{
           "jsonrpc": "2.0",
           "id": 1,
           "method": "tools/list",
           "params": {}
         }' \
     http://127.0.0.1:8000/mcp
*   Trying 127.0.0.1:8000...
* Connected to 127.0.0.1 (127.0.0.1) port 8000
> POST /mcp HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/8.7.1
> Content-Type: application/json
> Accept: application/json, text/event-stream
> Content-Length: 120
>
* upload completely sent off: 120 bytes
< HTTP/1.1 200 OK
< date: Tue, 22 Jul 2025 02:56:25 GMT
< server: uvicorn
< cache-control: no-cache, no-transform
< connection: keep-alive
< content-type: text/event-stream
< x-accel-buffering: no
< Transfer-Encoding: chunked
<
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[.... long text elided ...]}}

Mock tools

When building agents, it can be helpful to test them against mock versions that do not go against a real cluster, but return realistic values. The module k8stools.mock_tools does just that. The data is a small, hand-maintained cluster modeled on a Minikube instance running the Open Telemetry Demo application: a crash-looping ad service mid-upgrade, a DaemonSet, a CronJob and its Job, a StatefulSet with PVCs, and a few events. When running the MCP server, this may be enabled by using the --mock command line option.

The mock serves a capture — a JSON snapshot of one cluster — rather than a set of per-tool canned answers, so the tools agree with each other: a pod that is not in the capture does not exist for any tool, and one that is has consistent statuses, events, spec and logs. You can snapshot your own cluster the same way — see Capturing and replaying a cluster.

Capturing and replaying a cluster

k8s-capture-state snapshots a live cluster into a single JSON file, and the MCP server replays that file as if it were the cluster. A whole scenario — a crash loop, a full volume, a bad rollout — becomes a fixture you can re-run, commit, or attach to an issue, with no cluster needed to reproduce it.

# Snapshot the current cluster (respects KUBECONFIG)
k8s-capture-state -o incident-1234.json

# Replay it
k8s-mcp-server --state-file incident-1234.json

k8s-capture-state options

usage: k8s-capture-state [-h] [--namespace NS [NS ...]] [-o FILE]
                         [--kubeconfig PATH] [--context NAME] [--no-logs]
                         [--max-log-lines MAX_LOG_LINES] [--no-previous-logs]
                         [--no-redact]
                         [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]

options:
  -h, --help            show this help message and exit
  --namespace NS [NS ...]
                        Namespace(s) to capture namespaced resources from
                        [default: all]. Namespaces and nodes are always
                        captured in full.
  -o FILE, --output FILE
                        Output file [default: k8s-state-<timestamp>.json]
  --kubeconfig PATH     Kubeconfig file to capture from [default: KUBECONFIG,
                        then ~/.kube/config]
  --context NAME        Kubeconfig context to capture from [default:
                        K8STOOLS_CONTEXT, then the kubeconfig's current-
                        context]
  --no-logs             Skip container logs
  --max-log-lines MAX_LOG_LINES
                        Log lines to capture per container [default: 1000]
  --no-previous-logs    Skip the previous-instance logs of restarted containers
  --no-redact           Disable secret redaction of captured values (redaction
                        is on by default; can also be disabled with
                        K8STOOLS_REDACT=0)
  --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
                        Log level [default: INFO]

It finishes with a summary of what it got:

$ k8s-capture-state --namespace default -o incident-1234.json
Captured 27 pod(s), 31 container(s).
  logs captured:          31
  previous logs captured: 31
  values redacted:        4
Wrote incident-1234.json (1,435,335 bytes, redacted).

What gets captured

Everything the tools can read, so that every tool answers on replay:

Cluster

context name, API server URL and version, so get_cluster_info answers on replay (not the kubeconfig path, which names a file on the capturing machine)

Cluster-wide

namespaces, nodes

Per namespace

deployments, replica sets, services, statefulsets, daemonsets, cronjobs, jobs, PVCs, events, and each workload's change history (get_workload_history's result, so no env values are written)

ConfigMaps

summary and full contents, so get_configmap works too

Per pod

summary, labels, container statuses, spec, and per-container logs

A cluster is selected exactly as for the MCP server (see Selecting a cluster), and a selection that cannot be loaded fails the capture.

--namespace restricts only the namespaced resources; namespaces and nodes are always captured in full so the cluster still makes sense.

Logs dominate the file size — expect a few MB for a few dozen pods (the 27-pod capture above was 1.4 MB with only 50 lines per container; a 38-pod one at 200 lines was 3.3 MB). Use --max-log-lines to trade size against history, or --no-logs for a structure-only snapshot. Captures compress about 10x, and can be written and read gzipped — see Compression, and what to check in.

Compression, and what to check in

A name ending in .gz is written gzipped, and captures are read back compressed or not either way — detection is by content, so a capture still loads after being renamed:

k8s-capture-state -o incident-1234.json.gz     # 3.3 MB -> 364 KB
k8s-mcp-server --state-file incident-1234.json.gz

For a fixture you check into git, use plain .json anyway. Git already stores blobs compressed, so you do not pay the uncompressed size — and it deltas successive versions of a text file against each other, which it cannot do for a gzip blob. Measured on two captures of the same 38-pod cluster:

first commit

updating the fixture later

.json (3.3 MB)

404 KB

+61 KB

.json.gz (364 KB)

388 KB

+358 KB

The two cost about the same once, but every re-capture of a .gz adds a whole fresh blob, so the repo grows roughly 6x faster. Captures are also indented rather than compact for the same reason — it gives git something to delta. This is also why you probably do not need git-lfs here: LFS stores every version whole, which gives up exactly the delta compression that makes these files cheap.

Reach for .gz when the file travels on its own — attached to an issue, dropped in object storage, or simply too large to keep expanded in a working tree.

Previous-instance logs

The capture includes the previous-instance logs of every restarted container — what get_logs_for_pod_and_container(..., previous=True) returns. For a crash-looping container the current instance's logs are usually empty or post-restart, and the stack trace or OOM message that explains the crash lives in the previous instance, so a capture without them would be missing the evidence that matters most.

They roughly double the log payload for a cluster where a lot is restarting — which is exactly the cluster worth capturing. --no-previous-logs skips them. The summary reports how many could not be read (the previous instance may have been garbage-collected), because a crash-loop capture that lost them looks identical to one that never had any.

Previous-instance log semantics

previous=True asks the kubelet for the container's last terminated instance. Three of its behaviors read as bugs and are not, and all three show up in captures as well as in live queries:

  • In CrashLoopBackOff, both calls return the same text. There is no running instance during the backoff, so the kubelet serves the most recently terminated one for previous=False too. Check get_pod_container_statuses before concluding the flag was ignored.

  • A restart between two calls shifts the window. The instance that was current becomes the previous one, so a container crash-looping every few seconds can return byte-identical output for both. Compare the log timestamps, not the flag.

  • A reclaimed log file returns 200, not an error, with the body unable to retrieve container logs for <container-id>. It is a successful call whose content is an error message.

Only the single most recent terminated instance is retained; there is no way to reach further back than one.

Replay clock

Every age in a capture is stored relative to the moment of capture, so the intervals between resources survive replay exactly: a deployment aged 8 days whose newest replica set is aged 7h34m still says "upgraded 7h34m ago" whenever it is replayed.

By default those ages advance in real time from when the server starts, which is what makes an interactive session feel like a live cluster. For an automated test suite pass --state-time frozen:

k8s-mcp-server --state-file incident-1234.json --state-time frozen

which pins every age at its captured value, so repeated runs are identical and a long session cannot see ages drift between its first tool call and its last. (--state-time requires --state-file; it is rejected rather than ignored, since a suite that believed it had frozen the clock and had not would be flaky with no visible cause.)

Absolute times are replayed the same way: every timestamp a tool returns is moved so the moment of capture becomes the moment the server started. A container killed 5 minutes before the capture reads as killed 5 minutes before server start, and get_cluster_info's captured_at is that start time, not the date in the file, so the agent sees one consistent clock. Log line timestamps (the kubelet's prefix) are moved too, so since_seconds works on a capture of any age; timestamps an application writes inside its own log messages are left as recorded. The file's own capture date is in the server's startup log.

Replaying from Python

For a test suite, skip the server and load the capture directly. MockState has the same query methods as the tools:

from pathlib import Path
from k8stools.mock_state import MockState

state = MockState.from_file(Path("incident-1234.json"), frozen=True)

pods = state.get_pod_summaries("default")
logs = state.get_logs_for_pod_and_container("ad-647b4947cc-s5mpm", "default",
                                            previous=True)

Or point the mock_tools module at it, so anything already calling k8stools.mock_tools serves your capture instead of the built-in one:

from k8stools import mock_tools

mock_tools.load_mock_state(Path("incident-1234.json"), frozen=True)
agent = Agent(model="openai:gpt-4.1", tools=mock_tools.TOOLS)

Captures and secrets

k8s-capture-state applies the same redaction pass as the MCP server, on by default, opt out with --no-redact or K8STOOLS_REDACT=0. This matters because a capture file is far more portable than cluster access — it gets committed to git, attached to issues, and passed around long after anyone remembers which cluster it came from. Redaction is one-way: replaying a redacted capture with --no-redact restores nothing, so a scenario that genuinely needs real values has to be re-captured.

Secret redaction

Some read-only resources can carry secret-shaped values even though they are not Kubernetes Secret objects — ConfigMap data and the env blocks in a pod spec are the common cases. When you run the k8stools MCP server directly against an agent (with no wrapping service to scrub output), those values would otherwise flow straight into the model's context.

To prevent that, the MCP server applies a redaction pass to every tool's output. It is on by default and can be disabled with --no-redact or by setting K8STOOLS_REDACT=0. Redaction matches two ways, replacing each match with a visible [REDACTED] marker so the agent can tell "hidden" from "absent". We never provide a reader for Kubernetes Secret objects.

  1. By value shape — AWS access keys, JWT / bearer tokens, PEM private-key blocks.

  2. By key / env-var name — the name contains key, secret, token, password, passwd, credential or cred as a whole word. Names are split on separators and camelCase, so AWS_SECRET_ACCESS_KEY, apiKey and x-auth-token all match while VALKEY_ADDR does not.

    A field named exactly key is exempt: in the Kubernetes API that is always a map entry, a taint, a label selector or a projected-volume item, never a credential. This matters more than it sounds — on a real 38-pod cluster it was 130 of 139 redactions, none of them secrets: toleration keys such as node.kubernetes.io/not-ready, the filename ca.crt, and secretKeyRef.key. That last is worth stating plainly: a reference to a secret is not a secret. The value lives in the Secret object and is resolved by the kubelet, never appearing in tool output, so redacting the pointer hides which key feeds an env var and protects nothing. The exemption does not apply to env-var names, where a variable someone named KEY plausibly does hold one.

Where redaction applies

How the tools are used

Redacted?

k8s-mcp-server

Yes, on by default; --no-redact or K8STOOLS_REDACT=0 turns it off

k8s-capture-state

Yes: the capture applies the pass itself before writing the file

k8s_tools.TOOLS / mock_tools.TOOLS given to an agent framework, or composed into your own MCP server

No. Wrap each function: [wrap_with_redaction(fn) for fn in TOOLS]

Calling a tool function directly in Python

No. Apply the pass to the result: redact_object(result) returns (redacted, count)

wrap_with_redaction keeps each function's name, signature and docstring, so a framework that builds tool schemas from them (pydantic-ai, MCP) sees the same tool. Redaction catches known token shapes and values under sensitive names. It cannot catch everything: a credential embedded in a longer string, such as a connection URL or a --password= flag, can get through (see #12).

Available Tools

21 tools
get_cluster_infoA

Report which Kubernetes cluster these tools are bound to. Call this first when more than one cluster could be involved, and before drawing conclusions that depend on which cluster the data came from.

The binding is made once (at server startup, or on the first tool call) and
shared by every tool, so all tools answer from this cluster.

Parameters
----------
None
    This function does not take any parameters.

Returns
-------
ClusterInfo
    An object with the following fields:

    source : str
        "kubeconfig" (bound through a kubeconfig context), "in-cluster" (the
        service account of the pod the server runs in), or "capture" (a
        recorded snapshot of a cluster being replayed, not a live cluster).
    context : Optional[str]
        The kubeconfig context name. None for in-cluster config, and for a
        capture that did not record one.
    server : Optional[str]
        URL of the cluster's API server.
    kubeconfig : Optional[str]
        Path of the kubeconfig file (or ``:``-separated list of files) the
        binding was read from. None unless source is "kubeconfig".
    server_version : Optional[str]
        Kubernetes version reported by the API server, e.g. "v1.31.2". None if
        the server could not be reached, or the capture did not record it.
    captured_at : Optional[datetime.datetime]
        For a capture, when it was taken; every age and timestamp the tools
        return is relative to that moment. None for a live cluster.

Raises
------
K8sConfigError
    If no cluster configuration can be loaded.
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
serverNo
sourceYes
contextNo
kubeconfigNo
captured_atNo
server_versionNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it discloses that the binding happens once at startup or first call and is shared across all tools (a non-obvious global state semantic), enumerates the meaning of each source value including the non-live "capture" case, and documents the K8sConfigError failure mode.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening purpose and usage guidance are well front-loaded, but the numpydoc Returns section is long and largely duplicates the existing output schema. Roughly half the text restates structured data rather than adding value, hurting conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter introspection tool, everything needed is present: purpose, when to call it, the global binding semantics, error conditions, and the special meaning of capture timestamps. Output schema coverage means field duplication is harmless rather than a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so baseline is 4. The description confirms "This function does not take any parameters," which matches the empty input schema, but there is no parameter meaning to add.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Report which Kubernetes cluster these tools are bound to." This is a metadata/introspection tool that is clearly distinct from all sibling data-retrieval tools (pods, nodes, logs), so an agent can place it instantly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger condition: call first "when more than one cluster could be involved, and before drawing conclusions that depend on which cluster the data came from." No alternative tool exists for this purpose, so naming a sibling alternative is unnecessary; the when-to-use directive is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_configmapA

Retrieves the full contents of a single ConfigMap.

WARNING: ConfigMaps can contain secret-shaped values (e.g. credentials stored
as plain config). When this tool is served through the k8stools MCP server, the
output passes through a redaction step by default (see the `redaction` module
and the server's `--no-redact` flag). Callers using this function directly get
the raw values and are responsible for their own redaction.

Parameters
----------
name : str
    Name of the ConfigMap.
namespace : str, optional
    Namespace of the ConfigMap (default is "default").

Returns
-------
dict[str, Any]
    A dictionary describing the ConfigMap with the following keys:

    name : str
        Name of the ConfigMap.
    namespace : str
        Namespace of the ConfigMap.
    data : dict[str, str]
        The string key/value data map (empty dict if none).
    binary_data_keys : list[str]
        Names of any binary keys. The binary values themselves are not
        returned.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the ConfigMap is not found or the API call fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
namespaceNodefault

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it warns that ConfigMaps may hold secret-shaped plaintext values, explains that the MCP server redacts output by default but direct callers get raw values, and documents two failure modes (K8sConfigError, K8sApiError) plus the fact that binary values are withheld.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Sectioned layout (warning, parameters, returns, raises) is well front-loaded, but the Returns block restates a return shape that an output schema already defines, and the redaction paragraph is lengthy. Some sentences do not earn their place for an agent that can read the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read tool this covers everything an agent needs: purpose, parameter meanings, redaction caveat, error conditions, and note that binary values are omitted. The existence of an output schema makes the extra Returns detail a bonus rather than a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: name is 'Name of the ConfigMap' and namespace is optional with default 'default'. It covers both parameters adequately, though it adds no syntax constraints beyond the schema types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'Retrieves the full contents of a single ConfigMap.' The word 'single' and 'full contents' clearly distinguishes it from the sibling get_configmap_summaries, which lists many.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the single-vs-summaries naming, but the description never explicitly says when to reach for this tool over get_configmap_summaries or get_pod_spec. The redaction paragraph explains deployment context, not selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_configmap_summariesA

Retrieves a list of ConfigMapSummary objects for ConfigMaps in a given namespace or all namespaces, similar to kubectl get configmaps.

Note that this returns only summary metadata (not the ConfigMap contents); use
`get_configmap` to read the actual data map.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list ConfigMaps from. If None, lists ConfigMaps from
    all namespaces.

Returns
-------
list of ConfigMapSummary
    A list of ConfigMapSummary objects, each with the following fields:

    name : str
        Name of the ConfigMap.
    namespace : str
        Namespace in which the ConfigMap lives.
    key_count : int
        Number of keys across `data` and `binary_data`.
    data_size : int
        Approximate total size in bytes of all values.
    age : datetime.timedelta
        Age of the ConfigMap (current time minus creation timestamp).

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list ConfigMaps fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden. It discloses return fields and specific error cases (K8sConfigError, K8sApiError), which is valuable. However, it does not explicitly state read-only status, side-effect absence, or permission requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with headers and front-loads the core purpose. However, the detailed Returns section is largely redundant because an output schema already exists, so some sentences do not earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool, the description covers purpose, parameter semantics, return summary, and error cases. Nothing essential is missing for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage for the single optional 'namespace' parameter. The description fully compensates by explaining its type, default value, and exact semantics (None lists all namespaces).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Retrieves') and resource ('ConfigMapSummary objects'), and explicitly distinguishes itself from the sibling get_configmap by noting it returns summary metadata only. The kubectl analogy adds further clarity about scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative tool (get_configmap) for reading actual data and clarifies when to use this one (summary metadata only). It also explains the namespace behavior, leaving no ambiguity about usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_cronjob_summariesA

Retrieves a list of CronJobSummary objects for CronJobs in a given namespace or all namespaces, similar to kubectl get cronjobs.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list CronJobs from. If None, lists from all
    namespaces.

Returns
-------
list of CronJobSummary
    A list of CronJobSummary objects, each with the following fields:

    name : str
        Name of the CronJob.
    namespace : str
        Namespace of the CronJob.
    schedule : str
        Cron schedule expression.
    suspend : bool
        Whether the CronJob is suspended.
    active : int
        Number of currently active (running) jobs.
    last_schedule_time : Optional[datetime.timedelta]
        Time since the CronJob was last scheduled (None if never).
    last_successful_time : Optional[datetime.timedelta]
        Time since the CronJob last completed successfully (None if never).
    age : datetime.timedelta
        Age of the CronJob (current time minus creation timestamp).
    containers : list[ContainerTemplateSummary]
        The job pod template's containers, each with name, image, and literal
        environment values.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list CronJobs fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does reasonably well: it enumerates the exact returned fields and documents two error conditions (K8sConfigError on API init failure, K8sApiError on list failure). It doesn't explicitly confirm read-only semantics or note pagination/rate limits, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence front-loads the purpose effectively and the sectioned layout (Parameters/Returns/Raises) is easy to scan. However, the long field-by-field Returns enumeration partially duplicates the output schema, adding bulk that earns less than its space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the field listing is somewhat redundant, but the description still adds value via the kubectl analogy, error conditions, and namespace semantics. For a simple single-parameter read tool this is essentially complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it defines the single parameter's type, default (None), and the semantic consequence of None ('lists from all namespaces'). That is complete for a one-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Retrieves a list of CronJobSummary objects for CronJobs') and gives a concrete analogy ('similar to kubectl get cronjobs'). This clearly distinguishes it from sibling tools like get_logs_for_cronjob and get_job_summaries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the namespace parameter behavior (None lists all namespaces), which implies usage, but it never states when to prefer this tool over alternatives such as get_job_summaries or get_logs_for_cronjob. No explicit when/when-not guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_daemonset_summariesA

Retrieves a list of DaemonSetSummary objects for DaemonSets in a given namespace or all namespaces, similar to kubectl get daemonsets -o wide.

A DaemonSet runs one pod on each node it targets; its pods are named
"<daemonset>-<5 characters>" and have `owner` "DaemonSet/<daemonset>" in
`get_pod_summaries`. A shortfall between the counts below ("desired 5,
ready 4") is often the first sign of a problem with a particular node.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list DaemonSets from. If None, lists from all
    namespaces.

Returns
-------
list of DaemonSetSummary
    A list of DaemonSetSummary objects, each with the following fields:

    name : str
        Name of the DaemonSet.
    namespace : str
        Namespace in which the DaemonSet runs.
    desired_number_scheduled : int
        Number of nodes that should be running the DaemonSet's pod - the
        actual number of nodes it targets.
    current_number_scheduled : int
        Number of nodes running at least one of its pods that should.
    number_ready : int
        Number of nodes whose pod is ready.
    updated_number_scheduled : int
        Number of nodes running a pod from the current pod template. Less
        than desired means a rollout is in progress or stuck.
    number_available : int
        Number of nodes whose pod has been ready for at least minReadySeconds.
    number_misscheduled : int
        Number of nodes running its pod that should not be.
    node_selector : dict[str, str]
        The pod template's nodeSelector (kubectl's NODE SELECTOR column).
        Many DaemonSets choose their nodes with node affinity and
        tolerations instead, which this does not show, so an empty selector
        does not mean "every node"; desired_number_scheduled is the count.
    update_strategy : str
        Update strategy type ("RollingUpdate" or "OnDelete").
    images : list[str]
        Container images of the current pod template, in container order. A
        pod running a different image is from an earlier revision.
    age : datetime.timedelta
        Age of the DaemonSet (current time minus creation timestamp).

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list DaemonSets fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden, and it does so well: it declares the read-only retrieval nature, documents both raised errors (K8sConfigError, K8sApiError), and adds a non-obvious caveat that node_selector being empty does not mean 'every node' because affinity/tolerations are not shown. It omits RBAC/permission and pagination behavior, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose, then a semantic aside, then Parameters/Returns/Raises sections, so key information comes first. It is lengthy and the entire Returns field list partially duplicates the existing output schema, but most field notes (e.g., node_selector caveat, updated_number_scheduled meaning a stalled rollout) add interpretation that earns their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a single optional parameter, an existing output schema, and no annotations, the description covers everything an agent needs: purpose, kubectl analogy, parameter semantics, error conditions, and diagnostic interpretation of the counts. Nothing required for a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and there is one parameter, yet the description fully defines it: 'The specific namespace to list DaemonSets from. If None, lists from all namespaces.' This completely compensates for the undocumented schema and disambiguates the null default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Retrieves a list of DaemonSetSummary objects for DaemonSets') with scope ('in a given namespace or all namespaces'), and grounds it against a familiar reference ('similar to kubectl get daemonsets -o wide'). This clearly distinguishes it from siblings like get_deployment_summaries, get_statefulset_summaries, and get_replicaset_summaries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Offers diagnostic context ('a shortfall between the counts below is often the first sign of a problem with a particular node') and cross-references get_pod_summaries for pod naming/owner, which implies usage. However, it never explicitly states when to choose this over the sibling summary tools or any when-not conditions, so selection is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_deployment_summariesA
Retrieves a list of DeploymentSummary objects for deployments in a given namespace or all namespaces.
Similar to `kubectl get deployements`.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list deployments from. If None, lists deployments from all namespaces.

Returns
-------
list of DeploymentSummary
    A list of DeploymentSummary objects, each providing a summary of a deployment's status with the following fields:

    name : str
        Name of the deployment.
    namespace : str
        Namespace in which the deployment is running.
    total_replicas : int
        Total number of replicas desired for this deployment.
    ready_replicas : int
        Number of replicas that are currently ready.
    up_to_date_replicas : int
        Number of replicas that are up to date.
    available_replicas : int
        Number of replicas that are available.
    age : datetime.timedelta
        Age of the deployment (current time minus creation timestamp).

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list deployments fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does so well by disclosing behavioral traits: it specifies the kubectl-like behavior, lists potential errors (K8sConfigError, K8sApiError), and describes the return format. It does not mention rate limits or auth needs, but covers key operational aspects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded: the first sentence states the purpose clearly, followed by organized sections (Parameters, Returns, Raises) that add necessary detail without redundancy. Every sentence earns its place by providing essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (1 parameter, no annotations, but with an output schema), the description is complete enough. It explains the purpose, parameter usage, return values in detail (though the output schema covers this, the description adds clarity), and error conditions, leaving no significant gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the input schema, which has 0% coverage. It explains the 'namespace' parameter's purpose (to list deployments from a specific namespace or all namespaces), default behavior (None for all namespaces), and semantics, compensating fully for the schema's lack of descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'retrieves' and resource 'list of DeploymentSummary objects for deployments', specifying it works 'in a given namespace or all namespaces'. It distinguishes from siblings by focusing on deployments rather than pods, nodes, services, etc., and explicitly mentions the kubectl analogy for context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool (to get deployment summaries) and implies when not to use it (e.g., for pod or service summaries, as indicated by sibling tool names). However, it does not explicitly name alternatives or state exclusions, such as when to use get_pod_summaries instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_eventsA

Lists cluster- or namespace-wide events with optional server-side filtering.

Unlike `get_pod_events` (which is scoped to a single named pod), this supports
the sweep queries common in capacity/storage runbooks — e.g. all "Evicted"
events, or all "FailedScheduling" events — where the affected pods often have no
stable name to look up. Note Kubernetes expires an event record about an hour
(by default) after its last occurrence, so events that stopped repeating
earlier than that are gone.

Parameters
----------
namespace : Optional[str], default=None
    Namespace to list events from. If None, lists across all namespaces.
reason : Optional[str], default=None
    If set, only return events with this reason (e.g. "Evicted",
    "FailedScheduling", "BackOff").
involved_kind : Optional[str], default=None
    If set, only return events whose involved object is of this kind (e.g.
    "Pod", "Node", "PersistentVolumeClaim").
involved_name : Optional[str], default=None
    If set, only return events whose involved object has this name.
event_type : Optional[str], default=None
    If set, only return events of this type ("Normal" or "Warning").

Returns
-------
list of EventSummary
    Matching events. Each EventSummary has the following fields:

    last_seen : Optional[datetime.timedelta]
        Time since the event was last seen (if available).
    first_seen : Optional[datetime.timedelta]
        Time since the first occurrence combined into this record (if
        available).
    count : Optional[int]
        How many occurrences Kubernetes combined into this record: repeats
        of the same event on the same object are counted in one record
        rather than listed separately. The count covers first_seen to
        last_seen, not the object's lifetime - a record that stops repeating
        expires (after 1h by default), and a later repeat starts a new one.
        For a crash-looping container, count the "Created" or "Started"
        events to get restarts. "BackOff" is emitted repeatedly while the
        kubelet waits to restart, so its count is several times the number
        of restarts. count divided by (first_seen - last_seen) is the
        average rate over that window, not the current back-off.

        A record can lag behind what it counts. By default the kubelet
        writes at most one event update per object and event type
        ("Normal" or "Warning") every 5 minutes, once a burst of 25 is
        used up; occurrences in between are counted but only written with
        the next update, which then jumps by several at once. So count and
        last_seen describe the most recent *written* occurrence and can
        trail reality by several occurrences and tens of minutes. They lag
        together, so the rate above still holds, but last_seen is not the
        time of the last restart: for that, use the container status
        (last_state.finished_at, state.started_at from
        get_pod_container_statuses) or PodSummary.last_restart, which come
        from the kubelet's status rather than from events. "Pulled",
        "Created" and "Started" share one write budget, so their counts for
        the same restarts can differ by a few; don't compare counts across
        reasons.
    type : str
        Type of the event ("Normal" or "Warning").
    reason : str
        Reason for the event.
    object : str
        The involved object as "Kind/name" (or just the name when the kind is
        unavailable).
    message : str
        Message describing the event.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list events fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNo
namespaceNo
event_typeNo
involved_kindNo
involved_nameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden and does so: it discloses the ~1h event expiry, that `count` aggregates repeats from first_seen to last_seen, the kubelet's 5-minute/25-burst write budget that makes counts and last_seen lag reality, and which alternative sources (get_pod_container_statuses, PodSummary.last_restart) give true restart times. It also documents the raised errors (K8sConfigError, K8sApiError).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and sibling disambiguation, then clearly sectioned Parameters/Returns/Raises. It is long and partly redundant — the 1-hour expiry is stated twice and the count/rate caveat is re-explained across two paragraphs — and much of the Returns prose restates an output schema that already exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-optional-param query tool with no annotations, the definition covers everything needed: filtering semantics, retention limits, aggregation/lag pitfalls, error modes, and pointers to better sources for restart timing. Nothing an agent must know before calling it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for all five parameters: types, defaults (None meaning all-namespaces), and concrete accepted values/examples for reason, involved_kind and event_type ("Normal"/"Warning"). This adds meaning entirely absent from the bare anyOf/null schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (lists), resource (cluster- or namespace-wide events) and scope (server-side filtering), then explicitly contrasts with the sibling `get_pod_events` and names the workload types (capacity/storage runbooks) it serves. An agent can pick between the two event tools without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use this vs. `get_pod_events` ("scoped to a single named pod"), gives concrete trigger scenarios (all Evicted / FailedScheduling events where pods have no stable name), and adds a retention caveat (events expire ~1h after last occurrence) that affects whether the query is even worth running.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_job_summariesA

Retrieves a list of JobSummary objects for Jobs in a given namespace or all namespaces, similar to kubectl get jobs.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list Jobs from. If None, lists from all namespaces.

Returns
-------
list of JobSummary
    A list of JobSummary objects, each with the following fields:

    name : str
        Name of the Job.
    namespace : str
        Namespace of the Job.
    owner : Optional[str]
        Name of the owning CronJob, if this Job was created by one.
    active : int
        Number of actively running pods.
    succeeded : int
        Number of pods that completed successfully.
    failed : int
        Number of pods that terminated in failure.
    start_time : Optional[datetime.timedelta]
        Time since the Job started (None if not started).
    completion_time : Optional[datetime.timedelta]
        Time since the Job completed (None if not complete).
    conditions : list[str]
        Status condition types currently True (e.g. ["Complete"], ["Failed"]).
    age : datetime.timedelta
        Age of the Job (current time minus creation timestamp).
    containers : list[ContainerTemplateSummary]
        The Job pod template's containers, each with name, image, and literal
        environment values.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list Jobs fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it delivers by documenting two failure modes (K8sConfigError, K8sApiError) and a rich return structure. It does not explicitly state read-only safety or auth/permission requirements, but the 'Retrieves a list' framing and error disclosure give strong behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The sectioned layout is easy to parse, but the extensive Returns block enumerates every field of JobSummary even though an output schema already exists, which is largely redundant bulk. The parameter and Raises sections earn their place; the return field listing does not.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool, the definition covers the parameter, the return type, and error conditions. Since an output schema exists, the field-level Returns detail is not strictly necessary, but the Raises section adds genuinely useful completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate entirely, and it does: namespace is documented as Optional[str], default=None, and the None case is explicitly defined as 'lists from all namespaces'. That is exactly the semantics an agent needs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Retrieves) and resource (JobSummary objects for Jobs), and anchors it with the familiar 'kubectl get jobs' analogy. This clearly separates it from siblings like get_cronjob_summaries and get_logs_for_job.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The kubectl analogy implies the general use case, and the namespace parameter implies scoping, but there is no explicit when-to-use-this-vs-alternatives guidance or statement of exclusions (e.g., versus get_logs_for_job). Usage is implied rather than directed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_logs_for_cronjobA

Retrieves logs from the most-recent run of a CronJob.

Finds the newest Job owned by the CronJob, then returns the logs of that Job's
most-recently-created pod. Removes the need to manually locate the right
short-lived pod for a CronJob's last tick.

Parameters
----------
cronjob_name : str
    Name of the CronJob.
namespace : str, optional
    Namespace of the CronJob (default is "default").
container_name : str, optional
    Container within the pod. If None, defaults to the first container.
tail : int, optional
    Number of lines from the end of the log (default: last 1000).
since_seconds : int, optional
    If set, only return logs newer than this many seconds.
previous : bool, default False
    If True, return logs from the previous terminated container instance.
    See `get_logs_for_pod_and_container` for the cases - CrashLoopBackOff, a
    restart racing the call, a reclaimed log file - where that legitimately
    returns the same text as `previous=False`, or a 200 whose body is an
    error message.

Returns
-------
str, optional
    Log content, or None if the CronJob has no jobs/pods yet.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
tailNo
previousNo
namespaceNodefault
cronjob_nameYes
since_secondsNo
container_nameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses the job/pod resolution algorithm, the None return when no jobs/pods exist, and the error types raised (K8sConfigError, K8sApiError). It does not mention required RBAC permissions or rate limits, leaving a minor gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded with the core behavior in the opening sentence, then structured parameter/returns/raises sections. Slightly verbose but every section carries information; no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter read tool with no annotations and 0% schema coverage, the description supplies the resolution logic, all parameter semantics, return behavior, and failure modes. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must fully compensate, and it does: every one of the six parameters is documented with type, default, and behavioral meaning (e.g., tail default of last 1000 lines, previous semantics and its CrashLoopBackOff caveats).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (retrieves logs from a CronJob's most-recent run) and explains the resolution path (newest owned Job, then its most-recent pod). This clearly distinguishes it from siblings like get_logs_for_job and get_logs_for_pod_and_container.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the value proposition ('removes the need to manually locate the right short-lived pod') and cross-references get_logs_for_pod_and_container for the `previous` edge cases. However, it does not explicitly say when to prefer this over get_logs_for_job or get_logs_for_pod_and_container.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_logs_for_jobA

Retrieves logs from the most-recently-created pod of a Job.

Job pods are short-lived, so this convenience finds the newest pod belonging to
the Job (via its `job-name` label) and returns its logs, saving the caller from
listing pods and sorting by creation time.

Parameters
----------
job_name : str
    Name of the Job.
namespace : str, optional
    Namespace of the Job (default is "default").
container_name : str, optional
    Container within the pod. If None, defaults to the first container.
tail : int, optional
    Number of lines from the end of the log (default: last 1000).
since_seconds : int, optional
    If set, only return logs newer than this many seconds.
previous : bool, default False
    If True, return logs from the previous terminated container instance.
    See `get_logs_for_pod_and_container` for the cases - CrashLoopBackOff, a
    restart racing the call, a reclaimed log file - where that legitimately
    returns the same text as `previous=False`, or a 200 whose body is an
    error message.

Returns
-------
str, optional
    Log content, or None if the Job has no pods.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
tailNo
job_nameYes
previousNo
namespaceNodefault
since_secondsNo
container_nameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so: it discloses the pod-selection mechanism (newest pod via the `job-name` label), the None return when a Job has no pods, the CrashLoopBackOff/restart/log-reclaim cases where `previous=True` can return identical text or a 200 with an error body, and the two error types raised.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-sentence purpose and the rationale for the convenience wrapper before the reference sections. The Parameters section is long but earns its place given 0% schema coverage; the `previous` note is a single dense sentence that could be tightened but is not wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter read tool with no annotations, the description covers selection logic, defaults, edge cases, error behavior, and even return values (None vs str). Nothing an agent needs in order to call it correctly or interpret the result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and it does for all six parameters: default namespace 'default', first-container fallback for container_name, tail default of the last 1000 lines (a runtime default the schema's null does not convey), since_seconds semantics, and the meaning of `previous`.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Retrieves logs') plus the precise scope ('most-recently-created pod of a Job'). That scope immediately distinguishes it from the generic get_logs_for_pod_and_container and from get_logs_for_cronjob, so an agent can route without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the situation that motivates it ('Job pods are short-lived') and the alternative approach it saves the caller from ('listing pods and sorting by creation time'). It also points to the sibling get_logs_for_pod_and_container for the `previous` edge cases, though it never states an explicit 'do not use this when...' exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_logs_for_pod_and_containerA
Retrieves logs from a Kubernetes pod and container.

Args:
    pod_name (str): The name of the pod.
    namespace (str): The namespace of the pod.
    container_name (str, optional): The name of the container within the pod.
                                    If None, defaults to the first container.
    tail (int, optional): Number of lines to return from the end of the log.
                          If None, defaults to the last 1000 lines. Pass a
                          larger value to retrieve more history, or a small
                          value for a bounded recent slice.
    since_seconds (int, optional): If set, only return logs newer than this
                          many seconds. Combines with `tail` (both limits
                          apply).
    previous (bool, default False): If True, return logs from the *previous*
                          terminated instance of the container instead of the
                          current one. Indispensable for crashloop analysis,
                          where the current instance's logs are empty or
                          post-restart. Fails if there is no previous instance.

                          Three Kubernetes behaviors make `previous=True`
                          look as though it were ignored or broken; none is a
                          fault in this tool, and all are worth knowing before
                          drawing a conclusion from the output:

                          * While a container sits in CrashLoopBackOff there
                            is no running instance, so the kubelet serves the
                            most recently *terminated* one for `previous=False`
                            as well - both calls then return the same text.
                            Check the container's state with
                            `get_pod_container_statuses` before concluding the
                            flag had no effect.
                          * A restart between two calls shifts the window: the
                            instance that was current becomes the previous one,
                            so a container crash-looping every few seconds can
                            legitimately return identical bytes for both.
                            Compare the log timestamps, not just the flag.
                          * Once the previous instance's log file has been
                            reclaimed, the API answers 200 with the text
                            `unable to retrieve container logs for <id>` -
                            a successful call whose body is an error message,
                            not a raised error.

                          Only the single most recent terminated instance is
                          retained by the kubelet; there is no way to reach
                          further back than one.

Returns:
    str: The log content as text, with real newlines. An empty string if the
         container has produced no log output (never None).

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to fetch logs fails or an unexpected error occurs.
ParametersJSON Schema
NameRequiredDescriptionDefault
tailNo
pod_nameYes
previousNo
namespaceNodefault
since_secondsNo
container_nameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden and meets it: it documents the CrashLoopBackOff overlap, the restart window shift, the 200-with-error-text-body case, and the one-instance retention limit. It also lists raised errors and return-type guarantees (empty string, never None).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose, args, and returns are front-loaded and clean, but the previous parameter's three-bullet caveat block is long and sits inside the args section rather than after it. The operational warnings are valuable yet could be tightened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read tool with six parameters and an output schema, the description covers return semantics, error paths, and the subtlest failure modes comprehensively. It omits no critical invocation detail, though the oversized previous section slightly dilutes the overall completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden, and it does: it defines every parameter, documents defaults (first container, last 1000 lines, namespace default not restated), and explains how tail and since_seconds combine. The detailed previous semantics go well beyond a simple enumeration.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ("Retrieves logs from a Kubernetes pod and container") that unambiguously distinguishes it from siblings such as get_logs_for_job and get_logs_for_cronjob, which target different workload artifacts. The agent can select this tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong conditional guidance for the previous flag (use it for crashloop analysis, fall back to get_pod_container_statuses if results look identical), which is explicit when-to-use context. It doesn't name the job/cronjob log siblings or explain when to prefer them, but the pod/container scope makes the boundary reasonably clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_namespacesA

Return a summary of the namespaces for this Kubernetes cluster, similar to that returned by kubectl get namespace.

Parameters
----------
None
    This function does not take any parameters.

Returns
-------
list of NamespaceSummary
    List of namespace summary objects. Each NamespaceSummary has the following fields:

    name : str
        Name of the namespace.
    status : str
        Status phase of the namespace.
    age : datetime.timedelta
        Age of the namespace (current time minus creation timestamp).
Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list namespaces fails.
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden and does well by disclosing the return format (list of NamespaceSummary objects with specific fields), error conditions (K8sConfigError, K8sApiError), and behavioral aspects like what happens on API failure. It doesn't mention rate limits, authentication needs, or pagination behavior, but provides substantial operational context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (Parameters, Returns, Raises), front-loaded with the core purpose, and every sentence earns its place by providing essential information about behavior, output format, and error conditions without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has no parameters, has an output schema (implied by the detailed Returns section), and no annotations, the description provides complete context: clear purpose, detailed return format with field descriptions, specific error conditions, and operational behavior. Nothing essential appears missing for this type of read-only listing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0 parameters and 100% schema coverage, the baseline would be 4. The description explicitly states 'This function does not take any parameters' in the Parameters section, which adds clarity beyond what the empty schema alone conveys, confirming this is a parameterless operation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verb ('Return') and resource ('summary of the namespaces for this Kubernetes cluster'), and distinguishes it from siblings by specifying it returns namespace summaries rather than deployments, pods, services, etc. The kubectl analogy provides helpful context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context through the kubectl analogy and by specifying what it returns (namespace summaries), but doesn't explicitly state when to use this tool versus alternatives like get_pod_summaries or get_service_summaries. No explicit when-not-to-use guidance or prerequisite information is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_node_summariesA

Return a summary of the nodes for this Kubernetes cluster, similar to that returned by kubectl get nodes -o wide.

Parameters
----------
None
    This function does not take any parameters.

Returns
-------
list of NodeSummary
    List of node summary objects. Each NodeSummary has the following fields:

    name : str
        Name of the node.
    status : str
        Status of the node (Ready, NotReady, etc.).
    roles : list[str]
        List of roles for the node (e.g., ['control-plane', 'master']).
    age : datetime.timedelta
        Age of the node (current time minus creation timestamp).
    version : str
        Kubernetes version running on the node.
    internal_ip : Optional[str]
        Internal IP address of the node.
    external_ip : Optional[str]
        External IP address of the node (if available).
    os_image : Optional[str]
        Operating system image running on the node.
    kernel_version : Optional[str]
        Kernel version of the node.
    container_runtime : Optional[str]
        Container runtime version on the node.
    capacity : dict[str, str]
        Total capacity of the node keyed by resource name (e.g. "cpu",
        "memory", "ephemeral-storage", "pods"). Empty if unavailable.
    allocatable : dict[str, str]
        Resources allocatable to pods (capacity minus system-reserved),
        keyed by resource name. Empty if unavailable.
    conditions : dict[str, str]
        Node conditions keyed by type with their status, e.g.
        {"Ready": "True", "MemoryPressure": "False", "DiskPressure": "False"}.
    conditions_since : dict[str, datetime.timedelta]
        For each condition in `conditions`, the time since its status last
        changed (the API's lastTransitionTime), e.g. how long the node has
        been Ready, or how long ago a MemoryPressure episode ended. A
        condition with no transition time is left out.

        It changes only when the status does. A node or kubelet restart in
        which the node comes back Ready without having been marked NotReady
        or Unknown in between does not reset it: on a minikube cluster
        stopped and started together with its control plane, Ready stayed
        "True since the node was created" across a reboot. So a long Ready
        age does not mean the node or its pods have been running that long,
        and a short one can come from a brief NotReady flap rather than a
        reboot. To date a node's last start, use its "Starting" or
        "Rebooted" events (`get_events(involved_kind="Node")`, while they
        last - events usually expire after an hour), or the `started_at` of
        containers that start with the node, such as kube-proxy and the
        kube-system control-plane containers (`get_pod_container_statuses`).
    taints : list[str]
        Taints on the node formatted as "key=value:effect" (value omitted
        when empty).
    labels : dict[str, str]
        All labels on the node. Useful for identifying node pool / instance
        type and spotting version skew across pools.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list nodes fails.
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it names the errors raised (K8sConfigError, K8sApiError), documents the exact shape and optionality of returned fields, and discloses the non-obvious `conditions_since` semantics (it tracks lastTransitionTime, not node uptime, and survives a clean reboot). It stops short of stating read-only/idempotency explicitly, so not a perfect 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loading is good (purpose first, then structured sections), but the Returns block is a long field-by-field enumeration of return values that is redundant with the existing output schema, so it does not fully earn its space. The conditions_since caveat is verbose but conveys real, non-schema information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, read-only, zero-parameter list tool with an output schema, the description covers errors, edge-case semantics, and alternative tools, so an agent has enough to call it correctly. The only shortfall is composition: it re-documents return values the output schema already owns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, and the description explicitly says so ('This function does not take any parameters'), matching an empty schema. Baseline for a no-param tool is 4; nothing is ambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (return a summary) and resource (nodes for this Kubernetes cluster), reinforced by the concrete analogy `kubectl get nodes -o wide`. The resource noun cleanly separates it from the sibling `get_pod_summaries`, `get_service_summaries`, etc., without needing to name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit statement of when to prefer this tool over siblings or what preconditions apply; usage is only implied by the purpose. It does route the agent elsewhere for one specific sub-question (dating a node's last start via `get_events` and `get_pod_container_statuses`), which is genuinely useful, but that is a narrow slice of guidance rather than a general when/when-not.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pod_container_statusesA
Get the status for all containers in a specified Kubernetes pod.

Parameters
----------
pod_name : str
    Name of the pod to retrieve container statuses for.
namespace : str, optional
    Namespace of the pod (default is "default").

Returns
-------
list of ContainerStatus
    List of container status objects for the specified pod. Each ContainerStatus has the following fields:

    pod_name : str
        Name of the pod.
    namespace : str
        Namespace of the pod.
    container_name : str
        Name of the container.
    image : str
        Image name.
    ready : bool
        Whether the container is currently passing its readiness check.
        The value will change as readiness probes keep executing.
    restart_count : int
        Number of times the container has restarted.
    started : Optional[bool]
        Started indicates whether the container has finished its postStart
        lifecycle hook and passed its startup probe.
    stop_signal : Optional[str]
        Stop signal for the container.
    state : Optional[ContainerState]
        Current state of the container.
    last_state : Optional[ContainerState]
        Last state of the container. When Terminated, ``ran_for`` is how long
        that instance ran (``finished_at - started_at``). It is not the
        restart interval, which adds the back-off named in a Waiting
        ``state``'s message, and it is not how much time the container's log
        covers: a process can stop logging long before it is killed.
    volume_mounts : list[VolumeMountStatus]
        Status of volume mounts for the container
    resource_requests : dict[str, str]
        Describes the minimum amount of compute resources required. If Requests
        is omitted for a container, it defaults to Limits if that is explicitly specified,
        otherwise to an implementation-defined value. Requests cannot exceed Limits. 
    resource_limits : dict[str, str]
        Describes the maximum amount of compute resources allowed.
    allocated_resources : dict[str, str]
        Compute resources allocated for this container by the node.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to read the pod fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
pod_nameYes
namespaceNodefault

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It documents the return structure and error conditions (K8sConfigError, K8sApiError), but it doesn't disclose any behavioral traits like whether it waits for readiness, pagination, rate limits, or freshness. It provides some error context but lacks operational behavior detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for parameters, returns, and raises, but it is quite long—especially the detailed return field descriptions. While each sentence earns its place for a tool without an output schema, the verbose nested field explanations could be trimmed or moved to the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that there is no output schema, the description thoroughly documents the return type and its fields, which is essential. It also covers error cases. However, it omits usage context relative to other tools and doesn't mention any behavioral aspects like whether the status is cached or live.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does by fully documenting both parameters: pod_name (required) and namespace (optional with default 'default'). This adds significant value beyond the schema, though it could mention constraints like namespace format.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource ('Get the status for all containers in a specified Kubernetes pod'), which clearly distinguishes it from siblings like get_pod_summaries or get_pod_spec. However, it doesn't explicitly contrast with those siblings, leaving some differentiation implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies you should use this tool to get container statuses for a pod, but it provides no explicit when-to-use guidance, no alternatives, and no exclusions. It doesn't say when to choose it over get_pod_summaries or get_logs_for_pod_and_container.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pod_eventsA
Get events for a specific Kubernetes pod. This is equivalent to the kubectl command:
`kubectl get events -n NAMESPACE --field-selector involvedObject.name=POD_NAME,involvedObject.kind=Pod`

Parameters
----------
pod_name : str
    Name of the pod to retrieve events for.
namespace : str, optional
    Namespace of the pod (default is "default").

Returns
-------
list of EventSummary
    List of events associated with the specified pod. Each EventSummary has the following fields:

    last_seen : Optional[datetime.timedelta]
        Time since the most recent occurrence of the event (if available).
    first_seen : Optional[datetime.timedelta]
        Time since the first occurrence combined into this record (if
        available).
    count : Optional[int]
        How many occurrences Kubernetes combined into this record: repeats
        of the same event on the same object are counted in one record
        rather than listed separately. The count covers first_seen to
        last_seen, not the object's lifetime - a record that stops repeating
        expires (after 1h by default), and a later repeat starts a new one.
        For a crash-looping container, count the "Created" or "Started"
        events to get restarts. "BackOff" is emitted repeatedly while the
        kubelet waits to restart, so its count is several times the number
        of restarts. count divided by (first_seen - last_seen) is the
        average rate over that window, not the current back-off.

        A record can lag behind what it counts. By default the kubelet
        writes at most one event update per object and event type
        ("Normal" or "Warning") every 5 minutes, once a burst of 25 is
        used up; occurrences in between are counted but only written with
        the next update, which then jumps by several at once. So count and
        last_seen describe the most recent *written* occurrence and can
        trail reality by several occurrences and tens of minutes. They lag
        together, so the rate above still holds, but last_seen is not the
        time of the last restart: for that, use the container status
        (last_state.finished_at, state.started_at from
        get_pod_container_statuses) or PodSummary.last_restart, which come
        from the kubelet's status rather than from events. "Pulled",
        "Created" and "Started" share one write budget, so their counts for
        the same restarts can differ by a few; don't compare counts across
        reasons.
    type : str
        Type of the event.
    reason : str
        Reason for the event.
    object : str
        The object this event applies to.
    message : str
        Message describing the event.
Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list events fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
pod_nameYes
namespaceNodefault

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so unusually well: it discloses event coalescing, the 1h record expiry, the kubelet's one-write-per-5-minutes / burst-of-25 budget, the resulting lag between count and reality, and the two error types raised. These are exactly the behavioral traits an agent cannot infer from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded and the kubectl equivalent is a nice compression, but the count/last_seen explanation runs to several paragraphs of dense prose. Since an output schema exists for EventSummary, much of the field-by-field Returns block is duplicative, and the signal-to-length ratio suffers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read tool with error semantics and an output schema, the description covers purpose, parameters, failure modes, and the non-obvious caveats about event counting and lag. An agent has everything needed to call it and to interpret the results correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: pod_name is identified as the required target pod and namespace as optional with a 'default' default. It stops short of format constraints (e.g. naming rules, cross-namespace behavior).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Get events for a specific Kubernetes pod') and anchors it to an exact kubectl equivalent, which removes any ambiguity about scope. It also implicitly separates itself from get_events and get_pod_container_statuses by naming the latter for restart-time needs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives one concrete routing rule: for the time of the last restart, use the container status / get_pod_container_statuses rather than event last_seen. However it never states when to prefer this tool over the sibling get_events, nor any preconditions beyond the Raises section.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pod_specA
Retrieves the spec for a given pod in a specific namespace.

Args:
    pod_name (str): The name of the pod.
    namespace (str): The namespace the pod belongs to (defaults to "default").

Returns
-------
dict[str, Any]
    The pod's spec object, containing its desired state. It is converted
    from a V1PodSpec to a dictionary. Key fields include:

    containers : list of kubernetes.client.V1Container
        List of containers belonging to the pod. Each container defines its image,
        ports, environment variables, resource requests/limits, etc.
    init_containers : list of kubernetes.client.V1Container, optional
        List of initialization containers belonging to the pod.
    volumes : list of kubernetes.client.V1Volume, optional
        List of volumes mounted in the pod and the sources available for
        the containers.
    node_selector : dict, optional
        A selector which must be true for the pod to fit on a node.
        Keys and values are strings.
    restart_policy : str
        Restart policy for all containers within the pod.
        Common values are "Always", "OnFailure", "Never".
    service_account_name : str, optional
        Service account name in the namespace that the pod will use to
        access the Kubernetes API.
    dns_policy : str
        DNS policy for the pod. Common values are "ClusterFirst", "Default".
    priority_class_name : str, optional
        If specified, indicates the pod's priority_class via its name.
    node_name : str, optional
        NodeName is a request to schedule this pod onto a specific node.

Raises
------
K8SConfigError
    If unable to initialize the K8S API
K8sApiError
    If the pod is not found, configuration fails, or any other API error occurs.
ParametersJSON Schema
NameRequiredDescriptionDefault
pod_nameYes
namespaceNodefault

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does so well by detailing return values, key fields, and error conditions (K8SConfigError, K8sApiError). It explains that the spec is converted from V1PodSpec to a dictionary and lists common values for fields like restart_policy and dns_policy, adding valuable behavioral context beyond basic functionality.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded with the core purpose, followed by structured sections for Args, Returns, and Raises. Every sentence adds value, such as detailing return fields and errors, though the Returns section is somewhat lengthy but necessary for clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (retrieving detailed pod specs) and the presence of an output schema (implied by the detailed Returns section), the description is complete enough. It covers purpose, parameters, return semantics with key fields, and error handling, providing all necessary context for an AI agent to use the tool effectively without redundancy.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, which it does by explaining both parameters: pod_name as 'the name of the pod' and namespace as 'the namespace the pod belongs to (defaults to "default")'. This adds clear meaning beyond the schema's titles, though it doesn't elaborate on format constraints or examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'retrieves' and the resource 'spec for a given pod in a specific namespace', making the purpose specific and unambiguous. It distinguishes this tool from siblings like get_pod_summaries or get_pod_events by focusing on the detailed spec object rather than summaries or events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by specifying it retrieves a pod's spec, but it does not explicitly state when to use this tool versus alternatives like get_pod_summaries for high-level info or get_pod_container_statuses for container states. No explicit exclusions or prerequisites are provided, leaving usage context inferred rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pod_summariesA
Retrieves a list of PodSummary objects for pods in a given namespace or all namespaces.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list pods from. If None, lists pods from all namespaces.

Returns
-------
list of PodSummary
    A list of PodSummary objects, each providing a summary of a pod's status with the following fields:

    name : str
        Name of the pod.
    namespace : str
        Namespace in which the pod is running.
    total_containers : int
        Total number of containers in the pod.
    ready_containers : int
        Number of containers currently in ready state.
    restarts : int
        Total number of restarts for all containers in the pod.
    last_restart : Optional[datetime.timedelta]
        Time since a container of this pod last terminated - the most
        recent last_state.finished_at across its containers - or None if
        none has. For a container waiting in CrashLoopBackOff this is its
        last crash, not a restart: it has not been started again yet. Taken
        from the kubelet's status, so it is current, unlike event records.
    age : datetime.timedelta
        Age of the pod (current time minus creation timestamp).
    ip : Optional[str]
        Pod IP address (None if not assigned).
    node : Optional[str]
        Name of the node where the pod is running (None if not scheduled).
    owner : Optional[str]
        The pod's controlling owner, as "Kind/name" - the object that
        created and manages it, e.g. "DaemonSet/otel-collector-agent",
        "StatefulSet/valkey-cart", "Job/backup-29318400". None for a bare
        pod nobody manages. This is the direct owner only: a Deployment's
        pods are owned by one of its replica sets ("ReplicaSet/ad-7d9f8c6b5"),
        whose `owner_deployment` (`get_replicaset_summaries`) names the
        Deployment; likewise a Job's `owner` names its CronJob. Static
        (mirror) pods such as the control plane's report "Node/<node name>".
        Group pods into workloads by this field rather than by stripping
        name suffixes.
Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list pods fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden, and it does substantially: it enumerates the two exception types (K8sConfigError, K8sApiError), warns that last_restart for a CrashLoopBackOff container is the last crash rather than a restart, and notes the value comes from kubelet status so it is current unlike event records. It omits auth/permission requirements and any rate-limit or pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, but the bulk of the text is a re-documentation of the PodSummary return fields, an output schema already exists. The owner and last_restart explanations earn their place; much of the plain field enumeration does not. Size is disproportionate for a one-parameter read tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists, the description need not restate returns, yet it covers parameter meaning, error conditions, and a subtle data-semantics trap (last_restart on CrashLoopBackOff). What is missing is any permission/context requirement, but overall an agent has enough to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single parameter has no description in the schema, but the description explicitly defines it: 'The specific namespace to list pods from. If None, lists pods from all namespaces.' That fully compensates for the gap by explaining the null default's meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Retrieves a list of PodSummary objects for pods in a given namespace or all namespaces.' An agent can tell this is a listing/summary tool. It does not explicitly distinguish itself from nearby siblings such as get_pod_container_statuses, get_pod_spec, or get_pod_events, though the field list implicitly differentiates the scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the description ('list pods from all namespaces') but there is no explicit statement of when to prefer this over get_pod_container_statuses or get_pod_spec. The one genuine routing hint is the cross-reference that a ReplicaSet's owner_deployment can be named via get_replicaset_summaries, which helps group pods into workloads.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pvc_summariesA

Retrieves a list of PVCSummary objects for PersistentVolumeClaims in a given namespace or all namespaces, similar to kubectl get pvc.

For each PVC, this also resolves which pods currently mount it (by scanning pod
volumes in the same scope), which is useful for spotting orphaned PVCs — claims
with an empty `mounted_by` and no owning pod.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list PVCs from. If None, lists from all namespaces.

Returns
-------
list of PVCSummary
    A list of PVCSummary objects, each with the following fields:

    name : str
        Name of the PVC.
    namespace : str
        Namespace of the PVC.
    status : str
        Phase of the PVC ("Bound", "Pending", or "Lost").
    volume_name : Optional[str]
        Name of the bound PersistentVolume (None if unbound).
    capacity : Optional[str]
        Storage capacity (e.g. "10Gi"); falls back to the requested size when
        the claim is not yet bound.
    access_modes : list[str]
        Access modes (e.g. ["ReadWriteOnce"]).
    storage_class : Optional[str]
        StorageClass backing the claim.
    mounted_by : list[str]
        Names of pods (in the same scope) currently mounting this PVC. Empty
        for orphaned/unmounted claims.
    age : datetime.timedelta
        Age of the PVC (current time minus creation timestamp).

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list PVCs fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden and does so well: it discloses that the tool scans pod volumes in the same scope to compute `mounted_by`, that this is scoped to the same namespace/all-namespaces selection, and it enumerates the error conditions (K8sConfigError, K8sApiError). Read-only nature is implied by 'retrieves' but not explicitly asserted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded: purpose and the mounted_by behavior come first, followed by parameters, returns, and raises. The Returns section is lengthy field-by-field documentation that partially duplicates the output schema, which is a minor redundancy rather than a structural flaw.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool, the description covers purpose, the non-obvious mounted_by resolution behavior, the parameter's full semantics, and error modes. Nothing an agent needs to select or invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must fully compensate for the single `namespace` parameter, and it does: it explains the type (Optional[str]), the default (None), and precisely what None means (list from all namespaces). No ambiguity remains for the caller.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (retrieves), resource (PVCSummary objects for PVCs), and scope (namespace or all namespaces), anchored to a familiar analogue ('similar to `kubectl get pvc`'). It further differentiates itself from siblings like get_pod_summaries by explaining it also resolves which pods mount each PVC.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear use case — spotting orphaned PVCs via empty `mounted_by` — and frames the tool as the PVC equivalent of `kubectl get pvc`. It does not, however, name an alternative sibling or state when NOT to use it, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_replicaset_summariesA
Retrieves a list of ReplicaSetSummary objects, similar to `kubectl get replicasets`
but including each replica set's deployment revision and container images.

A Deployment's replica sets are its revision history: every update to a Deployment
creates a new replica set carrying that revision's pod template, and older replica
sets are retained (scaled to zero). Listing them for one deployment therefore shows
when it last changed and what its image was at each revision - which is how you
answer "did something change recently?" without access to deployment tooling or
version control.

Results are grouped by namespace and owning deployment, and within each
deployment sorted by revision, oldest first. So when filtered to a single
deployment, the last entry is that deployment's current revision.

Replica sets with no revision (see `revision` below) sort *first*, ahead of
revision 1, rather than being dropped. They have no place in any deployment's
history, so they are listed before it rather than appended to it. In practice
they are only visible in an unfiltered listing: a replica set without a
revision has no owning deployment either, so passing `deployment` filters them
out, and the "last entry is the current revision" guarantee above is unaffected.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list replica sets from. If None, lists from all namespaces.
deployment : Optional[str], default=None
    If given, return only replica sets owned by this deployment. This is the common
    case: one deployment's revision history.

Returns
-------
list of ReplicaSetSummary
    A list of ReplicaSetSummary objects with the following fields:

    name : str
        Name of the replica set.
    namespace : str
        Namespace in which the replica set is defined.
    owner_deployment : Optional[str]
        Name of the Deployment that owns this replica set, or None if it is
        standalone (not managed by a Deployment).
    revision : Optional[int]
        The deployment revision this replica set represents, taken from the
        `deployment.kubernetes.io/revision` annotation. None when that
        annotation is absent, which means no Deployment created this replica
        set - only the Deployment controller writes it. A hand-written replica
        set, or one created by another controller, therefore has no revision
        (and no `owner_deployment`), and appears in neither `kubectl rollout
        history` nor a `deployment`-filtered call here. Also None if the
        annotation is present but not an integer.
    desired_replicas : int
        Replicas desired for this replica set. Old revisions are scaled to 0.
    current_replicas : int
        Replicas currently running.
    ready_replicas : int
        Replicas currently ready.
    images : list[str]
        Container images in this revision's pod template, in container order.
        Comparing this across revisions shows what an upgrade changed.
    age : datetime.timedelta
        Age of the replica set (current time minus creation timestamp). For the
        newest revision this is how long ago the deployment last changed.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list replica sets fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo
deploymentNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it discloses grouping/sort order, the edge case that revision-less replica sets sort first, what None revision means, and the error types raised (K8sConfigError, K8sApiError). It omits permission/auth requirements and pagination/limit behavior, so it is not fully complete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, but the definition is long and the Returns section largely re-lists fields already present in the output schema, making it partly redundant. The edge-case paragraph on revision-less replica sets, while informative, is verbose relative to its value. Structure is good; size is not tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists, the description need not explain return values, yet it still adds interpretation (comparing images across revisions, age of newest revision as time-since-change). Combined with documented errors, sorting, and edge cases, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: both namespace and deployment are documented with types, defaults, and semantics ('If given, return only replica sets owned by this deployment. This is the common case'). It even explains the interaction between deployment filtering and revision-less replica sets.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Retrieves a list of ReplicaSetSummary objects') and immediately distinguishes itself from siblings with 'similar to kubectl get replicasets but including each replica set's deployment revision and container images.' An agent can tell it apart from get_deployment_summaries or get_pod_summaries without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use context ('how you answer "did something change recently?"') and identifies the common invocation case ('filtered to a single deployment ... one deployment's revision history'). It does not name alternative sibling tools or explicit exclusions, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_service_summariesA

Retrieves a list of ServiceSummary objects for services in a given namespace or all namespaces. Similar to kubectl get services.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list services from. If None, lists services from all namespaces.

Returns
-------
list of ServiceSummary
    A list of ServiceSummary objects, each providing a summary of a service's status with the following fields:

    name : str
        Name of the service.
    namespace : str
        Namespace in which the service is running.
    type : str
        Type of the service (ClusterIP, NodePort, LoadBalancer, ExternalName).
    cluster_ip : Optional[str]
        Cluster IP address assigned to the service (None for ExternalName services).
    external_ip : Optional[str]
        External IP address if applicable (for LoadBalancer services).
    ports : list[PortInfo]
        List of ports (and their protocols) exposed by the service.
    age : datetime.timedelta
        Age of the service (current time minus creation timestamp).
    selector : dict[str, str]
        The label selector the service uses to choose backing pods. Empty
        for services without a selector (e.g. ExternalName, or manually
        managed Endpoints).
    labels : dict[str, str]
        Labels on the service object.
    annotations : dict[str, str]
        Annotations on the service object.

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list services fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and mostly succeeds: it discloses the read-only nature ('Retrieves'), the two failure modes (K8sConfigError on API init, K8sApiError on list failure), and non-obvious semantics such as cluster_ip being None for ExternalName services and selector being empty for selectorless services.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence is front-loaded and efficient, but the bulk of the text is an exhaustive field-by-field enumeration of the return object, which duplicates what the output schema already provides. That block is the majority of the description and does not earn its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a simple single-parameter list operation and the description covers scope, the one parameter, error conditions, and edge-case field semantics. It is complete, though it spends effort re-documenting return fields that the output schema already carries.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it names the single parameter, marks it optional with default None, and explains the behavioral consequence of None (list across all namespaces) that the schema alone cannot convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Retrieves a list of ServiceSummary objects for services') and scopes it precisely to a namespace or all namespaces. The 'kubectl get services' analogy and the ServiceSummary naming make it trivially distinguishable from siblings like get_node_summaries or get_pod_summaries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the scope statement (list services in one namespace or all), but there is no explicit when-to-use/when-not guidance and no named alternative among the many *_summaries siblings. An agent can infer intent, but nothing routes it away from this tool when another would be better.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_statefulset_summariesA

Retrieves a list of StatefulSetSummary objects for StatefulSets in a given namespace or all namespaces, similar to kubectl get statefulsets.

Parameters
----------
namespace : Optional[str], default=None
    The specific namespace to list StatefulSets from. If None, lists from all
    namespaces.

Returns
-------
list of StatefulSetSummary
    A list of StatefulSetSummary objects, each with the following fields:

    name : str
        Name of the StatefulSet.
    namespace : str
        Namespace in which the StatefulSet runs.
    total_replicas : int
        Desired number of replicas.
    ready_replicas : int
        Number of replicas currently ready.
    current_replicas : int
        Number of replicas created by the current revision.
    update_strategy : str
        Update strategy type (e.g. "RollingUpdate", "OnDelete").
    service_name : Optional[str]
        Name of the governing (headless) service.
    age : datetime.timedelta
        Age of the StatefulSet (current time minus creation timestamp).

Raises
------
K8sConfigError
    If unable to initialize the K8S API.
K8sApiError
    If the API call to list StatefulSets fails.
ParametersJSON Schema
NameRequiredDescriptionDefault
namespaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and largely meets it: 'Retrieves' signals a read-only operation, and the Raises section names K8sConfigError and K8sApiError, telling the agent about init and API failure modes. It stops short of discussing pagination or large-cluster behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded and clear, but the description enumerates every field of StatefulSetSummary in a Returns block even though an output schema already exists, making it longer than necessary. The Raises block is useful; the field listing is largely redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter read tool, the description covers purpose, parameter semantics, and error modes adequately. Given that a return schema exists, the extra field enumeration is redundant rather than a completeness gap, so only minor context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: it explains that namespace is optional and that None means listing from all namespaces. That is exactly the semantic an agent needs, though it adds nothing about format or validation of the value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Retrieves) and resource (StatefulSetSummary objects for StatefulSets), and scopes it to a namespace or all namespaces. The kubectl analogy and the resource-specific name distinguish it clearly from siblings like get_deployment_summaries and get_replicaset_summaries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied via 'in a given namespace or all namespaces' and the kubectl comparison, so an agent can infer this is a read/list operation. However, there is no explicit guidance on when to prefer this over sibling summary tools or any exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 18 tool updatesv2.1.0
    • Addedget_cluster_info
    • Addedget_configmap
    • Addedget_configmap_summaries
    • Addedget_cronjob_summaries
    • Addedget_daemonset_summaries
    • Addedget_events
    • Addedget_job_summaries
    • Addedget_logs_for_cronjob
    • Addedget_logs_for_job
    • Changedget_logs_for_pod_and_container3 fields changed
      • addedInput schema / properties / previous
        Added value: +{
        +  "default": false,
        +  "title": "Previous",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / since_seconds
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Since Seconds"
        +}
      • addedInput schema / properties / tail
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Tail"
        +}
    • Changedget_node_summaries7 fields changed
      • changedOutput schema / $defs / NodeSummary / description
        Previous value: -"A summary of a node's status like returned by `kubectl get nodes -o wide`"New value: +"A summary of a node's status like returned by `kubectl get nodes -o wide`,\naugmented with the capacity/allocatable/conditions/taints/labels detail that\n`kubectl describe node` shows (useful for reconstructing a pods-per-node\ncapacity model)."
      • addedOutput schema / $defs / NodeSummary / properties / allocatable
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Allocatable",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / NodeSummary / properties / capacity
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Capacity",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / NodeSummary / properties / conditions
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Conditions",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / NodeSummary / properties / conditions_since
        Added value: +{
        +  "additionalProperties": {
        +    "format": "duration",
        +    "type": "string"
        +  },
        +  "title": "Conditions Since",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / NodeSummary / properties / labels
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Labels",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / NodeSummary / properties / taints
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "title": "Taints",
        +  "type": "array"
        +}
    • Changedget_pod_container_statuses1 field changed
      • addedOutput schema / $defs / ContainerStateTerminated / properties / ran_for
        Added value: +{
        +  "anyOf": [
        +    {
        +      "format": "duration",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Ran For"
        +}
    • Changedget_pod_events2 fields changed
      • addedOutput schema / $defs / EventSummary / properties / count
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Count"
        +}
      • addedOutput schema / $defs / EventSummary / properties / first_seen
        Added value: +{
        +  "anyOf": [
        +    {
        +      "format": "duration",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "First Seen"
        +}
    • Changedget_pod_summaries1 field changed
      • addedOutput schema / $defs / PodSummary / properties / owner
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Owner"
        +}
    • Addedget_pvc_summaries
    • Addedget_replicaset_summaries
    • Changedget_service_summaries4 fields changed
      • changedOutput schema / $defs / ServiceSummary / description
        Previous value: -"A summary of a service's status like returned by `kubectl get servicess`"New value: +"A summary of a service's status like returned by `kubectl get services`,\nplus the pod `selector` and the service's labels/annotations."
      • addedOutput schema / $defs / ServiceSummary / properties / annotations
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Annotations",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / ServiceSummary / properties / labels
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Labels",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / ServiceSummary / properties / selector
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "title": "Selector",
        +  "type": "object"
        +}
    • Addedget_statefulset_summaries
  2. 9 tool updates
    • First observedget_deployment_summaries
    • First observedget_logs_for_pod_and_container
    • First observedget_namespaces
    • First observedget_node_summaries
    • First observedget_pod_container_statuses
    • First observedget_pod_events
    • First observedget_pod_spec
    • First observedget_pod_summaries
    • First observedget_service_summaries

TDQS

A3.9/5.0

Scored across 21 tools

Disambiguation4/5

Most tools target clearly distinct Kubernetes resources and levels (nodes, pods, deployments, services, logs, etc.), and the descriptions explicitly distinguish similar tools. However, get_pod_events overlaps with get_events, which can also filter by involved_kind and involved_name, creating a minor selection ambiguity.

Naming Consistency5/5

All tool names use snake_case with a consistent get_ prefix and resource-oriented nouns. The patterns get_<resource>_summaries, get_<resource>, and get_logs_for_<entity> are predictable and easy to scan.

Tool Count3/5

With 21 tools, the set is on the heavy side for a read-only inspection server. Many resource summaries are justified, but the surface could be consolidated (e.g. pod-specific events and generalized events, or separate job/cronjob log helpers).

Completeness3/5

Core workload inspection is well covered: pods, containers, logs, events, deployments, replica sets, stateful sets, daemon sets, jobs, cronjobs, services, configmaps, PVCs, nodes, and namespaces. Notable gaps remain for common Kubernetes resources such as ingresses, endpoints, secrets, storage classes, persistent volumes, HPA, and RBAC objects.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

  • The Cortex MCP server provides read-only access to real-time engineering context from the Cortex developer portal, allowing AI coding assistants to answer natural language questions about your organization's catalog (microservices, libraries, domains, teams, infrastructure), scorecards (engineering standards and best practices), initiatives (goals and deadlines), and Engineering Intelligence metrics. It includes tools for querying documentation, tracking personal entities, and accessing AI-assisted insights across the entire Cortex ecosystem.

  • The Google GKE MCP server is a managed Model Context Protocol server that provides AI applications with tools to manage Google Kubernetes Engine (GKE) clusters and Kubernetes resources. It exposes a structured, discoverable interface that allows AI agents to interact with GKE and Kubernetes APIs, enabling them to inspect cluster configurations, retrieve Kubernetes resource YAMLs, monitor operations like cluster upgrades, diagnose issues, and optimize costs—all without needing to parse text output or use complex kubectl commands.

  • Provides read access to your GKE and Kubernetes resources.

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A read-only MCP server for Kubernetes that allows querying cluster information and diagnosing issues through natural language interfaces like Claude.
    8
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    A read-only MCP server for inspecting Kubernetes clusters, allowing LLMs to list resources, describe pods, and read logs without mutation.
    5
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Exposes a Kubernetes cluster to MCP-compatible AI clients, enabling read-only and optional write operations on cluster resources like pods, deployments, and namespaces through natural language.
    9
    1
    MIT