feat(mcp): index struct fields and interface method sets (#1)

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>
This commit was merged in pull request #1.
This commit is contained in:
2026-06-10 10:38:30 -06:00
committed by NOCHEBUENADEV
parent e23e86b06c
commit 13a186c60a
7 changed files with 328 additions and 15 deletions

View File

@@ -6,6 +6,24 @@ This module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html
---
## [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 `fields` array — field name, type, raw struct tag (backticks stripped), doc comment, and an `embedded` marker. `get_symbol` returns it; previously the signature was truncated to the bare `type X struct` header, 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 `methods` array — method name, signature (without the leading `func`), and doc comment, including embedded interfaces. Consumers can now see what a port like `db-postgres` `Provider` actually requires.
- **Search by field/tag/method.** `search_symbols` now 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/index` test 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; `SchemaVersion` is 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` (see `Dockerfile`). 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.