AGENTS.md · git:20260625.b95e689 · 2026-06-25 · sha256 043ec7d15dcdd301
AGENTS.md git:20260625.b95e689A
Immutable. This exact content never changes and is served at /api/v1/blob/043ec7d15dcdd301.
# Agent Guide for Prometheus MCP Server An MCP server that gives LLM clients typed tools and resources for working with a running Prometheus instance — PromQL queries, metric/series/label discovery, target and rule inspection, management endpoints, and gated TSDB-admin operations — plus custom tools and resources backed by an embedded, Bleve-indexed copy of the official Prometheus documentation. Compatible backends (e.g. Thanos) get tailored toolsets. See [README.md](README.md) for the full tool list, backend differences, install methods, auth, telemetry, and time-format handling. ## Development workflow Use `Makefile` targets — not raw `go` commands. The build uses the standard Prometheus tooling: [`promu`](https://github.com/prometheus/promu) driven through `Makefile` / `Makefile.common`. The embedded Prometheus documentation is a pinned `prometheus/docs` snapshot (`DOCS_VERSION` in the `Makefile`) that `make docs` downloads as a tarball and extracts into `cmd/prometheus-mcp/external/docs/`; `build`, `test`, and `crossbuild` depend on it, and the directory is gitignored. | Task | Command | |---|---| | Run tests | `make test` | | Run linters | `make lint` | | Full check suite (style, license, lint, yamllint, tidy, build, test) | `make` | | Build the binary for the host | `make build` | | Cross-build all release platforms | `make crossbuild` | | Refresh the embedded docs snapshot | `make docs` | | List the project-specific targets | `make help` | Use bare `make` (or `make lint test` for a faster subset) as the default pre-commit check. Release artifacts (container images, tarballs) are produced in CI via [`prometheus/promci`](https://github.com/prometheus/promci) + `promu` — not built locally. ## Code layout (`pkg/mcp/`) - `server.go` — `ServerContainer` (DI struct), middleware chain, HTTP + stdio transport. - `tools.go` — `*mcp.Tool` definitions with annotations. - `types.go` — tool input structs (`jsonschema` tags) and their `slog.LogValuer` implementations. - `handlers.go` — tool handler methods on `*ServerContainer`. - `registration.go` — toolset composition, per-backend toolsets (prometheus, thanos), `CoreTools` list. - `resources.go` — MCP resources (metric list, targets, docs). - `docs.go`, `docs_updater.go` — Bleve-indexed doc search with optional live auto-update. - `middleware.go`, `errors.go`, `logging.go` — telemetry middleware, graceful 404 handling, MCP client logging. Supporting: `pkg/prometheus/` (API client builder, plus the `UserAgent()` helper), `internal/metrics/` (metrics registry + namespace). Build/version info comes from `github.com/prometheus/common/version` (populated by promu ldflags); the embedded docs commit is read from `external/docs/COMMIT_HASH` at startup in `cmd/prometheus-mcp/main.go`. ## Adding a new tool 1. **Input type** in `types.go`: struct with `jsonschema` tags and a `LogValue() slog.Value` method so structured logs group fields cleanly. Reuse `TimeRangeInput`, `TruncatableInput` where applicable. 2. **Tool definition** in `tools.go`: `*mcp.Tool` with `Annotations.ReadOnlyHint` *or* `Annotations.DestructiveHint` (use the `ptr(true)` helper — can't take the address of a constant). Zero-input tools use `InputSchema: emptyInputSchema`, not the SDK's `EmptyInput` — see issue [#119](https://github.com/tjhop/prometheus-mcp-server/issues/119) for the OpenAI strict-schema workaround. 3. **Handler** method on `*ServerContainer` in `handlers.go`, signature `(ctx, req, input) (*mcp.CallToolResult, any, error)`. `s.GetAPIClient(ctx)` returns both the prom Go client *and* the matching `http.RoundTripper` — use the client for endpoints it supports, and route everything else through `s.doHTTPRequest` (see "HTTP plumbing" below). Never reach for the default client/transport fields directly; that bypasses request-scoped auth. 4. **Register** in `initPrometheusToolset()` in `registration.go`. If Thanos doesn't support the tool, add its name to `thanosRemovedTools`. Leave `CoreTools` alone unless the tool is essential enough that it should still load even when a user explicitly narrows the toolset — the server already defaults to `--mcp.tools=all`. 5. **Test** in `handlers_test.go` (mock Prometheus lives in `api_mock_test.go`). `registration_test.go` validates toolset composition — it will fail loudly if the maps are inconsistent. 6. Update the tool table in `README.md`. ## Project-specific quirks/gotchas - **Time inputs** accept epoch seconds, RFC3339, *or* Go duration strings relative to now (`5m`, `1h30m`). Use `ParseTimestampOrDuration` / `parseTimeWithDefault` — don't hand-parse. - **HTTP plumbing.** `s.GetAPIClient(ctx)` returns both the prom Go client and the matching `http.RoundTripper`; `authContextMiddleware` makes the RoundTripper request-scoped when an `Authorization` header is present. For anything outside `promv1.API` — custom backends, management endpoints, new APIs — pull the RoundTripper and call `s.doHTTPRequest(ctx, method, rt, path, expectJSON)`, or `s.doManagementAPICall(ctx, method, path)` for `/-/...` endpoints. Both wrappers share the connection pool, emit `target_path`-labelled telemetry, and surface 404s as `ErrEndpointNotSupported`. References: `ThanosStoresHandler` for `/api/v1/...` calls, the Management API handlers for `/-/...`. - **Docs state** in `ServerContainer` is guarded by `sync.RWMutex` because `--docs.auto-update` can swap the Bleve index at runtime. Read under `RLock`, write under `Lock`. - **TSDB admin tools** (`delete_series`, `clean_tombstones`, `snapshot`) gate on the `--dangerous.enable-tsdb-admin-tools` flag and set `DestructiveHint`. `delete_series` additionally requires both `start_time` and `end_time` to avoid accidental full-data wipes. - **Metrics** register through `metrics.Registry` and use `metrics.MetricNamespace` via `prometheus.BuildFQName` — don't register globally. - **Backend toolsets** derive from the base Prometheus toolset: each backend has a `<backend>RemovedTools` list and an `init<Backend>Toolset` initializer that prunes unsupported tools and adds any backend-specific ones (see `initThanosToolset` for the canonical example). To add a new backend, extend `PrometheusBackends`, add the removal list + initializer, and wire it into `getToolset`'s switch — don't fork a parallel map. - **TOON output mode** is a server flag affecting how results are serialized to clients — not usually relevant when editing handler logic, but don't assume JSON shape in end-to-end tests. ## Testing `*_test.go` files sit alongside the code they test. `handlers_test.go` is where most new tool tests land; use `api_mock_test.go`'s mock Prometheus. Run `make test` often — it's fast.