# gadfly-mcp — Developer Guide A stdio [MCP](https://modelcontextprotocol.io) server exposing the [gadfly-reports](https://gitea.stevedudenhoeffer.com/steve/gadfly-reports) findings store to an MCP client (e.g. Claude). It is a **thin, stateless HTTP client** to the store — it never opens SQLite and never imports the store's package. > This is a public, **vibe-coded** project (built largely by an AI agent). Keep that honest in the > README; it's homelab-grade. ## Shape - Single `main.go` (`package main`) at the repo root, so the launch path is just `go run gitea.stevedudenhoeffer.com/steve/gadfly-mcp@latest` — no `cmd/` subpath. This is the whole point: the client compiles + caches it on demand; nothing to install or manage. - Uses the official Go MCP SDK (`github.com/modelcontextprotocol/go-sdk`): `mcp.NewServer` → `mcp.AddTool[In,Out]` (input schemas inferred from struct + `jsonschema` tags) → `server.Run(ctx, &mcp.StdioTransport{})`. - Config: `--store` flag (default `$GADFLY_REPORTS_URL`, else `http://localhost:8090`); bearer token from `$GADFLY_REPORTS_TOKEN`, sent on every request when set. ## Contract with gadfly-reports The store's HTTP/JSON API is the contract — its README is the **source of truth**. This client mirrors only the subset it needs with small local structs (`exportRow`, `modelStat`, `gradeReq`, …). If you change a field here, check it against gadfly-reports' `server.go`/`store.go`. Endpoints used: `GET /export`, `POST /findings/{id}/grade`, `GET /scoreboard`. Three tools: `list_findings`, `record_finding_grade`, `scoreboard`. The grader is always forced to `"claude"`. The store holds **no points**; ranking by points/value-per-minute is a client concern — say so in the `scoreboard` tool description. ## Tests The core logic (`groupFindings` / `listFindings` / `recordGrade` / `scoreboard`) is factored free of MCP types and tested against an `httptest.Server`, so tests need no real daemon. Keep it that way — add a test when you add a tool or change the grouping/filtering. ```sh go build ./... go vet ./... gofmt -l . # must be empty go test -race ./... ``` ## When making changes - Keep this a thin client: no SQLite, no business logic the store should own. - Keep the launch path a root `package main` (don't move it under `cmd/`), so `go run …@latest` stays the one-liner the README documents.