Files
go-server-with-otel/AGENTS.md
T
rmcguire 3241fc7107
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
add AGENTS.md, update deps, fix mcp
2026-07-04 17:21:22 -04:00

3.4 KiB
Raw Permalink Blame History

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:

    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.