Kubernetes Tools MCP Server
Summary: This is a read-only MCP server for Kubernetes clusters that exposes strongly-typed tools for inspecting cluster state, workloads, workloads' change history, logs, events, storage, and configmaps — the same tools an agent can use for monitoring and root-cause analysis.
Get cluster identity:
get_cluster_info(context, API server URL/version, or whether a capture is being replayed).List namespaces (
get_namespaces) and nodes (get_node_summaries, with capacity, allocatable, conditions, taints, labels).List and inspect pods:
get_pod_summaries(with owner, restarts, last restart),get_pod_container_statuses,get_pod_spec,get_pod_events.Read logs:
get_logs_for_pod_and_container(tail, since_seconds, previous-instance logs), plus convenience wrappersget_logs_for_jobandget_logs_for_cronjob.Inspect Deployments and their revision history:
get_deployment_summaries,get_replicaset_summaries, andget_workload_history(what changed and when, including referenced ConfigMaps/Secrets by name).Inspect StatefulSets, DaemonSets, Jobs, CronJobs, Services, and PVCs (with mounting pods resolved).
Read ConfigMaps: summaries via
get_configmap_summaries, full contents viaget_configmap.Query events cluster- or namespace-wide with server-side filters (
get_events) or per pod (get_pod_events).All tools are read-only (
get/listonly), do not read Kubernetes Secrets, and the MCP server redacts secret-shaped values by default.Can run in mock mode or replay a captured cluster snapshot (
.jsonor.gz) for reproducible testing without a live cluster.Includes debug
print_*counterparts for every tool.
Enables chat interactions with Kubernetes clusters via GitHub Copilot, allowing users to query cluster status, inspect resources, and retrieve logs through natural language conversation supported by custom instruction files.
Provides a collection of Kubernetes tools for querying and monitoring cluster resources, including namespaces, nodes, pods, deployments, and services. Enables agents to retrieve logs, inspect pod specifications, and check container statuses to support monitoring and root cause analysis use cases.
Provides mock tools that can simulate interactions with a Kubernetes cluster running OpenTelemetry Demo, useful for testing agents against realistic but static data without requiring a live cluster.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Kubernetes Tools MCP Servershow me the status of pods in the default namespace"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Kubernetes Tools
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:
There are tools that mimic the output of kubectl commands (e.g.
get_pod_summaries, which is equivalent tokubectl get pods). Strongly-typed Pydantic models are used for the return values of these tools.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.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 isdict[str,Any], but we document the fields in the function's docstring.get_pod_specis 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 k8stoolsVia uv:
uv add k8stoolsThis 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 replayedget_namespaces- get a list of namespaces, likekubectl get namespaceget_node_summaries- get a list of nodes, likekubectl get nodes -o wide(includes capacity/allocatable/conditions/taints/labels)get_pod_summaries- get a list of pods, likekubectl 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 podget_pod_events- return the events for a podget_pod_spec- retrieves the spec for a given podget_logs_for_pod_and_container- retrieves logs from a pod and container (supportstail,since_seconds, andprevious). See Previous-instance log semantics for whenprevious=Truereturns the same text asprevious=False— it is Kubernetes behavior, not a bug.get_deployment_summaries- get a list of deployments, likekubectl get deploymentsget_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, likekubectl get services(includesselector/labels/annotations)get_configmap_summaries- get a list of ConfigMaps, likekubectl get configmapsget_configmap- retrieve the full contents of a single ConfigMapget_statefulset_summaries- get a list of StatefulSets, likekubectl get statefulsetsget_daemonset_summaries- get a list of DaemonSets, likekubectl get daemonsets -o wide(includes node selector and images)get_cronjob_summaries- get a list of CronJobs, likekubectl get cronjobsget_job_summaries- get a list of Jobs, likekubectl get jobsget_logs_for_job- retrieve logs from a Job's most-recent podget_logs_for_cronjob- retrieve logs from a CronJob's most-recent runget_pvc_summaries- get a list of PersistentVolumeClaims, likekubectl 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_namespacesprint_node_summariesprint_pod_summariesprint_pod_container_statusesprint_pod_eventsprint_pod_specprint_deployment_summariesprint_workload_historyprint_service_summariesprint_configmap_summariesprint_configmapprint_statefulset_summariesprint_daemonset_summariesprint_cronjob_summariesprint_job_summariesprint_pvc_summariesprint_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(andmock_tools.TOOLS) return raw values: ConfigMap contents, env values in pod specs, container logs and command-line args, exactly as the API returns them. Onlyk8s-mcp-serverandk8s-capture-stateapply redaction for you. If you handTOOLSto an agent, or build your own MCP server from them, wrap each one withwrap_with_redactionas 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 |
|
|
2nd |
|
|
3rd |
| the file's |
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,--contextorK8STOOLS_CONTEXTis 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-contextdoes not repoint a server that is already running.--kubeconfigand--contextare rejected with--mockor--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 stagingUse 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:
The Python virtual environment is expected to be in
.venvunder the root of your VSCode workspaceYou have installed the k8stools package into your workspace
The environment file
.envrccontains any variables you need defined. In particular, you may need to setKUBECONFIGto point to yourkubectlconfig file, andK8STOOLS_CONTEXTto pin a context (or pass--kubeconfig/--contextinargs).
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.jsonk8s-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 |
Cluster-wide | namespaces, nodes |
Per namespace | deployments, replica sets, services, statefulsets, daemonsets, cronjobs, jobs, PVCs, events, and each workload's change history ( |
ConfigMaps | summary and full contents, so |
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.gzFor 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 | |
| 404 KB | +61 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=Falsetoo. Checkget_pod_container_statusesbefore 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 frozenwhich 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.
By value shape — AWS access keys, JWT / bearer tokens, PEM private-key blocks.
By key / env-var name — the name contains
key,secret,token,password,passwd,credentialorcredas a whole word. Names are split on separators and camelCase, soAWS_SECRET_ACCESS_KEY,apiKeyandx-auth-tokenall match whileVALKEY_ADDRdoes not.A field named exactly
keyis 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 asnode.kubernetes.io/not-ready, the filenameca.crt, andsecretKeyRef.key. That last is worth stating plainly: a reference to a secret is not a secret. The value lives in theSecretobject 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 namedKEYplausibly does hold one.
Where redaction applies
How the tools are used | Redacted? |
| Yes, on by default; |
| Yes: the capture applies the pass itself before writing the file |
| No. Wrap each function: |
Calling a tool function directly in Python | No. Apply the pass to the result: |
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 toolsget_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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| server | No | |
| source | Yes | |
| context | No | |
| kubeconfig | No | |
| captured_at | No | |
| server_version | No |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| namespace | No | default |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | ||
| namespace | No | ||
| event_type | No | ||
| involved_kind | No | ||
| involved_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| tail | No | ||
| previous | No | ||
| namespace | No | default | |
| cronjob_name | Yes | ||
| since_seconds | No | ||
| container_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| tail | No | ||
| job_name | Yes | ||
| previous | No | ||
| namespace | No | default | |
| since_seconds | No | ||
| container_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| tail | No | ||
| pod_name | Yes | ||
| previous | No | ||
| namespace | No | default | |
| since_seconds | No | ||
| container_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| pod_name | Yes | ||
| namespace | No | default |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| pod_name | Yes | ||
| namespace | No | default |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| pod_name | Yes | ||
| namespace | No | default |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No | ||
| deployment | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
18 tool updates
v2.1.0- Added
get_cluster_info - Added
get_configmap - Added
get_configmap_summaries - Added
get_cronjob_summaries - Added
get_daemonset_summaries - Added
get_events - Added
get_job_summaries - Added
get_logs_for_cronjob - Added
get_logs_for_job - Changed
get_logs_for_pod_and_container3 fields changed- added
Input schema / properties / previousAdded value: +{ + "default": false, + "title": "Previous", + "type": "boolean" +} - added
Input schema / properties / since_secondsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Since Seconds" +} - added
Input schema / properties / tailAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tail" +}
- Changed
get_node_summaries7 fields changed- changed
Output schema / $defs / NodeSummary / descriptionPrevious 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)." - added
Output schema / $defs / NodeSummary / properties / allocatableAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Allocatable", + "type": "object" +} - added
Output schema / $defs / NodeSummary / properties / capacityAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Capacity", + "type": "object" +} - added
Output schema / $defs / NodeSummary / properties / conditionsAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Conditions", + "type": "object" +} - added
Output schema / $defs / NodeSummary / properties / conditions_sinceAdded value: +{ + "additionalProperties": { + "format": "duration", + "type": "string" + }, + "title": "Conditions Since", + "type": "object" +} - added
Output schema / $defs / NodeSummary / properties / labelsAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Labels", + "type": "object" +} - added
Output schema / $defs / NodeSummary / properties / taintsAdded value: +{ + "items": { + "type": "string" + }, + "title": "Taints", + "type": "array" +}
- Changed
get_pod_container_statuses1 field changed- added
Output schema / $defs / ContainerStateTerminated / properties / ran_forAdded value: +{ + "anyOf": [ + { + "format": "duration", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ran For" +}
- Changed
get_pod_events2 fields changed- added
Output schema / $defs / EventSummary / properties / countAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" +} - added
Output schema / $defs / EventSummary / properties / first_seenAdded value: +{ + "anyOf": [ + { + "format": "duration", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "First Seen" +}
- Changed
get_pod_summaries1 field changed- added
Output schema / $defs / PodSummary / properties / ownerAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Owner" +}
- Added
get_pvc_summaries - Added
get_replicaset_summaries - Changed
get_service_summaries4 fields changed- changed
Output schema / $defs / ServiceSummary / descriptionPrevious 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." - added
Output schema / $defs / ServiceSummary / properties / annotationsAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Annotations", + "type": "object" +} - added
Output schema / $defs / ServiceSummary / properties / labelsAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Labels", + "type": "object" +} - added
Output schema / $defs / ServiceSummary / properties / selectorAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "title": "Selector", + "type": "object" +}
- Added
get_statefulset_summaries
9 tool updates
- First observed
get_deployment_summaries - First observed
get_logs_for_pod_and_container - First observed
get_namespaces - First observed
get_node_summaries - First observed
get_pod_container_statuses - First observed
get_pod_events - First observed
get_pod_spec - First observed
get_pod_summaries - First observed
get_service_summaries
TDQS
Scored across 21 tools
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.
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.
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).
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
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
- AlicenseNot gradedqualityCmaintenanceA read-only MCP server for Kubernetes that allows querying cluster information and diagnosing issues through natural language interfaces like Claude.8MIT
- AlicenseAqualityBmaintenanceRead-only MCP server for safe Kubernetes inspection, diagnosis, and debugging. Supports Kubernetes core, Helm, Argo Workflows, and Argo CD.2584 npm5MIT
- AlicenseAqualityCmaintenanceA read-only MCP server for inspecting Kubernetes clusters, allowing LLMs to list resources, describe pods, and read logs without mutation.5MIT
- AlicenseAqualityDmaintenanceExposes 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.91MIT