Minor release. The indexer named composite types but could not describe their shape: every declaration was truncated at the first brace, so a struct symbol carried only its `type X struct` header and an interface symbol only its `type X interface` header. Field names, field types, and — most painfully — struct tags such as `env:"EINHERJAR_PG_HOST"` were dropped, as were the method sets of every port interface. An assistant could be told that `db-postgres` has a `Config` and a `Provider`, but not what env vars configure the one or what methods the other requires. This change captures both. internal/index (schema): - Symbol gains two optional fields. `fields` ([]Field) carries a struct's field set — name, type, raw struct tag (surrounding backticks stripped), doc comment, and an `embedded` marker. `methods` ([]Method) carries an interface's method set — name, signature without the leading `func`, and doc comment, including embedded interfaces. Both are omitempty and absent for every other kind. - SchemaVersion is deliberately unchanged. The two additions are additive and omitempty, so an older consumer parses the new index unchanged; per the existing rule the constant only bumps on a breaking format change. internal/index (builder): - collectSymbols now inspects each type's TypeSpec and, for a *ast.StructType or *ast.InterfaceType, fills the new Symbol members. A grouped field declaration (`x, y int`) yields one Field per name; an embedded field or interface yields an entry with an empty name. - New helpers: typeSpecType (underlying type expr of a lone type spec), extractFields, extractIfaceMethods, fieldDoc (doc comment or trailing line comment), and nodeString — a non-truncating printer used for field types, tags, and method signatures, distinct from formatNode which keeps truncating to produce the one-line header. internal/index (search): - matches() now also tests the query against struct field names, field types, and struct tags, and against interface method names and signatures. A query like an env-var key or a method name now resolves to the type that declares it. internal/tools: - get_symbol and search_symbols descriptions updated to advertise the new struct-field and interface-method coverage. No input/output schema change beyond the additive Symbol fields, which get_symbol already returns whole. internal/index (tests): - New builder_test.go — the package previously had no tests. Builds a temporary module fixture and asserts capture of struct fields (with tags and docs), embedded fields, interface methods (with signatures and docs), embedded interfaces, and discovery of a struct by one of its struct tags (the failure mode that motivated the change). Docs: - CHANGELOG.md gains an [Unreleased] entry; README.md tool table updated to state that get_symbol returns struct fields and interface methods and that search_symbols matches fields, tags, and methods. No new dependencies. The committed data/index.json placeholder is untouched — the index is regenerated at image build (Dockerfile runs cmd/indexer), so a deployment must be rebuilt to serve the richer index; a server still running the prior image keeps serving the older, member-less one. Reviewed-on: #1 Co-authored-by: Rene Nochebuena Guerrero <rene@nochebuena.dev> Co-committed-by: Rene Nochebuena Guerrero <rene@nochebuena.dev>
7.1 KiB
Changelog — einherjar/mcp
All notable changes to this module are documented here. Format follows Keep a Changelog. This module adheres to Semantic Versioning.
[0.2.0] — 2026-06-10
Minor release. The indexer now captures the members of composite types, closing a gap where get_symbol and search_symbols could name a struct or interface but not describe its shape — most painfully, struct tags (env-var keys, json names) were invisible.
Added
- Struct fields in the index. Each struct-type symbol now carries a
fieldsarray — field name, type, raw struct tag (backticks stripped), doc comment, and anembeddedmarker.get_symbolreturns it; previously the signature was truncated to the baretype X structheader, so field names, types, and tags (e.g.env:"EINHERJAR_PG_HOST") were dropped entirely. - Interface method sets in the index. Each interface-type symbol now carries a
methodsarray — method name, signature (without the leadingfunc), and doc comment, including embedded interfaces. Consumers can now see what a port likedb-postgresProvideractually requires. - Search by field/tag/method.
search_symbolsnow also matches a query against struct field names, field types, and struct tags, and against interface method names/signatures — so an env-var key or a method name resolves to the type that declares it. internal/indextest suite covering field, tag, embedded-field, interface-method, and search-by-tag capture (the package previously had no tests).
Notes
- The index schema gains two optional (
omitempty) fields;SchemaVersionis unchanged because the change is additive and older consumers parse the new index unchanged. - This is a pure indexer/schema change. The live server picks it up on its next image build, which re-runs
cmd/indexer(seeDockerfile). A deployment that has not been rebuilt will still serve the older, member-less index.
[0.1.1] — 2026-05-29
Patch release. Two changes to cmd/server make the binary cleaner to run behind a unix socket on a reverse-proxied host, plus two repository-hygiene changes that follow from the same deployment exercise.
Added
- Systemd socket activation in
cmd/server. The binary inherits the listener fromLISTEN_FDSviagithub.com/coreos/go-systemd/v22/activationwhen present, falling back transparently to TCP-addrbinding otherwise. Startup log records"mode":"socket-activated"or"mode":"tcp". Same binary, no flag or env var to toggle.
Changed
- Health probe path moved from
/healthzto<path>/healthz(default/mcp/healthz). Lets a reverse proxy expose the entire MCP service through one location prefix. v0.1.0 consumers hitting the old/healthzroute receive 404; update to/mcp/healthz(or whatever path matches your-pathflag). README.mddeployment section rewritten to be hosting-agnostic. Points at theDockerfileand systemd socket activation as supported binary modes without prescribing one operator's setup. Adds the SSE-buffering caveat once: any reverse proxy must disable response buffering on the/mcplocation, otherwise Server-Sent Events get batched and streamable MCP sessions break./deploy/is now.gitignored. Local deployment artefacts (systemd units, reverse-proxy templates, per-release scripts) are operator-specific by design and live outside the public repository. TheDockerfileat the module root remains the only portable, public-facing build artefact.
Dependencies
- Added:
github.com/coreos/go-systemd/v22 v22.7.0— used bycmd/serverto detect and use a systemd-passed listener.
Upgrade notes
| If you… | Action |
|---|---|
| Consume the MCP service from an MCP client (Claude, Cursor, Zed, etc.) | None — /mcp is unchanged |
| Monitor the service via the healthz probe | Update the probe URL from /healthz to /mcp/healthz |
| Run the binary directly (no reverse proxy) | None — -addr TCP binding still works the same way |
| Run the binary under systemd with a socket unit | The same binary now picks up the inherited listener automatically |
[0.1.0] — 2026-05-29
Initial release. The mcp module hosts the Einherjar Model Context Protocol server — a remote, streamable-HTTP service that teaches AI assistants about every other module of the framework.
Added
Server (cmd/server)
- Streamable-HTTP MCP server built on
github.com/modelcontextprotocol/go-sdkv1.0.0 - Listen address and HTTP path configurable via
EINHERJAR_MCP_ADDR(default:8080) andEINHERJAR_MCP_PATH(default/mcp) /healthzliveness endpoint- Embedded framework index loaded once at startup; in-memory for the lifetime of the process
Indexer (cmd/indexer)
- Walks an Einherjar repository checkout and produces
data/index.json - For each sibling module captures: import path, Go version, README (full + extracted tagline), CHANGELOG, root
doc.gopackage comment, sub-package doc comments, every exported symbol (type/interface/func/method/const/var) with signature + godoc, ADRs, README code-fence examples, dependency edges fromgo.mod, and the contents ofcompliance_test.go(interface assertions + structural test names) - Appends a synthetic
wiremodule documenting canonical Einherjar application wiring conventions
Tools (10)
list_modules— enumerate every Einherjar module with purpose and sub-packagesget_module— package doc, dependencies, sub-packages, key symbols, ADRs, compliance counts; optional embedded READMEsearch_symbols— full-text search across name, doc, sub-package, moduleget_symbol— full signature, doc, and source location for one symbollist_adrs— list architectural decision records, optionally filtered by moduleget_adr— fetch one ADR's markdown bodyget_example— canonical usage snippets extracted from module READMEs and thewireconventionsget_compliance— interface assertions and structural test names from a module'scompliance_test.goget_changelog— full CHANGELOG.md markdown for one modulevalidate_snippet— pattern-match a Go snippet against framework conventions; returns findings with severity, hint, and line
Validation rules (8)
launcher.missing-run,launcher.no-components,launcher.run-error-discardedlogz.direct-env-readweb.server-not-appendedwire.hook-bad-signature,wire.hook-outside-beforestart,wire.route-specific-after-param
Synthetic wire module
- Authored in
internal/index/builtins/README.md; participates inlist_modules,get_module, andget_exampleexactly like a real module - Sections: project layout,
Run()shape, feature hook shape, route ordering, authorization, middleware helpers, adapters at the wire boundary, migrations and seeds - All examples use einherjar import paths
Packaging
- Multi-stage
Dockerfilethat builds from the einherjar repository root (docker build -f mcp/Dockerfile .) so the indexer can walk every sibling module at image-build time - Distroless runtime image; static binary; non-root user