Before running an installation command, follow SETUP.md. It is the single source of truth for setup by either a person or a coding agent, including prerequisites, host selection, installation, verification, updates, rollback, and removal.
Semantic JS MCP requires Node.js 22 or newer and rg (ripgrep). It can be
installed through the verified Codex plugin route or registered as a local
stdio server in another compatible MCP host. Package installation alone does not configure an MCP host.
After setup, see Getting started for practical investigation prompts and compact evidence examples.
Your coding agent is only as good as its understanding of your codebase.
Coding agents can generate code quickly, but reliable engineering requires more than reading files and matching text. They need to understand which declaration a reference belongs to, how symbols cross workspace boundaries, whether the collected evidence is complete, and whether that evidence is still accurate.
Semantic JS MCP gives coding agents structured, read-only semantic context so they can navigate, review, and change code with explicit uncertainty.
Its scope is intentionally narrow: it strengthens an agent's understanding of symbol identity, types, references, diagnostics, and evidence coverage. It does not replace architectural reasoning, source inspection, dependency analysis, tests, or runtime observation.
Better agents begin with better evidence.
It supports the JavaScript ecosystem, including TypeScript, JavaScript, TSX, JSX, Node module variants, and Vue projects. Language servers provide the underlying semantic data, which the server turns into structured results designed for coding agents.
For each file, it identifies the owning workspace and uses the corresponding TypeScript or Vue language server. Across the repository, it can distinguish verified references from unrelated or unresolved text matches. Analysis stays within a configured workspace boundary (the directory the server was started in by default). These results complement text search, source inspection, and focused tests.
Version 0.11.0 is the current release. APIs and result contracts may evolve while the project remains on the 0.x release line. See the roadmap for areas under consideration.
- Node.js 22 or newer is required.
- Node.js 24 LTS is recommended for new installations. See the Node.js release schedule.
rg(ripgrep) must be available onPATHfor repository-wide discovery.- The bundled TypeScript SDK is used by default. The analyzed repository's own
node_modules/typescriptis used only whenSEMANTIC_JS_MCP_ALLOW_WORKSPACE_TYPESCRIPT=1is set. - Analysis is confined to a workspace boundary: the directory the server was started in and the package root. Paths outside it are rejected with
PATH_OUTSIDE_WORKSPACE_BOUNDARY. Hosts that advertise the MCProotscapability (for example Claude Code) provide the active workspace automatically. In Codex, the agent proposes the current project or another human-selected directory, canonicalizes it without granting access, and adds it only after a separate human-approved tool call. That authorization exists only for the MCP process lifetime.SEMANTIC_JS_MCP_WORKSPACE_ROOTSremains available for explicitly preconfigured roots in other or non-interactive hosts. - Language servers and tsserver run with a fixed snapshot of the canonical workspace roots. Node.js filesystem permissions, a symlink-aware path guard, temporary-directory-only writes, provider-child restrictions, and output filtering keep provider imports and cached results inside that snapshot. Changing host roots closes providers and invalidates reference sets before new analysis.
- TypeScript,
typescript-language-server, the Vue language server, and@vue/typescript-pluginare pinned dependencies. Published packages bundle every production dependency so Codex installations do not require a separate dependency installation step. Startup verifies provider entry points before accepting MCP requests. - Source discovery and language selection include
.ts,.tsx,.mts,.cts,.js,.jsx,.mjs,.cjs, and.vuefiles. - Run
npm run check:runtimeto report every required component and its resolved file path.
The package exposes a semantic-js-mcp executable. semantic-js-mcp serve starts the stdio MCP server, and semantic-js-mcp doctor verifies the installed Node runtime, ripgrep, resolved provider paths, MCP startup, tool discovery, TypeScript reference accounting, diagnostic freshness, and Vue navigation.
Complete the source-checkout setup, then run the checks applicable to the change:
npm run check
npm run check:runtime
npm run doctor
npm run smoke:ci
npm run smoke
npm run smoke:vue
npm run smoke:lifecycleRun npm run benchmark after changes to scanning, references, caching, lifecycle, or memory. Provider disposal changes can also be characterized with npm run benchmark:lifecycle-memory; its output declares the garbage-collection and platform measurement method. Normal analysis is local and read-only; it does not require network access after dependencies are installed.
Tools are ordered from smaller responses to deeper evidence:
| Tool | Provides | Typical continuation |
|---|---|---|
lsp_document_symbols |
Structure for one file | lsp_definition, lsp_audit_symbol |
lsp_workspace_symbols |
Symbol-name discovery | lsp_count_named_symbol, lsp_audit_named_symbol |
lsp_definition |
Definition resolution at a position | lsp_hover, lsp_count_references |
lsp_hover |
Inferred type and documentation | lsp_definition, lsp_audit_symbol |
lsp_diagnostics |
Focused diagnostics for one file | lsp_definition, lsp_hover |
lsp_count_text_matches |
Exact identifier text count without semantic verification | lsp_count_named_symbol, lsp_audit_named_symbol |
lsp_count_named_symbol |
Definition and reference counts by name | lsp_audit_named_symbol, lsp_reference_page |
lsp_count_references |
Reference counts at a position | lsp_audit_symbol, lsp_reference_page |
lsp_audit_named_symbol |
Compact composed summary by symbol name | lsp_reference_page |
lsp_audit_symbol |
Compact composed summary at a position | lsp_reference_page |
lsp_references |
First page of verified locations | lsp_reference_page |
lsp_reference_page |
A later page from the same collection | lsp_definition |
lsp_unresolved_reference_page |
Unresolved candidates with locations and literal reasons | lsp_definition |
Composite audits reuse the same internal definition, hover, and reference primitives as the narrow tools. Their default response contains definition identity, signature, reference and text-match counts, unresolved count, files affected, collection status, and freshness. Use lsp_reference_page with a returned referenceSetId for verified locations and detailed collection evidence, or lsp_unresolved_reference_page for unresolved candidates. Use lsp_references when starting from an exact source position without an existing reference set.
Compatible count, audit, and reference calls reuse a short-lived reference set. Compact presentation changes response size, not collection scope.
Every successful result contains:
producer: the literal semantic-js-mcp name, server version, and result-schema version that produced the response.request: normalized inputs and explicit limit interpretation.result: evidence produced by the tool.collection: how evidence collection completed.presentation: how much collected evidence appears in this response.continueWith: a list of exact MCP tool names that can add the next kind of evidence.
structuredContent is the canonical JSON object. The text content is YAML generated from that same object and parses back to the same data.
Consumers upgrading from result schema 5 should follow the schema migration guide.
complete: the requested collection scope completed and every discovered item was classified.limited: a suppliedmaxCandidatesormaxDefinitionsvalue stopped collection.partial: collection completed with explicitly reported items whose definition or owning file could not be resolved.failed: the tool call failed and the error object explains why.
Collection and presentation are independent. A complete collection may use presentation.mode: compact-summary, page, count-only, or subset without weakening its counts. Audits use compact-summary by default and retain their full reference set for focused follow-up calls.
For reference results, includeDeclaration: false excludes locations that resolve to the requested declaration. It never excludes the source position merely because that position initiated the query. The reported invariant is verifiedTotal = foundByOwningWorkspaceLanguageServer + verifiedFromOtherWorkspaces after declaration filtering and deduplication.
Reference pages group the locations returned in that page under referenceGroups by their exact source file. Each location keeps its explicit range and discoveryMethod, while locationsAvailable and locationsReturned continue to count locations rather than file groups. Pagination selects locations before grouping, so grouping does not change page membership or collection status. File groups follow first appearance in the page, and locations preserve their relative order within each file; cross-file interleaving is not part of the reference contract.
Named counts and audits report definitionSelectionStatus as no-definition-selected, one-definition-selected, or multiple-definitions-selected. This status describes exact declarations remaining after fileHint filtering, before any maxDefinitions analysis limit. When selection is empty or ambiguous, continueWith recommends structural or position-based tools. It recommends lsp_reference_page only when the response contains a reusable reference set.
They also report semanticEvidence.status as usable-as-requested or follow-up-required. Follow-up reasons combine incomplete collection and ambiguous definition selection without treating a compact, paged, or subset presentation as incomplete evidence. This status evaluates only the requested semantic result; it does not declare the code correct.
When fileHint selects no declaration, a named audit can verify whether source bindings resolve to the hinted file while keeping declaration identity and uncertainty explicit.
Collection limits accept positive integers only:
- omitted:
{mode: unlimited} - supplied:
{mode: maximum, maximum: N}
Omitting maxCandidates or maxDefinitions requests unlimited collection. pageSize and maxResults only control returned items for tools that expose them as presentation parameters.
Reusable reference sets verify participating file content and the repository source inventory before returning another page. Added, removed, renamed, or changed sources invalidate stale evidence instead of silently reusing it.
Diagnostics are current only when the owning provider confirms the analyzed
document snapshot. Unconfirmed reports remain isolated and explicitly
untrusted; an empty unconfirmed report is never presented as a clean file.
MCP tools report evidence; they do not decide whether a code change passes. npm run ci:evaluate -- <result.json> applies a deterministic CI policy to one canonical structured result:
pass, exit0: complete evidence and no verified error diagnostic.fail, exit1: verified diagnostics contain an error.untrusted, exit2: collection is partial or limited.blocked, exit3: the tool failed or the input is not a semantic-js-mcp result.
Pass --yaml after the input path for a YAML representation. The adapter accepts canonical JSON or YAML, validates the producer and result-schema version plus public tool and presentation literals, and never converts incomplete evidence into a pass.
lsp_count_text_matches measures a common identifier before semantic
verification. Compact tools omit operational metrics; detailed reference calls
retain timing, semantic request, concurrency, and memory observations. The
server applies no hidden candidate cap.
Language-server clients and reusable reference sets use idle timeout, TTL, and LRU policies. These policies govern reuse; they never impose a hidden limit on the collection in progress. Configuration literals and defaults are listed in the generated protocol reference.
npm run check
npm run check:runtime
npm run doctor
npm run smoke
npm run smoke:ci
npm run smoke:vue
npm run smoke:lifecycle
npm run smoke:distributionnpm run benchmark measures text counting, verified reference collection, memory, and freshness-validation latency at configurable match counts. Set SEMANTIC_JS_MCP_BENCHMARK_COUNTS=10,100,1000,10000 to include the 10,000-match scale.
npm run smoke:distribution packs the explicit npm file allowlist, installs the tarball into a temporary consumer project, runs the installed executable, and verifies that runtime components resolve from the consumer dependency tree rather than the source checkout.
The smoke tests create temporary generic TypeScript and Vue projects. They do not depend on a specific application repository.
Run semantic-js-mcp doctor and include its structured output, the package version, Node.js version, operating system, affected source type, and the smallest reproducible workspace or public repository. Remove proprietary source, credentials, local absolute paths, and customer data before opening an issue. See Contributing for validation details and the Security policy for private vulnerability reports.
- The server provides static semantic evidence, not runtime call tracing or behavioral proof.
- Empty references and clean diagnostics do not establish absence or correctness.
- Vue named-component discovery remains ambiguous when filenames, component names, import aliases, global registration, and test doubles differ. Prefer a position-based audit when an exact use is available.
- Diagnostics remain
untrustedwhen the owning language server does not correlate a report with the current document version. - Dynamic imports, computed property access, generated code, runtime dependency injection, and dynamically constructed class names may require text search and direct source inspection.
- CSS graph analysis, Tailwind semantics, and other language domains are intentionally outside this project. Provider-native diagnostics embedded in Vue documents may still be preserved.
See ROADMAP.md for planned areas of development. Roadmap items describe direction, not release commitments.