Skip to content

MCP symbol tools: stop hiding symbols that no package barrel re-exports #4739

Description

@amcclain

Problem

The symbol tools from #4736 treat a symbol that no package barrel re-exports as internal: hoist-search-symbols hides it by default and halves its rank, and hoist-get-symbol renders its import line as "none - not re-exported from a package barrel (internal API)". The premise was that apps cannot import such a symbol. That is false: the package has no exports map, so a deep import such as @xh/hoist/cmp/card/CardModel has always worked.

Barrels remain the preferred import path. Apps use them by far the most, the barrels are curated, and #4640 to #4644 keep them as the public API surface while removing internal barrel imports inside the library. So the tools should show the barrel path as the import when one exists, and never hide a symbol or claim it is unimportable for lack of one.

#4737 completed the barrels for the gaps the resolver found, so nothing is hidden today. This ticket removes the behavior so the next gap does not hide a real API.

Where the assumption is load-bearing

  • mcp/data/symbol-search.ts: isInternalSymbol and isInternalMember treat a null importPath as internal; INTERNAL_WEIGHT halves the score of such symbols.
  • mcp/formatters/typescript.ts importLine(): "none - not re-exported from a package barrel (internal API)".
  • Tool description and server instructions call it the "public" import path and say to import from it rather than from the source file.
  • mcp/data/import-paths.ts header comment asserts apps import from barrels, not files.
  • mcp/README.md design notes ("un-importable", "no public import") and the MCP symbol tools v2: ranked concise search, member summaries and filters, import paths, external members #4736 CHANGELOG bullet ("un-importable symbols hidden").
  • mcp/data/symbol-search.spec.ts: the hidden-exact-match case uses LeafRow, a symbol hidden only for lacking a barrel.

Proposed change

  • Internal means internal by location or visibility only: impl/, admin/, inspector/, dynamics/, and non-exported declarations. A null barrel path no longer hides or penalizes a symbol.
  • When no barrel re-exports a symbol, render the import that works, for example import {LeafRow} from '@xh/hoist/data/cube/row/LeafRow';, and note that no barrel covers it. Search hits show the same file-path import.
  • Tool descriptions and instructions: "import path (the package barrel when one re-exports the symbol, otherwise the file)". Drop "public".
  • Update the README, the MCP symbol tools v2: ranked concise search, member summaries and filters, import paths, external members #4736 CHANGELOG bullet, the resolver's header comment, and the spec's hidden-example case (use an impl/ symbol).

Open question

docs/coding-conventions.md "Barrel Exports" shows a deep import as a ❌ Don't. The hoist-ai reference skill, the Context7 rules, and the review checklist (HR-026) follow that section. If the intended strength is "prefer the barrel", that section is the place to say so and the others follow from it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions