Metadata-Version: 2.4
Name: triagekit-mcp-k8s-triage
Version: 0.1.0
Summary: MCP server that diagnoses unhealthy Kubernetes workloads and finds resource right-sizing candidates using real cluster state - not another kubectl wrapper.
Project-URL: Homepage, https://github.com/Karthick-dev-cart/k8s-triage
Project-URL: Repository, https://github.com/Karthick-dev-cart/k8s-triage
Author: TriageKit Contributors
License-Expression: MIT
License-File: LICENSE
Keywords: devops,incident-response,kubernetes,mcp,model-context-protocol,sre
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.11
Requires-Dist: fastmcp<4.0,>=3.0
Requires-Dist: httpx>=0.27
Requires-Dist: kubernetes>=30.0
Requires-Dist: triagekit-mcp-core<0.2.0,>=0.1.0
Description-Content-Type: text/markdown

# triagekit-mcp-k8s-triage

Part of the [TriageKit](https://github.com/Karthick-dev-cart/triagekit-mcp) MCP server suite.

Diagnoses unhealthy Kubernetes workloads and finds resource right-sizing candidates using
real cluster state — not another `kubectl` wrapper. Existing Kubernetes MCP servers mostly
expose cluster CRUD; this one narrows hard on read-only diagnosis and right-sizing.

## Why

When a pod is crash-looping, an on-call engineer pivots across `kubectl describe`, `kubectl
logs`, rollout history, and (if they're lucky) a Grafana dashboard to figure out what's
actually wrong. This server does that correlation directly: container exit codes and event
reasons get mapped to a ranked failure category, crashes get checked against recent rollouts,
and Prometheus usage history gets compared against resource requests — all as structured
evidence, not another raw JSON dump.

## Tools

| Tool | What it does |
|---|---|
| `diagnose_workload` | Classifies a pod/deployment's failure as OOMKilled, image-pull error, config error, probe failure, or scheduling failure, with evidence |
| `explain_pod_events` | Orders a pod's raw Kubernetes events into a time-sequenced narrative |
| `get_pod_logs_since_last_restart` | Fetches logs from the container's current run only, so an old crash's logs don't drown out the current state |
| `correlate_crashloop_with_recent_changes` | Checks whether a crash lines up with a recent rollout (deploy-related vs. pre-existing bug) |
| `find_resource_right_sizing_candidates` | Compares Prometheus usage history against resource requests, flags over/under-provisioned workloads |
| `cluster_health_summary` | One-shot digest: node pressure, failed/pending pods, PDB violations, HPAs at max |

Also exposes a resource (`k8s://{context}/{namespace}/{workload}/diagnosis`) and a prompt
(`incident_response_runbook`) that walks an LLM through the standard triage sequence.

This server is **read-only** by design — see [SECURITY.md](SECURITY.md). It never creates,
updates, or deletes cluster resources.

## Install

> **Not yet published.** This package itself is not on PyPI yet (alpha, pre-release) - its
> dependency `triagekit-mcp-core` is. Once this package is published, install with `uvx
> triagekit-mcp-k8s-triage` or `pip install triagekit-mcp-k8s-triage`. Until then, build
> locally: `uv build --out-dir dist && uv pip install dist/*.whl`.

## Quick Start (Claude Desktop / Claude Code)

Add to your `mcp.json`:

```json
{
  "mcpServers": {
    "k8s-triage": {
      "command": "uvx",
      "args": ["triagekit-mcp-k8s-triage"],
      "env": {
        "KUBECONFIG": "/path/to/your/kubeconfig"
      }
    }
  }
}
```

## Example prompts

- "Why is the `checkout` deployment in `prod` crash-looping?"
- "Walk me through the incident response runbook for the `payments-api` pod in `staging`."
- "Show me the event timeline for pod `worker-7f9c8d-abc12` in `default`."
- "Give me logs for `api-server` since its last restart, not the old crash logs."
- "Did the last rollout of `checkout` in `prod` cause these crashes?"
- "Is anything in `prod` over- or under-provisioned based on the last 7 days of usage?"
- "Give me a cluster health summary for `prod`."

## Authentication

| Variable | Required for | Notes |
|---|---|---|
| `KUBECONFIG` (native) or `TRIAGEKIT_K8S_TRIAGE_KUBECONFIG_PATH` | All 6 tools | Path to a kubeconfig file. Falls back to the default kubeconfig resolution if unset. |
| `TRIAGEKIT_K8S_TRIAGE_PROMETHEUS_URL` (or native `PROMETHEUS_URL`) | `find_resource_right_sizing_candidates` | Base URL of a Prometheus server scraping `container_cpu_usage_seconds_total` / `container_memory_working_set_bytes` (e.g. via kube-state-metrics + cAdvisor) |

Recommended minimum-privilege RBAC — a read-only `ClusterRole` covering exactly what these
tools use:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: triagekit-k8s-triage-readonly
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log", "events", "nodes"]
    verbs: ["get", "list"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets"]
    verbs: ["get", "list"]
  - apiGroups: ["policy"]
    resources: ["poddisruptionbudgets"]
    verbs: ["get", "list"]
  - apiGroups: ["autoscaling"]
    resources: ["horizontalpodautoscalers"]
    verbs: ["get", "list"]
```

Credentials are only ever read from the environment/kubeconfig at startup — no tool accepts
a credential as a parameter. See [CONTRIBUTING.md](CONTRIBUTING.md) for why.

## Development

```bash
uv sync
uv run pytest -v
uv run ruff check .
uv run pyright
```

Tests never talk to a real cluster — `KubeClient` and `PrometheusClient` are constructed from
mocked API objects/HTTP responses in every test.

## License

[MIT](LICENSE)
