webnav-mcp
Navigates CSS stylesheets through the CSS language server, offering hover, go-to-definition, references and diagnostics for .css files, plus a cross-file index that tracks where CSS custom properties (--name) and #id/.class selectors are defined and used across CSS, HTML and JS.
Routes JS/TS files (.js/.mjs/.cjs/.jsx/.ts/.mts/.cts/.tsx) to TypeScript 7's native language server (tsc --lsp --stdio) to provide hover, definition, references, diagnostics, workspace symbol search, symbol info and file outlines for the navigated project.
webnav-mcp
⚠️ Deprecated — do not use this package. Use
webnav-ts-mcpfrom the npm registry instead (claude mcp add webnav -- npx webnav-ts-mcp). It is a TypeScript port with the same tools and environment variables, needs only Node.js (no Python oruv), and is the only version that will receive updates.
An MCP server that gives AI agents JS/TS/HTML/CSS navigation, plus a
cross-file index of CSS custom properties and #id/.class selectors that
single-file language servers can't provide. It's the front-end counterpart to
codenav-mcp.
Quick start
You need uv (or pipx) and Node.js ≥ 18:
uvx webnav-mcpRegister it with your MCP host. For Claude Code, from the project root:
claude mcp add webnav -- uvx webnav-mcpOr add it to a project .mcp.json (Claude Code) or .cursor/mcp.json (Cursor):
{
"mcpServers": {
"webnav": {
"command": "uvx",
"args": ["webnav-mcp"]
}
}
}In Cursor, also set "env": {"WEBNAV_MCP_WORKSPACE": "${workspaceFolder}"},
because Cursor may start MCP servers with your home directory as the working
directory.
Related MCP server: LSP MCP
Language servers
Requests are routed to three Node language servers by file extension:
Extension | Backend |
| TypeScript 7 native LSP: |
|
|
|
|
Resolution order for tsc / HTML / CSS binaries: navigated project's
node_modules/.bin/ → webnav's own package-local install (see Development) →
PATH → npx --yes (JS/TS: npx -p typescript@7 tsc --lsp --stdio). webnav
does not use typescript-language-server — TypeScript 7 no longer ships
classic tsserver.js.
To skip downloads, install in the project (or under this package for standalone):
npm install --save-dev typescript@^7 vscode-langservers-extractedTools
For JS/TS, start with the name-based tools:
Tool | Answers |
| What is this? Header, hover, definition and references in one call |
| What's in this file? (source order; locals left out unless |
| JS/TS workspace symbol search (ranked, capped; optional |
| Which directory is being navigated, and why |
Then use the position tools once you have a path:line:col:
Tool | Answers |
| Type and docs at a position |
| Go to definition (CSS/HTML tokens answer from the index below) |
| All usages (CSS/HTML tokens answer from the index below) |
| Language-server diagnostics; CSS/HTML also get unreferenced-selector and undefined-variable warnings |
Cross-file CSS/HTML index (a Python scanner, not the language servers):
Tool | Answers |
| Where is |
| Where is |
search_symbol, symbol_info and outline are JS/TS only. Use
css_var and selector for markup and stylesheets.
name and query are accepted as aliases of each other on the name-based
tools. A missing parameter gets a short hint back instead of a validation
error.
Positions are 1-indexed. column is a UTF-16 character offset (a leading
tab counts as one character).
Environment
Variable | Default | Purpose |
| unset: follows the client's MCP roots when they name a worktree of the same git repository, else | Pins the project root (never overridden). See the |
| the whole workspace as one root, labelled | Comma-separated |
| nothing | Comma-separated workspace-relative paths of generated script output (e.g. the JS a TS build emits). These aren't opened, are hidden from |
| nothing | Comma-separated workspace-relative stylesheets (files or directories) that are a public API, e.g. a design-token file consumed by other projects. |
Requirements
Python ≥ 3.11
Node.js ≥ 18 (for TypeScript 7's
tscshim and the HTML/CSS servers)Installed automatically:
mcp,mcp-nav-shared
Related
Design notes (index heuristics, dynamic selectors, positioning): docs/agent-tooling.md.
Development
Source: github.com/illescasDaniel/webnav-mcp. From a
checkout: uv sync --group dev, then npm ci in this directory (owns
typescript@^7 + vscode-langservers-extracted for standalone launch), then
uv run webnav-mcp.
License
MIT. See LICENSE.
Available Tools
10 toolscss_varA
Where is this --custom-property defined and used? Example: css_var(name="--bg").
The CSS/HTML language servers only see one file at a time, so var(--x)
usages can't be cross-referenced across files that way — this scans
.css files and HTML <style>/style="…" blocks/attributes instead.
name may be given with or without the leading --. Definitions (value
enclosing context, e.g.
@media (prefers-color-scheme: dark) › :root) and usages (grouped by file with line numbers) are reported separately per configured root (seeWEBNAV_MCP_ROOTS; a single unnamed root by default), since each may define its own values.queryis accepted as an alias forname.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the scan scope (`.css` files plus HTML style blocks/attributes), that definitions and usages are reported separately, and that results are grouped per configured root with `WEBNAV_MCP_ROOTS` controlling roots. It does not mention whether files must be saved/indexed or any performance/limit behavior, but the disclosure is otherwise rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The leading question plus example fronts the core intent effectively, and the parentheticals pack useful detail. The middle paragraph is dense and slightly run-on, but no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return structure needn't be explained, and the description instead explains what is reported (definitions with value/context, usages by file with line numbers) and the per-root grouping model. Combined with the alias/`--` handling, it is nearly complete for a two-optional-string tool, missing only edge-case behavior when no name is supplied.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does: it explains that `name` may be passed with or without the leading `--`, and that `query` is an accepted alias for `name`. It does not state the consequence of supplying neither or both, but both parameters are meaningfully documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource in question form (where is `--custom-property` defined and used) and immediately gives a call example. It distinguishes itself from siblings like `references`/`definition` by explaining that language servers are single-file and this tool scans across `.css` and HTML `<style>`/`style=` blocks instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly establishes the context in which this tool is needed — cross-file var() resolution that single-file language servers cannot do — which implies choosing it over `definition`/`references` for custom properties. However, it never explicitly states exclusions (e.g. 'use `references` for non-custom-property symbols'), so routing is inferred rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
definitionA
Go to the definition of the symbol at a position.
line and column are 1-indexed. column is a UTF-16 character offset
on the line (not a visual/display column): a leading tab counts as one
character. On a --custom-property/#id/.class token in a .css/
.html file (or a name inside an HTML id="..."/class="..." value),
answers from the cross-file index (see css_var/selector)
instead of the single-file language server: for definition, just the
definition(s) in the file's own root (each WEBNAV_MCP_ROOTS root
is separate); for references, that root's definitions and usages.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | ||
| column | Yes | ||
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it does so well: it discloses 1-indexed lines, UTF-16 column offsetting, tab-counting behavior, and the significant CSS/HTML cross-file-index routing instead of single-file LSP. It omits what happens when no definition is found (error vs. empty), keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose in one sentence, then adds warranted detail about indexing and the CSS/HTML special case. Slightly dense but no wasted sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation. The tricky parameter semantics and the CSS/HTML cross-file-index behavior are covered; the only real gap is the no-definition-found outcome.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It thoroughly explains `line`/`column` indexing (1-indexed, UTF-16 offset, tabs count as one character), which is the non-obvious semantics; `file_path` is self-evident. This meaningfully exceeds the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Go to the definition') and resource ('the symbol at a position'), and even contrasts with `references` in the CSS/HTML case. Clear enough to separate from siblings, though general sibling differentiation (hover, symbol_info) is only implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the standard LSP 'go to definition' semantic, and the CSS/HTML special case is explained. However, there is no explicit when-to-use/when-not guidance against alternatives like `hover`, `symbol_info`, or `references` for the common case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnosticsA
Get the relevant language server's diagnostics (errors/warnings) for a single file.
For .css/.html files, this also includes index-derived warnings the
single-file language server can't see: var(--x) used with no matching
declaration anywhere in the same indexed root, custom properties declared
but never used, and CSS selectors (#id/.class) with no HTML/JS
reference in that root (files under WEBNAV_MCP_PUBLIC are exempt from
the last two).
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does add real behavioral context: it explains that CSS/HTML files get index-derived warnings the single-file server cannot see, enumerates the three categories, and discloses an exemption rule for files under WEBNAV_MCP_PUBLIC. It stops short of stating whether the file must be open/indexed or whether the operation is strictly read-only.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action is front-loaded in the first sentence, with the CSS/HTML nuance properly relegated to a follow-up paragraph. Every sentence carries information; only the parenthetical category list is slightly dense for a description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description adds the scope and edge-case behavior an agent needs. The main remaining gap is the absence of any guidance on when this tool should be chosen over its sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for the single file_path parameter, so the description must compensate; it only implies a file argument via "for a single file." No format detail (absolute vs workspace-relative path) is given, leaving the parameter underspecified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with an explicit scope constraint ("for a single file"), which an agent can act on immediately. It does not explicitly differentiate itself from the overlapping siblings css_var and selector, even though its extra index-derived warnings touch exactly those domains, so sibling differentiation is only implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied (call it to get errors/warnings for a file) but there is no explicit when-to-use, no prerequisites, and no routing away from alternatives. Given siblings like css_var and selector that also surface variable/selector information, some statement of when diagnostics is the right pick would have helped.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hoverB
Get type/documentation info for the symbol at a position.
line and column are 1-indexed. column is a UTF-16 character offset
on the line (not a visual/display column): a leading tab counts as one
character.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | ||
| column | Yes | ||
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it discloses nothing about the operation's nature (read-only vs mutating), permissions, or output. It only clarifies coordinate semantics, which belongs more to parameter semantics than behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with zero filler, front-loading the tool's purpose before the parameter disambiguation. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described, and the tricky coordinate params are covered. However, with no annotations and no usage context, the description stops short of fully equipping an agent to pick this over its siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates well for the non-obvious parameters: it states line/column are 1-indexed and that column is a UTF-16 offset where a tab counts as one character. It leaves file_path unexplained, but that param is largely self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (type/documentation info) tied to a symbol at a position, which matches the well-known IDE 'hover' concept. It is clear on its own but does not explicitly differentiate itself from sibling tools like symbol_info or definition, which could plausibly overlap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use hover versus symbol_info, definition, or references, nor any exclusions. The phrase 'at a position' loosely implies usage, but alternative selection is left entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
outlineA
What's in this file? Example: outline(file_path="src/app.ts").
Indented outline (functions, classes, interfaces, with :start-end line
spans) of a JS/TS file in source order, so you can navigate without reading
it in full. Locals, callbacks and object-literal keys inside functions and
variables are left out; pass detailed=true to include them. Follow up
with hover/definition/references at a listed line, or symbol_info by name.
| Name | Required | Description | Default |
|---|---|---|---|
| detailed | No | ||
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and largely does so: it discloses the output shape (indented, source order, `:start-end` spans) and precisely what is excluded (locals, callbacks, object-literal keys) and how to include it. It omits error/edge behavior (non-JS/TS files, missing paths), but the output schema covers return structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the framing question and a call example, followed by the functional explanation and follow-up guidance. Every sentence earns its place, though the parenthetical 'What's in this file?' plus example is slightly redundant framing rather than content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter read tool with an output schema, the description covers inclusions, exclusions, the toggle, and next-step routing, which is essentially complete. The only gap is failure behavior for unsupported or missing files, which is minor given an output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does: `detailed=true` is explained as 'include' the otherwise-excluded locals, callbacks and object-literal keys, and `file_path` is demonstrated via the `outline(file_path="src/app.ts")` example. Both parameters gain meaning beyond the bare schema, though format expectations for file_path are only implied.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: an indented outline of functions, classes and interfaces with `:start-end` line spans for a JS/TS file, in source order. This is clearly distinguished from siblings like hover, definition, references and symbol_info, so an agent can select it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the reason to use it ('so you can navigate without reading it in full') and explicit routing to alternatives: 'Follow up with hover/definition/references at a listed line, or symbol_info by name.' It also names the condition that changes behavior (`detailed=true`). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
referencesA
Find all usages of the symbol at a position across the workspace.
line and column are 1-indexed. column is a UTF-16 character offset
on the line (not a visual/display column): a leading tab counts as one
character. On a --custom-property/#id/.class token in a .css/
.html file (or a name inside an HTML id="..."/class="..." value),
answers from the cross-file index (see css_var/selector)
instead of the single-file language server, limited to the file's own root
(each WEBNAV_MCP_ROOTS root is separate) unless it has no hits there.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | ||
| column | Yes | ||
| file_path | Yes | ||
| include_declaration | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it discloses meaningful behavior: which engine answers (cross-file index vs single-file language server), that results are scoped to the file's own root with separate WEBNAV_MCP_ROOTS, and the fallback when the scoped index has no hits. It omits any note on read-only semantics or result/pagination behavior beyond what the output schema covers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence, with positional semantics and the CSS/HTML edge case following in a logical order. The middle paragraph is dense but each clause conveys usable information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is unnecessary, and the description covers position semantics, the CSS/HTML token edge case, and root scoping. The one meaningful omission is what 'include_declaration' does, which affects results for a 4-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate; it does a strong job on the two error-prone parameters, specifying 1-indexing and UTF-16 offset semantics for 'column' (leading tab = one character). It leaves 'include_declaration' (default true) and 'file_path' unexplained, which is a notable gap for a result-shaping boolean.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Find all usages of the symbol at a position across the workspace.' This cleanly distinguishes it from the sibling 'definition' (goto-definition) and 'hover' (type info) without the agent needing to inspect either schema. Scope ('across the workspace') is explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by requiring a position (line/column) and by the CSS/HTML special-case paragraph, which routes to the cross-file index. However, there is no explicit when-to-use vs 'definition'/'search_symbol', and no stated prerequisites or exclusions for the normal language-server path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_symbolA
Search JS/TS files for a symbol by name (function, class, const, etc.).
JS/TS-only: the HTML/CSS language servers don't implement useful
workspace-wide symbol search (webnav does not reimplement it). Prefer
symbol_info for a one-call summary. Returned positions point at the
identifier name and use the same character-offset column convention as
the other tools. Results include a SymbolKind label and are capped.
name is accepted as an alias for query. Narrow broad queries with
kind (SymbolKind labels, comma-separated: class, function,method,
interface, ...) and path (workspace-relative prefix such as src/,
or a glob such as src/**/*.ts). Production code ranks before tests.
Loose fuzzy hits whose names don't contain the query are summarised as a
count when real matches exist; pass fuzzy=true to list them too.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | ||
| name | No | ||
| path | No | ||
| fuzzy | No | ||
| query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and delivers: it discloses that positions point at the identifier name using the same character-offset column convention as other tools, that results carry a SymbolKind label and are capped, that production code ranks before tests, and that fuzzy hits not containing the query are collapsed to a count unless `fuzzy=true`. These are non-obvious behavioral traits an agent could not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose and the alternative tool are front-loaded in the first two sentences, followed by progressively finer detail on semantics, ranking, and edge cases. Each sentence supplies distinct, actionable information and no sentence is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value structure need not be re-explained, yet the description still adds return-relevant context (position convention, SymbolKind label, capping, fuzzy collapsing). Combined with the JS/TS restriction, ranking behavior, and full parameter coverage, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must supply all parameter meaning, and it does: `name` as an alias for `query`, `kind` as comma-separated SymbolKind labels with examples, `path` as a workspace-relative prefix or glob with an example, and `fuzzy` as the switch that lists otherwise-summarised loose hits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource with explicit scope: searching JS/TS files for a symbol by name, with examples of the symbol kinds (function, class, const). It then distinguishes itself from the sibling `symbol_info` and explains the JS/TS-only boundary, so an agent can tell it apart from alternatives without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit alternative and the condition that selects it ('Prefer `symbol_info` for a one-call summary') and a clear when-not-to-use rule (HTML/CSS language servers don't support useful workspace-wide symbol search). It does not address the other symbol-oriented siblings such as `definition`, `references`, or `outline`, leaving a few routing choices to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
selectorA
Who uses this #id or .class? Example: selector(name=".card-title").
Looks up the selector across the whole workspace.
Cross-references CSS rule definitions, HTML id=/class= attributes,
and JS usages (getElementById, classList.add/remove/toggle/contains,
querySelector/querySelectorAll, className assignment, and any JS
string literal exactly equal to the bare name — e.g. an id passed to a
project's own helper like onClick("btn-save", …), labeled "string
literal"). Hits in generated output (WEBNAV_MCP_EXCLUDE) are labeled
[generated]; edit their source instead. This is something
the single-file CSS/HTML language servers can't do. name must include
the leading # or .. Grouped by file with line numbers, separately per
configured root (see WEBNAV_MCP_ROOTS). A JS hit built from string
concatenation (e.g. getElementById("view-" + x)) is reported against
only its static prefix and labeled "dynamic partial match"; a query whose
name starts with such a prefix (e.g. #view-components against a stored
#view-) also surfaces that hit, labeled "dynamic partial match via
''", instead of being silently dropped or guessed. query is
accepted as an alias for name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so richly: it enumerates the cross-referenced surfaces (CSS rules, HTML id/class attrs, JS APIs and bare string literals), labels generated hits `[generated]`, explains `dynamic partial match` and prefix-query behavior, and states grouping by file/line per root. A reader knows exactly what comes back and why.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and example are correctly front-loaded, but the body is a dense prose block mixing invocation rules, labeling semantics, and configuration env-vars (`WEBNAV_MCP_EXCLUDE`, `WEBNAV_MCP_ROOTS`) without structure. Most sentences earn their place, but readability suffers from lack of bullets or ordering.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a high-complexity cross-referencing lookup, the description covers the behavioral contract thoroughly, and an output schema exists so return shape needn't be re-explained. It stops short of stating read-only/auth posture, which would matter in the absence of annotations, but otherwise nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: it mandates the leading `#` or `.` on `name`, gives a concrete example, and declares `query` as an alias for `name`. It does not explain what happens if only one of the two aliases is supplied, but the key formatting constraint is covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The lead sentence 'Who uses this `#id` or `.class`?' plus the example call makes the specific verb (find usages) and resource (CSS selector) unambiguous. It distinguishes itself from generic single-file language servers, but never names or contrasts with the overlapping sibling `references`, so an agent must still infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'Looks up the selector across the whole workspace' and the example call, and it notes hits in `WEBNAV_MCP_EXCLUDE` output should be edited at source. However there is no explicit when-to-use-this-vs-`references`/`definition`/`hover` guidance despite those siblings clearly overlapping.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
symbol_infoA
What is X and where is it used? Example: symbol_info(name="renderSidebar").
One-call summary for a JS/TS name: header, hover text, definition, and
references grouped by file — the usual first lookup instead of chaining
search_symbol → hover → definition → references by hand. Pass file_path
to disambiguate; query is accepted as an alias for name. For CSS/HTML
cross-file lookups use css_var / selector instead.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| query | No | ||
| file_path | No | ||
| include_references | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden, and it does disclose the composite return shape (header, hover, definition, references grouped by file) and the query alias for name. It doesn't state read-only nature, defaults, or limits, and an output schema partly covers returns, but the aggregation behavior itself is well communicated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the question 'What is X and where is it used?', then a concrete example, then the substance and the CSS/HTML escape hatch. Every sentence earns its place; the example adds cost but also genuine invocation clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, yet the description helpfully summarizes what comes back and where to go for non-JS/TS lookups. Only the include_references flag and any disambiguation failure behavior are left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains name, the query alias, and file_path's disambiguation role, but says nothing about include_references — a boolean defaulting to true that materially changes the call. Three of four parameters are covered, one silently ignored.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific operation over a specific resource: a one-call summary for a JS/TS name returning header, hover text, definition, and references. It explicitly contrasts itself with the sibling chain (search_symbol → hover → definition → references), so an agent can place it immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names this as 'the usual first lookup' and gives the negative case ('For CSS/HTML cross-file lookups use css_var / selector instead'), plus the disambiguation condition for file_path. When-to-use, when-not, and alternatives are all explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workspaceA
Which directory is webnav navigating, and why? Use when results look like they come from the wrong checkout/worktree.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It implies a read-only diagnostic query (asking which directory is being navigated and why), but never states read-only semantics, permissions, or cost. With an output schema present, return-value detail is not required, which keeps this at a middling score.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, and the usage trigger follows immediately after the purpose. The interrogative framing is slightly quirky for a tool description but costs little space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter diagnostic with an output schema, the description supplies the essential missing piece: the failure condition under which to call it. The one gap is that it never plainly states what the tool returns or when it is irrelevant, but the output schema covers the return side.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to document. Baseline 4 applies; the description has nothing to add or omit here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description is phrased as a question ("Which directory is webnav navigating, and why?") rather than a specific verb+resource statement, so the agent must infer that this tool reports the active workspace/checkout directory and its rationale. It conveys the topic area but not the concrete operation, and it does nothing to distinguish itself from code-navigation siblings like outline or diagnostics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear, concrete trigger: "Use when results look like they come from the wrong checkout/worktree." This is an explicit situation in which to invoke the tool. It stops short of naming alternatives or stating when not to use it, so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.1.3- First observed
css_var - First observed
definition - First observed
diagnostics - First observed
hover - First observed
outline - First observed
references - First observed
search_symbol - First observed
selector - First observed
symbol_info - First observed
workspace
TDQS
Scored across 10 tools
Most tools have clearly distinct purposes: hover/definition/references are standard position-based LSP queries, css_var and selector target distinct cross-file resource types, and workspace is a unique diagnostic. The only real overlap is search_symbol vs symbol_info (both accept a name), but the descriptions explicitly frame symbol_info as the one-call summary wrapper, which should steer selection correctly.
All names are lowercase and use snake_case for multi-word names (search_symbol, symbol_info, css_var), with single-word names for the rest, so there is no case or delimiter mixing. However, there is no unifying verb_noun pattern—several tools are bare nouns (hover, definition, references, diagnostics, outline)—so it is consistent in style but not in grammatical shape.
Ten tools is a well-scoped set for a code-navigation server: four core LSP-style primitives, three navigation helpers (outline, search_symbol, symbol_info), two cross-file CSS/HTML index lookups, and one workspace diagnostic. Each tool maps to a distinct workflow and none feel padded.
The surface covers navigation (definition, references, hover, outline, symbol search), diagnostics, and cross-file CSS/HTML lookups well, with clear coverage of the stated JS/TS/CSS/HTML domain. Minor gaps remain—no rename, call hierarchy, implementation lookup, or general textual/file search—but these are outside the apparent navigation-focused scope and agents can work around them.
Maintenance
Related MCP Connectors
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Coding agents in multi-service codebases routinely rebuild existing helpers, trust stale type definitions, and modify API contracts without knowing who consumes them. Carrick solves this by indexing your entire TypeScript ecosystem across service and repository boundaries. By integrating deeply with the TypeScript compiler, Carrick traces every route, type, and cross-service call while recording function behaviour so agents search by intent rather than name. Delivered via MCP for AI agents and LSP for IDEs, Carrick ensures models see existing endpoints and utilities before generating new code. The scanner is source-available and runs from your CLI or CI pipeline.
Give your AI agent a persistent map of your project's structure, dependencies, and bugs.
Codebase intelligence for AI agents — dead code, blast radius, ownership.
Related MCP Servers
- AlicenseBqualityDmaintenanceExposes TypeScript Language Server Protocol functionality to AI agents, enabling them to query types at specific positions, find definitions and references, get diagnostics, run type tests, and type-check inline code just like in an IDE.9210 npm3MIT
- AlicenseNot gradedqualityDmaintenanceProvides AI agents with language-aware code analysis through the Language Server Protocol, enabling tasks like getting code insights and diagnostics.6 npm192MIT
- AlicenseNot gradedqualityDmaintenanceExposes type-aware code navigation and fast file search to AI agents via language servers, enabling definitions, references, symbols, and file lookup without reading entire codebases.3,131 npmMIT
- AlicenseAqualityBmaintenanceEnables AI coding agents to interact with TypeScript projects through compiler-level code intelligence, providing tools for navigation, type information, diagnostics, refactoring, and semantic search.29122 npm3Apache 2.0