Metadata-Version: 2.5
Name: helm-python-ai
Version: 0.1.0
Summary: AI layer for Helm v4: an MCP server and an autonomous agent built on helm-python-sdk
Project-URL: Homepage, https://github.com/shivamkumar99/helm-python-ai
Project-URL: Python SDK, https://github.com/shivamkumar99/helm-python-sdk
Project-URL: Native library, https://github.com/shivamkumar99/helm-c-sdk
Author: Shivam Kumar
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: agent,ai,claude,devops,helm,kubernetes,llm,mcp,mcp-server,model-context-protocol
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Systems Administration
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: helm-python-sdk>=0.2.2
Provides-Extra: agent
Requires-Dist: anthropic>=0.116; extra == 'agent'
Provides-Extra: all
Requires-Dist: anthropic>=0.116; extra == 'all'
Requires-Dist: anyio>=4; extra == 'all'
Requires-Dist: mcp>=2; extra == 'all'
Provides-Extra: dev
Requires-Dist: anthropic>=0.116; extra == 'dev'
Requires-Dist: anyio>=4; extra == 'dev'
Requires-Dist: mcp>=2; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27; extra == 'dev'
Requires-Dist: opentelemetry-sdk>=1.27; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: observability
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27; extra == 'observability'
Requires-Dist: opentelemetry-sdk>=1.27; extra == 'observability'
Provides-Extra: server
Requires-Dist: anyio>=4; extra == 'server'
Requires-Dist: mcp>=2; extra == 'server'
Description-Content-Type: text/markdown

# helm-python-ai — MCP Server and AI Agent for Helm

