|
| 1 | +# AGENTS.md - KAgent Tools Repository Guide for AI Agents |
| 2 | + |
| 3 | +This document provides instructions and context for AI coding agents working in the kagent-dev/tools repository. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Project Overview |
| 8 | + |
| 9 | +**KAgent Tools** is a Go-based MCP (Model Context Protocol) server that provides Kubernetes and cloud-native management tools. It wraps CLI tools (kubectl, helm, istioctl, cilium, etc.) behind a standardized MCP interface for use by AI agents. |
| 10 | + |
| 11 | +**Architecture:** |
| 12 | + |
| 13 | +``` |
| 14 | +┌────────────────┐ |
| 15 | +│ MCP Client │ (AI agent or kagent runtime) |
| 16 | +└───────┬────────┘ |
| 17 | + │ MCP Protocol (SSE / Streamable HTTP) |
| 18 | + ▼ |
| 19 | +┌────────────────┐ |
| 20 | +│ MCP Server │ cmd/main.go |
| 21 | +│ (mcp-go) │ |
| 22 | +└───────┬────────┘ |
| 23 | + │ Registers tool providers |
| 24 | + ▼ |
| 25 | +┌───────────────────────────────────────────────┐ |
| 26 | +│ Tool Providers (pkg/) │ |
| 27 | +│ k8s │ helm │ istio │ argo │ cilium │ ... │ |
| 28 | +└───────────────────────────────────────────────┘ |
| 29 | + │ CommandBuilder (internal/commands/) |
| 30 | + ▼ |
| 31 | +┌───────────────────────────────────────────────┐ |
| 32 | +│ CLI Binaries │ |
| 33 | +│ kubectl │ helm │ istioctl │ cilium │ argoctl │ |
| 34 | +└───────────────────────────────────────────────┘ |
| 35 | +``` |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## Repository Structure |
| 40 | + |
| 41 | +``` |
| 42 | +tools/ |
| 43 | +├── cmd/ |
| 44 | +│ └── main.go # MCP server entry point, tool registration |
| 45 | +├── pkg/ # Public tool provider packages |
| 46 | +│ ├── argo/ # Argo Rollouts tools |
| 47 | +│ ├── cilium/ # Cilium CNI networking tools |
| 48 | +│ ├── helm/ # Helm package management tools |
| 49 | +│ ├── istio/ # Istio service mesh tools |
| 50 | +│ ├── k8s/ # Kubernetes management tools |
| 51 | +│ │ └── resources/ # K8s resource sub-packages |
| 52 | +│ ├── kubescape/ # Security scanning tools |
| 53 | +│ ├── prometheus/ # Prometheus query tools |
| 54 | +│ └── utils/ # DateTime and general utilities |
| 55 | +├── internal/ # Internal packages |
| 56 | +│ ├── cache/ # Thread-safe TTL cache with metrics |
| 57 | +│ ├── cmd/ # Shell command execution (with mock support) |
| 58 | +│ ├── commands/ # CommandBuilder fluent CLI interface |
| 59 | +│ ├── errors/ # Structured ToolError with context |
| 60 | +│ ├── logger/ # Structured logging |
| 61 | +│ ├── metrics/ # Prometheus metrics definitions |
| 62 | +│ ├── security/ # Input validation (K8s names, URLs, PromQL) |
| 63 | +│ ├── telemetry/ # OpenTelemetry tracing and HTTP middleware |
| 64 | +│ └── version/ # Version info |
| 65 | +├── test/ |
| 66 | +│ └── e2e/ # End-to-end tests (Kind cluster) |
| 67 | +├── scripts/ # Build and setup scripts |
| 68 | +│ └── kind/ # Kind cluster configuration |
| 69 | +├── helm/ # Helm chart for deployment |
| 70 | +├── docs/ # Documentation |
| 71 | +├── .github/workflows/ # CI/CD pipelines |
| 72 | +│ ├── ci.yaml # Build, test, e2e, Helm tests |
| 73 | +│ └── tag.yaml # Release tagging |
| 74 | +├── Makefile # Build orchestration |
| 75 | +├── Dockerfile # Multi-stage build (multi-arch) |
| 76 | +├── go.mod # Go 1.25.6 |
| 77 | +├── DEVELOPMENT.md # Development setup and standards |
| 78 | +└── CONTRIBUTION.md # Contribution process |
| 79 | +``` |
| 80 | + |
| 81 | +--- |
| 82 | + |
| 83 | +## Tool Providers |
| 84 | + |
| 85 | +Each provider lives in `pkg/` and registers MCP tools via a `RegisterTools(server, readOnly)` function: |
| 86 | + |
| 87 | +| Provider | Package | Purpose | |
| 88 | +|----------|---------|---------| |
| 89 | +| **Kubernetes** | `pkg/k8s/` | kubectl get, describe, logs, exec, scale, patch, rollouts | |
| 90 | +| **Helm** | `pkg/helm/` | List, install, upgrade, uninstall releases; repo management | |
| 91 | +| **Istio** | `pkg/istio/` | VirtualService, Gateway, DestinationRule; proxy diagnostics | |
| 92 | +| **Argo Rollouts** | `pkg/argo/` | Rollout promotion, pause/resume, canary/blue-green | |
| 93 | +| **Cilium** | `pkg/cilium/` | BGP routing, cluster connectivity checks | |
| 94 | +| **Kubescape** | `pkg/kubescape/` | Image scanning, configuration compliance | |
| 95 | +| **Prometheus** | `pkg/prometheus/` | PromQL instant/range queries, scrape status | |
| 96 | +| **Utils** | `pkg/utils/` | DateTime formatting/parsing | |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## Build & Test Commands |
| 101 | + |
| 102 | +| Task | Command | |
| 103 | +|------|---------| |
| 104 | +| Build all platforms | `make build` | |
| 105 | +| Format code | `make fmt` | |
| 106 | +| Lint | `make lint` | |
| 107 | +| Lint with auto-fix | `make lint-fix` | |
| 108 | +| Run tests with coverage | `make test` | |
| 109 | +| Run tests only (no build/lint) | `make test-only` | |
| 110 | +| Run E2E tests | `make e2e` | |
| 111 | +| Build Docker image | `make docker-build` | |
| 112 | +| Build multi-arch Docker | `make docker-build-all` | |
| 113 | +| Helm chart tests | `make helm-test` | |
| 114 | +| Install locally | `make tools-install` | |
| 115 | +| Run MCP server locally | `make run` | |
| 116 | +| Check tool version updates | `make check-releases` | |
| 117 | +| Run Jaeger tracing | `make otel-local` | |
| 118 | +| Show all targets | `make help` | |
| 119 | + |
| 120 | +Before submitting changes, run `make fmt && make lint && make test`. |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +## Code Conventions |
| 125 | + |
| 126 | +### Tool Registration Pattern |
| 127 | + |
| 128 | +Each provider implements a `RegisterTools` function that adds MCP tool handlers to the server: |
| 129 | + |
| 130 | +```go |
| 131 | +func RegisterTools(server *server.MCPServer, readOnly bool) { |
| 132 | + server.AddTool(mcp.NewTool("tool_name", ...), handleToolName) |
| 133 | + if !readOnly { |
| 134 | + server.AddTool(mcp.NewTool("write_tool", ...), handleWriteTool) |
| 135 | + } |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +Handler functions are prefixed with `handle` (e.g., `handleKubectlGetEnhanced`, `handleHelmList`). |
| 140 | + |
| 141 | +### CommandBuilder Pattern |
| 142 | + |
| 143 | +Use the fluent `CommandBuilder` interface for executing CLI commands: |
| 144 | + |
| 145 | +```go |
| 146 | +result, err := commands.NewCommandBuilder("helm"). |
| 147 | + WithArgs("list"). |
| 148 | + WithNamespace("default"). |
| 149 | + Execute(ctx) |
| 150 | +``` |
| 151 | + |
| 152 | +Available builders: `KubectlBuilder()`, `HelmBuilder()`, `IstioCtlBuilder()`, `CiliumBuilder()`, `ArgoRolloutsBuilder()`. |
| 153 | + |
| 154 | +### Error Handling |
| 155 | + |
| 156 | +MCP handlers return `(*mcp.CallToolResult, error)`. Always return a `nil` Go error and use the structured `ToolError` type to format errors as MCP results: |
| 157 | + |
| 158 | +```go |
| 159 | +toolErr := errors.NewToolError("get_pods", "kubernetes", errors.ErrValidation). |
| 160 | + WithSuggestion("Check that the namespace exists"). |
| 161 | + WithContext("namespace", namespace) |
| 162 | +return toolErr.ToMCPResult(), nil |
| 163 | +``` |
| 164 | + |
| 165 | +Never panic in tool handlers — always return a `*mcp.CallToolResult`. |
| 166 | + |
| 167 | +### Security Validation |
| 168 | + |
| 169 | +Always validate user inputs using the `internal/security` package before passing them to CLI commands: |
| 170 | + |
| 171 | +- `security.ValidateK8sResourceName()` — Kubernetes resource names |
| 172 | +- `security.ValidateNamespace()` — Kubernetes namespaces |
| 173 | +- `security.ValidateURL()` — HTTP URLs |
| 174 | +- `security.ValidatePromQLQuery()` — PromQL syntax |
| 175 | +- `security.ValidateCommandInput()` — General input sanitization |
| 176 | + |
| 177 | +### Caching |
| 178 | + |
| 179 | +The `internal/cache` package provides a thread-safe generic `Cache[T]` with TTL: |
| 180 | + |
| 181 | +- Cache is automatically invalidated on write operations (apply, delete, patch, scale) |
| 182 | +- Metrics tracked: hits, misses, evictions, size |
| 183 | +- Do not bypass caching for read-heavy operations |
| 184 | + |
| 185 | +### Naming Conventions |
| 186 | + |
| 187 | +- Use **descriptive variable and function names** throughout. Names should clearly convey purpose and intent. |
| 188 | +- Avoid abbreviations and single-letter names (except loop counters). Use `resourceName` not `rn`, `kubeClient` not `kc`, `toolResult` not `tr`. |
| 189 | +- Function names should describe what they do: `handleKubectlGetEnhanced` not `doGet`, `validatePromQLQuery` not `checkQ`. |
| 190 | +- Handler functions: prefix with `handle`. |
| 191 | +- Builder methods: prefix with `With`. |
| 192 | +- Validation functions: prefix with `Validate`. |
| 193 | + |
| 194 | +### Code Reuse |
| 195 | + |
| 196 | +- Before writing new code, search for existing utilities in `internal/` that already solve the problem. |
| 197 | +- Do not duplicate logic across tool providers. Shared functionality belongs in `internal/` packages: |
| 198 | + - Command execution → `internal/commands/` |
| 199 | + - Error formatting → `internal/errors/` |
| 200 | + - Input validation → `internal/security/` |
| 201 | + - Caching → `internal/cache/` |
| 202 | + - Logging → `internal/logger/` |
| 203 | +- If you find duplicated code while working on a change, consolidate it as part of your PR when the scope is reasonable. |
| 204 | + |
| 205 | +--- |
| 206 | + |
| 207 | +## Testing |
| 208 | + |
| 209 | +### Framework |
| 210 | + |
| 211 | +- **Ginkgo v2 + Gomega** for behavioral tests |
| 212 | +- **testify** for assertions and mocking |
| 213 | +- Table-driven tests for comprehensive coverage |
| 214 | +- **Minimum 80% test coverage** enforced by CI |
| 215 | + |
| 216 | +### Mock Infrastructure |
| 217 | + |
| 218 | +Use the mock shell executor for unit tests instead of calling real CLI tools: |
| 219 | + |
| 220 | +```go |
| 221 | +mockExecutor := cmd.NewMockShellExecutor() |
| 222 | +mockExecutor.AddResponse("kubectl get pods -n default", "NAME READY STATUS\npod1 1/1 Running", nil) |
| 223 | +ctx := cmd.WithShellExecutor(context.Background(), mockExecutor) |
| 224 | +``` |
| 225 | + |
| 226 | +### Test Files |
| 227 | + |
| 228 | +- Unit tests: co-located `*_test.go` files in each package |
| 229 | +- E2E tests: `test/e2e/` (requires Kind cluster) |
| 230 | +- All public functions require unit tests |
| 231 | + |
| 232 | +--- |
| 233 | + |
| 234 | +## CI/CD Pipeline |
| 235 | + |
| 236 | +The main workflow (`.github/workflows/ci.yaml`) runs on pushes/PRs to `main`: |
| 237 | + |
| 238 | +1. **Multi-arch Docker build** — amd64 + arm64 |
| 239 | +2. **Go unit tests** — `go test -v -cover` |
| 240 | +3. **E2E tests** — Kind cluster-based integration tests |
| 241 | +4. **Helm chart tests** — Chart unit tests |
| 242 | + |
| 243 | +Additional workflow: `tag.yaml` for release tagging. |
| 244 | + |
| 245 | +--- |
| 246 | + |
| 247 | +## Observability |
| 248 | + |
| 249 | +The server includes built-in observability: |
| 250 | + |
| 251 | +- **OpenTelemetry tracing** — gRPC, HTTP exporters, stdout |
| 252 | +- **Prometheus metrics**: |
| 253 | + - `kagent_tools_mcp_invocations_total` — invocation count by tool/provider |
| 254 | + - `kagent_tools_mcp_invocations_failure_total` — failure count |
| 255 | + - `kagent_tools_mcp_registered_tools` — tool inventory |
| 256 | + - `kagent_tools_mcp_server_info` — server metadata |
| 257 | +- **Structured logging** with context via `internal/logger/` |
| 258 | + |
| 259 | +--- |
| 260 | + |
| 261 | +## Commit Messages |
| 262 | + |
| 263 | +Use **Conventional Commits**: |
| 264 | + |
| 265 | +``` |
| 266 | +<type>: <description> |
| 267 | +
|
| 268 | +[optional body] |
| 269 | +
|
| 270 | +Signed-off-by: Name <email> |
| 271 | +``` |
| 272 | + |
| 273 | +Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `perf`, `ci` |
| 274 | + |
| 275 | +--- |
| 276 | + |
| 277 | +## What Not to Do |
| 278 | + |
| 279 | +- Do not call CLI tools directly — use the `CommandBuilder` from `internal/commands/`. |
| 280 | +- Do not skip input validation — always use `internal/security/` validators. |
| 281 | +- Do not return Go errors from MCP handlers — use `ToolError.ToMCPResult()` instead. |
| 282 | +- Do not duplicate logic across providers — extract to `internal/` packages. |
| 283 | +- Do not bypass the cache for read operations. |
| 284 | +- Do not add new tool providers without a corresponding `RegisterTools` function. |
| 285 | +- Do not commit without running `make fmt && make lint && make test`. |
| 286 | + |
| 287 | +--- |
| 288 | + |
| 289 | +## Adding a New Tool |
| 290 | + |
| 291 | +1. Create a new package under `pkg/<provider>/`. |
| 292 | +2. Implement tool handlers (prefix with `handle`). |
| 293 | +3. Implement `RegisterTools(server, readOnly)` — respect the `readOnly` flag for write operations. |
| 294 | +4. Register the provider in `cmd/main.go` inside `registerMCP()`. |
| 295 | +5. Add input validation using `internal/security/`. |
| 296 | +6. Use `CommandBuilder` for CLI execution. |
| 297 | +7. Return errors via `ToolError.ToMCPResult()`. |
| 298 | +8. Write unit tests with mock shell executor (80% coverage minimum). |
| 299 | +9. Add E2E tests if the tool interacts with a cluster. |
| 300 | +10. Run `make fmt && make lint && make test` before submitting. |
| 301 | + |
| 302 | +--- |
| 303 | + |
| 304 | +## Additional Resources |
| 305 | + |
| 306 | +- [DEVELOPMENT.md](DEVELOPMENT.md) — Development setup and code standards |
| 307 | +- [CONTRIBUTION.md](CONTRIBUTION.md) — Contribution process and PR guidelines |
| 308 | +- [docs/quickstart.md](docs/quickstart.md) — Quick start guide |
0 commit comments