webnav-ts-mcp
Indexes and navigates CSS across the workspace: locates where custom properties (--name) and #id/.class selectors are defined and used across stylesheets, HTML and JS, and surfaces CSS diagnostics including unreferenced-selector and undefined-variable warnings (with an option to mark public stylesheets as an external API).
Provides name-based and position-based navigation of JS/TS source via the TypeScript 7 native language server: symbol info (header, hover, definition, references), file outlines, call hierarchy (callers), interface/class/method implementations, ranked workspace symbol search, hover/definition/references and diagnostics.
webnav-ts-mcp
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 needs only Node.js and installs
with a web project's own package manager.
Quick start
You need Node.js ≥ 20:
npx webnav-ts-mcpRegister it with your MCP host. For Claude Code, from the project root:
claude mcp add webnav -- npx webnav-ts-mcpOr add it to a project .mcp.json (Claude Code) or .cursor/mcp.json (Cursor):
{
"mcpServers": {
"webnav": {
"command": "npx",
"args": ["webnav-ts-mcp"]
}
}
}In Cursor, also set "env": {"WEBNAV_MCP_WORKSPACE": "${workspaceFolder}"},
because Cursor may start MCP servers with your home directory as the working
directory.
To pin it per project instead of resolving through npx each time:
npm install --save-dev webnav-ts-mcpRelated MCP server: ts-language-mcp
Language servers
Requests are routed to three Node language servers by file extension:
Extension | Backend |
| TypeScript 7 native LSP: |
|
|
|
|
They are ordinary npm dependencies, so nothing is downloaded at runtime. A TypeScript ≥ 7 in the navigated project wins; otherwise the copy installed with webnav-ts-mcp is used. (An app on an older TypeScript still works, at the cost of the extra install size: see Costs.)
Tools
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 and imports left out unless |
| Who calls this function/method? (call hierarchy) |
| Who implements/extends this interface, class or method? |
| 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:
Tool | Answers |
| Where is |
| Where is |
search_symbol, symbol_info, outline, callers and implementations 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.
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). Not opened, 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. |
Layout
src/
cli.ts stdio entry point (exits when the host closes stdin)
server.ts registers the twelve tools on the MCP SDK
webnav.ts the tools as plain async functions returning text; owns all state
webIndex.ts CSS var / selector index
langCommand.ts how to launch tsc / html / css language servers
glob.ts just enough glob for jsconfig `include`
shared/ lspClient, format, resolve, workspace, notices, errors,
params, exclude
tests/ vitest; fixtures/sample-app is the shared fixtureDevelopment
npm install
npm run check # biome + tsc + vitest (pretest builds dist/)
npm run upload # check + publish to npm (--build-only / --dry-run / --otp CODE after `--`); needs `npm login`
npm run test-package # install the published version in a throwaway project and drive it over MCP stdio
node bin/launch.mjs # checkout launcher: installs + builds when needed, then starts the serverSource: github.com/illescasDaniel/webnav-ts-mcp.
Design notes
webnav is glue: it spawns three Node language servers and formats their answers,
plus a regex-grade index.
Tests: vitest (unit tests for the index/format code, real language servers
against the fixture, MCP protocol over an in-memory transport incl. worktree
selection via client roots with a real git worktree, LSP client failure modes,
and the built executable).
Things worth knowing
The MCP SDK's stdio server does not treat stdin EOF as a close. With a language server child alive, the process kept running after the host went away (found by installing the tarball and launching via
npx).cli.tsnow handlesstdinend/close;tests/cli.test.tsfails without it.Columns are UTF-16 offsets, which is what LSP uses and what JS strings already are, so no conversion is needed.
Regex index limit:
\wis ASCII in JS. The index regexes use(?<![\w-])to avoid matchingdata-id=, so a non-ASCII letter directly beforeid=/class=/style=still counts as a match. Vanishingly rare in real markup.Inherited-member lookup needs a different approach. TypeScript 7's language server advertises no type hierarchy (checked against its
initializecapabilities), so a member declared on a base class can't be found that way. webnav reads theextends/implementsclauses from the source and resolves each base withtextDocument/definition, breadth-first across files (generic bases, qualified names and mixin calls handled;.d.ts/node_modulesbases aren't followed).callersandimplementationsare offered because the server advertisescallHierarchyProviderandimplementationProvider.
Costs
Install size: a fresh app installing this next to its own TypeScript 5: 177 MB
node_modules(vscode-langservers-extracted66 MB, TypeScript 7 ~50 MB with its native binary). An app already on TypeScript ≥ 7 shares that copy.Not verified: Windows, macOS, Node 20/24. Only Linux + Node 22.
License
MIT. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Codebase intelligence for AI agents — dead code, blast radius, ownership.
Code intelligence platform for AI agents. 20 tools for architecture, security & impact analysis.
Give your AI agent a persistent map of your project's structure, dependencies, and bugs.
Related MCP Servers
- 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
- AlicenseNot gradedqualityBmaintenanceEnables LLM agents to efficiently understand and navigate a codebase by providing semantic search over symbols and a reference graph, replacing expensive grep/glob calls with structured tools like definition lookup, caller/callee queries, and change-impact analysis.3MIT
- FlicenseNot gradedqualityAmaintenanceProvides efficient code navigation and graph-based analysis for AI agents, enabling symbol resolution, callers, implementations, and type schemas with minimal token usage.-