[![PyPI](https://img.shields.io/pypi/v/helm-python-ai?logo=pypi&logoColor=white)](https://pypi.org/project/helm-python-ai/)
[![CI](https://github.com/shivamkumar99/helm-python-ai/actions/workflows/ci.yml/badge.svg)](https://github.com/shivamkumar99/helm-python-ai/actions/workflows/ci.yml)
[![License: Apache-2.0](https://img.shields.io/github/license/shivamkumar99/helm-python-ai)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-3776AB?logo=python&logoColor=white)](pyproject.toml)
[![MCP](https://img.shields.io/badge/MCP-server%20%2B%20Apps%20UI-informational)](https://modelcontextprotocol.io)

A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server and an
autonomous AI agent for [Helm](https://helm.sh), the Kubernetes package
manager. Manage Helm releases from Claude Code, Claude Desktop, or any MCP
client — or hand a plain-language mission to an LLM agent that investigates
and operates your deployments — with safety tiers, dry-run defaults, and a
structured audit trail. Built in Python on
[helm-python-sdk](https://github.com/shivamkumar99/helm-python-sdk), which
binds Helm's official Go SDK directly: no `helm` binary, no `kubectl`, no
shelling out.

Two fronts share one safety-tiered tool layer:

| Command | What it is | Runtime |
|---|---|---|
| `helm-ai-mcp` | An MCP server exposing Helm operations to any MCP client (Claude Code, Claude Desktop, …) | [`mcp`](https://pypi.org/project/mcp/) ≥ 2 |
| `helm-ai-agent` | An autonomous agent that investigates and operates releases from a plain-language mission | [`anthropic`](https://pypi.org/project/anthropic/) |

```
helm (Go SDK) → helm-c-sdk (C ABI) → helm-python-sdk (ctypes) → helm-python-ai
                                                                 ├─ helm-ai-mcp    (MCP server)
                                                                 └─ helm-ai-agent  (agent CLI)
```

## Install

```bash
pip install "helm-python-ai[all]"       # both fronts
pip install "helm-python-ai[server]"    # MCP server only
pip install "helm-python-ai[agent]"     # agent only
```

Python ≥ 3.10. The native Helm library ships inside the `helm-python-sdk`
wheel — nothing else to install.

## The MCP server

Register in your MCP client (stdio transport):

```json
{
  "mcpServers": {
    "helm": {
      "command": "helm-ai-mcp"
    }
  }
}
```

Fifteen tools in three tiers:

* **Read (always available):** `helm_list_releases`, `helm_release_status`,
  `helm_release_manifest`, `helm_release_history`, `helm_release_values`,
  `helm_show_chart`, `helm_template_chart`, `helm_lint_chart`,
  `helm_search_repository`, `helm_chart_tags`, `helm_versions`.
* **Write (dry-run by default):** `helm_install_release`,
  `helm_upgrade_release`. They run as server-side dry runs unless called
  with `apply=true` **and** the server environment sets
  `HELM_AI_ALLOW_WRITES=1`.
* **Destructive (double-gated):** `helm_uninstall_release`,
  `helm_rollback_release`. They require `confirm=<release name>` echoed
  exactly **and** `HELM_AI_ALLOW_DESTRUCTIVE=1` in the server environment.

Cluster access uses the standard kubeconfig resolution (`KUBECONFIG`, then
`~/.kube/config`, then in-cluster).

### Live feedback

Long-running tools (installs, upgrades, registry operations) are async and
send MCP **progress notifications** every few seconds while they run —
elapsed time plus the Helm SDK's own live log line ("waiting for
resources…") — so the host can show real activity instead of a call that
looks stuck.

### Releases dashboard (MCP Apps)

`helm_list_releases` ships an [MCP Apps](https://modelcontextprotocol.io)
(SEP-1865) UI: hosts that support the extension — Claude among them —
render the releases as an interactive table (status badges, revisions,
chart versions) directly in the conversation. Hosts without the extension
see the same JSON text as before; nothing is lost.

### Docker

```bash
docker build -t helm-ai-mcp .
```

The build installs helm-python-sdk straight from PyPI — prebuilt wheels
exist for amd64 and arm64, so nothing compiles — on Docker Hardened
Images (digest-pinned, Debian/glibc): a `-dev` stage assembles the venv
and the hardened runtime variant ships it (non-root, no shell, no
installers, near-zero CVEs). Pulling `dhi.io` needs a free Docker
login.

Run it with least privilege (no capabilities, no privilege escalation,
read-only root filesystem, tmpfs scratch space):

```json
{
  "mcpServers": {
    "helm": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--init",
               "--read-only", "--cap-drop", "ALL",
               "--security-opt", "no-new-privileges",
               "--tmpfs", "/tmp", "--tmpfs", "/home/nonroot",
               "-v", "/home/you/.kube/config:/home/nonroot/.kube/config:ro",
               "helm-ai-mcp"]
    }
  }
}
```

`docker-compose.yml` wraps the same image for `docker compose run --rm
helm-mcp` (compose `run`, not `up`: stdio servers are launched by their
client) with the same hardening baked in (`cap_drop: [ALL]`,
`no-new-privileges`, `read_only`, tmpfs mounts, `pids_limit`). Pass
`-e HELM_AI_ALLOW_WRITES=1` / `-e HELM_AI_ALLOW_DESTRUCTIVE=1` only when
you mean it, and prefer mounting a kubeconfig whose RBAC matches the tier
you enabled.

## The agent

```bash
export ANTHROPIC_API_KEY=...   # or an active `ant auth` profile
helm-ai-agent "why is release payments-api failing in namespace prod?"
```

The agent investigates with the read-only tools first, cites evidence
(revisions, values diffs, manifest details), dry-runs any change it
proposes, and asks at the keyboard before applying or destroying anything:

```
  → list_releases {"namespace": "prod"}
  → release_history {"name": "payments-api", "namespace": "prod"}
  → release_values {"name": "payments-api", "revision": 6}

APPROVAL NEEDED: helm upgrade payments-api ./charts/payments (namespace=prod)
Proceed? [y/N]
```

`--yes` auto-approves gated operations (for scripted use, together with the
environment gates); `--model` selects the Claude model (default
`claude-opus-5`); `-v/--verbose` streams the Helm SDK's own log lines to
stderr while operations run.

## Security model

The design follows the
[MCP security best practices](https://modelcontextprotocol.io/docs/2026-07-28/tutorials/security/security_best_practices)
and the OWASP GenAI *Practical Guide for Secure MCP Server Development*
(v1.0, Feb 2026):

* **stdio transport only.** The server is a local child process of its MCP
  client; it never opens a network socket, so the remote-transport attack
  classes (token passthrough, confused deputy, session hijacking) do not
  arise. Do not put it behind an HTTP proxy without adding authentication.
* **Structured, schema-validated invocation.** Every tool has a typed JSON
  schema; values documents are size-capped (1 MB) and must parse to a JSON
  object; release names are validated by Helm's own rules before use.
* **Least privilege by default.** Read tools are ungated; writes are
  dry-run unless explicitly enabled; destructive operations are
  double-gated (exact-name confirmation + a separate environment flag).
  For defense in depth, run the server with a kubeconfig whose RBAC
  matches the tier you enabled — a read-only account when the gates are
  off.
* **Human in the loop.** The agent pauses for keyboard approval on every
  write/destructive operation; over MCP (no terminal), the environment
  gates are the authorization channel and the client's own approval UI
  governs tool use.
* **No secrets in the model's reach.** No tool accepts or returns
  credentials. Registry and cluster credentials come from Helm's and
  Kubernetes' own configuration files; there is no login tool, and error
  messages carry Helm's detail strings, not tracebacks.
* **Untrusted data stays data.** Chart READMEs, notes, values, and
  manifests are cluster-controlled input. The agent's system prompt pins
  them as data-not-instructions; treat MCP tool output the same way in
  your client.
* **Resource limits.** Install/upgrade waits are capped (300 s default)
  and tool output is truncated at 200 K characters with an explicit
  marker, so a wedged rollout or a huge manifest cannot hang the process
  or flood the model's context.
* **Audit trail.** Every allow/refuse decision and every mutating
  operation (with parameters) is logged to stderr, where the MCP host
  captures it — stdout stays reserved for protocol framing.

## Observability & audit

Instrumentation is vendor-neutral OpenTelemetry; no backend is bundled.

* **Tracing** — the MCP SDK emits a span per inbound message
  (`tools/call helm_install_release`, GenAI `execute_tool` attributes,
  W3C trace-context propagation from the caller), and the tool layer adds
  a nested span per operation. The agent wraps each mission in an
  `invoke_agent` span carrying `gen_ai.usage.input_tokens`/
  `output_tokens` and turn count. Export activates only when the standard
  `OTEL_EXPORTER_OTLP_ENDPOINT` is set and the `observability` extra is
  installed (`pip install helm-python-ai[observability]`); point it at
  any OTLP backend (Grafana/Tempo, Jaeger, Langfuse, Datadog, ...).
* **Audit trail** — every tool invocation (with an allowlisted argument
  snapshot; values payloads are recorded as sizes only, never content),
  every safety allow/refuse decision, every MCP request outcome, and each
  agent mission produce structured JSON events on the `helm_ai.audit`
  logger (stderr) and, when `HELM_AI_AUDIT_LOG=/path/file.jsonl` is set,
  an append-only JSONL file. Events carry the active trace/span IDs, so
  audit records and traces cross-reference.
* **Metrics** — `helm_ai.tool.calls` (by tool and outcome) and a
  `helm_ai.tool.duration` histogram flow through the same OTLP pipeline;
  refusal spikes and error rates are the signals worth alerting on.

## Development

```bash
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest            # offline; cluster tests auto-skip
.venv/bin/ruff check src tests
```

## License

Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
