Files
mcp/CHANGELOG.md
Rene Nochebuena e23e86b06c feat(mcp): systemd socket activation and healthz under /mcp (v0.1.1)
Patch release. Two changes to cmd/server, both motivated by running the
service behind a unix socket on a reverse-proxied host: the binary now
inherits a systemd-passed listener when present, and the healthz handler
moves under the same path prefix as the MCP endpoint so a single proxy
location forwards both. Bundled with two repository-hygiene changes.

cmd/server:
- chooseListener (new) — picks a listener at startup. When systemd has
  passed a LISTEN_FDS fd via github.com/coreos/go-systemd/v22/activation,
  the binary uses the inherited listener; otherwise it binds TCP at -addr
  as before. The startup log records "mode":"socket-activated" or
  "mode":"tcp" so operators can confirm which path is live. Same binary
  works for local dev and for systemd-managed deployment with no flags
  or env vars to toggle.
- Health probe path is now derived from -path. With the default -path /mcp
  the probe is served at /mcp/healthz; the legacy /healthz route is no
  longer registered. A reverse proxy can now route the whole MCP service
  through a single "/mcp" location prefix instead of maintaining a second
  forward for /healthz. Consumers of v0.1.0 that hit /healthz directly
  must switch to /mcp/healthz.

Dependencies:
- github.com/coreos/go-systemd/v22 v22.7.0 — listener inheritance via
  LISTEN_FDS. Loaded only by cmd/server.

Docs:
- README.md "Deployment" section rewritten to be hosting-agnostic. The
  v0.1.0 draft prescribed a specific systemd-on-HestiaCP layout; the new
  text points at the Dockerfile and at systemd socket activation as a
  supported binary mode without dictating one operator's setup. Adds an
  explicit note that any reverse proxy must disable response buffering on
  the /mcp location — streamable MCP delivers tool results via Server-Sent
  Events and default proxy buffering breaks the stream.

Repository hygiene:
- /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. The Dockerfile at the
  module root remains the only portable, public-facing build artefact.

No tool surface, no validation rules, no index schema, and no behaviour of
the indexer changed. Operators upgrading from v0.1.0 must update their
health-probe URL to /mcp/healthz (or whichever path matches their -path
flag); MCP-protocol clients (Claude, Cursor, Zed, etc.) need no changes.
2026-05-29 14:09:06 -06:00

5.3 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.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 from LISTEN_FDS via github.com/coreos/go-systemd/v22/activation when present, falling back transparently to TCP -addr binding 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 /healthz to <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 /healthz route receive 404; update to /mcp/healthz (or whatever path matches your -path flag).
  • README.md deployment section rewritten to be hosting-agnostic. Points at the Dockerfile and 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 /mcp location, 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. The Dockerfile at the module root remains the only portable, public-facing build artefact.

Dependencies

  • Added: github.com/coreos/go-systemd/v22 v22.7.0 — used by cmd/server to 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-sdk v1.0.0
  • Listen address and HTTP path configurable via EINHERJAR_MCP_ADDR (default :8080) and EINHERJAR_MCP_PATH (default /mcp)
  • /healthz liveness 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.go package comment, sub-package doc comments, every exported symbol (type/interface/func/method/const/var) with signature + godoc, ADRs, README code-fence examples, dependency edges from go.mod, and the contents of compliance_test.go (interface assertions + structural test names)
  • Appends a synthetic wire module documenting canonical Einherjar application wiring conventions

Tools (10)

  • list_modules — enumerate every Einherjar module with purpose and sub-packages
  • get_module — package doc, dependencies, sub-packages, key symbols, ADRs, compliance counts; optional embedded README
  • search_symbols — full-text search across name, doc, sub-package, module
  • get_symbol — full signature, doc, and source location for one symbol
  • list_adrs — list architectural decision records, optionally filtered by module
  • get_adr — fetch one ADR's markdown body
  • get_example — canonical usage snippets extracted from module READMEs and the wire conventions
  • get_compliance — interface assertions and structural test names from a module's compliance_test.go
  • get_changelog — full CHANGELOG.md markdown for one module
  • validate_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-discarded
  • logz.direct-env-read
  • web.server-not-appended
  • wire.hook-bad-signature, wire.hook-outside-beforestart, wire.route-specific-after-param

Synthetic wire module

  • Authored in internal/index/builtins/README.md; participates in list_modules, get_module, and get_example exactly 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 Dockerfile that 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