Skip to content

Commit 33fa633

Browse files
authored
docs: add AGENTS.md with repository guide for AI coding agents (#51)
Add comprehensive guide covering project architecture, tool provider patterns, build/test commands, code conventions, naming standards, code reuse guidelines, testing approach, and CI/CD pipeline details. Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
1 parent a648547 commit 33fa633

1 file changed

Lines changed: 308 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
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

Comments
 (0)