Search entity plugins
September 21, 2026 ยท View on GitHub
Search list results are built from ordered entity plugins under
packages/worker/src/mcp/tools/search-entity-plugins/.
The plugin registry is the discovery/candidate/format seam, but a new entity type is not only a plugin registration yet. Closed TypeScript unions, Markdown list formatting, and detail resolution still need parallel updates.
To add a search entity:
- Add one lower-kebab-case module in
search-entity-plugins/. - Export a
SearchEntityPluginwith the entitytype. - Implement the applicable hooks:
buildDescriptorsforunderstandSearchQueryentity hints.buildCandidatesfor list-search candidates.formatSlimMatchfor structured list results (toSlimStructuredMatches/SlimSearchMatch). It does not cover Markdown list output โ keep actionable list fields in parity withformatMatchListIteminsearch-format-list.ts(entity refs, why-matched, inlined call contracts / shapes, next-step guidance).formatEntityDetailonly whensearch({ entity })supports that type.
- Register the plugin once in
search-entity-registry.ts, in the intended flatten order. - Extend the closed unions in
search-format-types.ts, keeping these groups separate:- Always required for any list/result type (including result-only types such
as
retriever_resultanddomain):SearchMatchType,SearchMatch, andSlimSearchMatch. - Entity-backed only (types accepted by
{type}:{id}/ entity detail):SearchEntityType,SearchEntityDetail, and relatedSearchEntityDetailStructuredvariants as needed.
- Always required for any list/result type (including result-only types such
as
- Update Markdown list formatting in
search-format-list.ts(formatMatchListItemused byformatSearchMarkdown) for the new type. PluginformatSlimMatchalone is not enough for agent-visible list text. - Teach
resolveEntityDetailinsearch-detail.tshow to load that entity whensearch({ entity })should support it (skip for result-only types such asretriever_result). - Update
parseEntityRefinsearch-format-helpers.tsso{type}:{id}parsing accepts the new entity-backed type (first:is the type; the id may contain colons). Unknown types and malformed refs share the same invalid-entity error. Guide and package entity refs also accept a hash fragment (guide:{id}#{slug},package:{id}#{subpath}); other types reject fragments inresolveEntityDetail. - For entity-backed types, update the public allowed-type lists so agents and
docs stay in sync:
search-tool-definition.ts(tool description andentityinput schema copy that enumeratescapability|guide|integration|mcp-server|package|secret)docs/use/search.md(user-facing{type}:{id}type list)
- Add or update
search-entity-registry.node.test.tsto prove the registry order and whether the type is entity-backed.
Current candidate flatten order is:
capabilityguidepackageintegrationsecretretriever_result
The package plugin may emit additional first-class candidates for strong
export contracts (id / entity ref package:{kodyId}#{subpath}) alongside the
package index candidate. Promotion is capped and score-gated so broad queries
are not flooded; see docs/use/search.md (Package exports in ranked results).
domain is registered last as a result-only plugin (slim formatting only): its
rows come from the broad-query domain overview in searchUnified, not from the
candidate pipeline.
Keep ranking, scoring, and output formatting changes out of plugin seam work unless the behavior change is explicitly requested.