add AGENTS.md, update deps, fix mcp
Build and Publish / check-chart (push) Successful in 33s
Build and Publish / helm-release (push) Has been skipped
Build and Publish / container-images (push) Successful in 3m30s
Build and Publish / go-binaries (push) Successful in 5m2s

This commit is contained in:
2026-07-04 17:21:22 -04:00
parent c0a1631320
commit 3241fc7107
4 changed files with 218 additions and 49 deletions
+64
View File
@@ -0,0 +1,64 @@
# AGENTS.md — go-server-with-otel (template)
A ready-to-fork template app for the `go-app` framework: HTTP + gRPC +
grpc-gateway + MCP + OTEL/Prometheus, wired and building. Fork it, rename it,
replace the `demo` domain with your service. See go-app's AGENTS.md for
framework internals.
## Kick off a new app (do these in order)
1. **Rename via the Makefile** (rewrites module path, binary/app name,
Dockerfile, helm, buf `merge_file_name`, main.go `appName`; deletes the old
swagger file). GNU `sed` required (macOS: `brew install gnu-sed` or coreutils
on PATH). The target is interactive, so pipe confirmation:
```sh
echo y | make rename NAME=your.gitremote/pathto/newapp APP=new-app-name
```
It does **not** rename the `demo` domain — that's steps 46. Afterward verify
`git grep go-server-with-otel` is empty and update `.gitea/workflows/ci.yml`.
2. **Edit config** (`pkg/config/custom.go`): put app fields on `ServiceConfig`
(keep the embedded `*config.AppConfig`). Add `env:"..."` tags for anything
env-configurable — **and see the env gotcha below.** Update `config.yaml`,
`env-sample`, and `helm/values.yaml` to match. Then `make schema`.
3. **Define your proto**: replace `proto/demo/app/v1alpha1/` with
`proto/<domain>/v1alpha1/`, update `PROTO_DIRS` in the Makefile, and run
`make proto` (buf; managed mode → generates into `api/<same path>`, so the
proto `go_package` option is overridden — don't fight it). Delete `api/demo`.
4. **Implement `service.AppService`** (`Init`, `GetGRPC`, `GetHTTP`) in a new
`pkg/<domain>/` package, mirroring `pkg/demo`:
- `<domain>grpc/` — gRPC impl (embed `pb.Unimplemented...Server`); `GetServices`
returns `*opts.GRPCService`; `GetDialOpts` adds the insecure creds the
gateway needs.
- `<domain>mcp/` — `mcp.NewServer` exposed as `HTTPHandler{Prefix:"/api/mcp"}`;
tools via `mcp.AddTool`, typically delegating to the gRPC impl.
- Remove `demohttp/` unless you actually need plain HTTP funcs.
5. **Register it in `main.go`**: set `appServices = []service.AppService{&yoursvc}`.
This should be the only functional change in `main.go`.
6. **Delete `pkg/demo`** and any remaining `demo` references.
7. Build/verify: `go build ./... && go test ./...`, then run and hit `/metrics`,
`/api/...` (REST), `:8081` (grpc + reflection), `/api/mcp`.
## Gotchas the template inherits from go-app
- **Custom-field env doesn't auto-apply.** `MustLoadConfigInto` only parses env
for the embedded `AppConfig`. Add a `ServiceConfig.LoadEnv()` that runs
`env.Parse` over the custom fields (nil the embedded `*AppConfig` first to keep
go-app's precedence) and call it in `main.go` right after `MustLoadConfigInto`.
- **REST gateway 404s** unless `grpcGatewayPathStrip: true` is set in the grpc
config (default is false, so the `/api` prefix isn't stripped before matching).
- **Prometheus double-unit suffix**: don't use `metric.WithUnit` for gauges whose
names already carry the unit; the exporter appends another suffix.
- MCP streamable HTTP: clients must POST to `/api/mcp/` (trailing slash); the
bare path 307-redirects.
## What `make rename` does NOT touch
The `demo` domain naming: package dirs (`pkg/demo*`), `proto/demo`, `api/demo`,
types (`DemoService`, `DemoAppService`, `DemoTool`, …), `PROTO_DIRS`, and the
demo values in `config.yaml`/`helm`. Rename those by hand in steps 26.