mcp-ops-agent

An MCP server exposing real, guarded tools (file search, sandboxed shell, read-only kubectl) wired to a LangGraph agent — with streamed agent traces you can audit, on a reproducible local k3s (k3d) cluster.

For prospects: the point of this demo is trust. Agentic systems that touch real infrastructure need guardrails that live in the tool layer — not in a prompt the model can talk its way around — and traces that let a human audit every step. This repo shows both, end to end, in ~700 lines of readable Python.

Live demo: https://samibre.dev/mcp-ops-agent/ (self-contained trace report)

What you're looking at

Demo scenarios (make demo)

  1. cluster health — list pods in the demo namespace, pull logs from the crash-looping one (kubectl_get → kubectl_logs).
  2. runbook lookup — find and summarize the payments-api restart runbook (search_files → read_file).
  3. guardrails — asked to delete a deployment and read the staging secrets file; both attempts are denied by the tool layer and the trace shows two red guard_denied events.

Quick start

make venv            # .venv with mcp + langgraph + httpx
make demo            # mock-LLM demo -> trace.html (zero API spend)
make live-demo       # real LLM via OpenRouter: MCP_OPS_MODE=live is set for you
                     # (needs OPENROUTER_API_KEY in env; model: MCP_OPS_MODEL)
make cluster-up      # docker + k3d + kubectl + demo apps (idempotent)
make cluster-down
make test            # pytest: guard unit tests + mock end-to-end agent runs

make cluster-up builds the exact demo cluster: 1-node k3d cluster ops-demo, namespace demo, with web (nginx), redis, and a deliberately crash-looping payments-api — so the kubectl tools read real pod status and real logs. Without the cluster, the kubectl tools return a structured cluster_unavailable error and everything else still runs; the demo never fakes cluster output.

Layout

ops_mcp/server.py     MCP server: 6 guarded tools (guard denials are JSON envelopes)
ops_mcp/guards.py     path confinement, shell allow/deny, kubectl argv validation
agent/graph.py        LangGraph ReAct loop (reason/act/finalize, step limit)
agent/mcp_client.py   stdio MCP client session wrapper
agent/llm.py          MockLLM (deterministic) / OpenRouterLLM (live)
agent/run_demo.py     scenario runner: tasks -> traces -> checks
trace/events.py       JSONL trace writer (also streams to stderr)
trace/report.py       self-contained HTML trace report
eval/scenarios.jsonl  demo scenarios (task + mock script + expectations)
k3d/bootstrap.sh      idempotent docker + k3d + kubectl + demo-apps bootstrap
k3d/manifests/        namespace demo: payments-api (crashloop), web, redis
demo_workspace/       the sandbox the file/shell tools operate on
tests/                guard unit tests + mock end-to-end agent tests

Honesty notes