hebros-mcp
Supports npm workspace packages when resolving dependencies and references across a monorepo.
Supports pnpm workspace packages when resolving dependencies and references across a monorepo.
Indexes TypeScript and TSX codebases, providing symbol locations, imports, dependencies, and references, and understands tsconfig path mappings.
Supports Yarn workspace packages when resolving dependencies and references across a monorepo.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@hebros-mcpWhere is thebuildEdgesfunction defined?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Hebros MCP
An MCP server that gives coding agents a map of your codebase.
To find its way around a project, an agent usually lists folders, searches for text, and reads whole files. Every one of those steps costs tokens. Hebros reads your code once and then answers directly: where something is defined, what a file imports, who calls a function.
TypeScript and TSX. Nothing to configure, nothing running in the background.
The index is one JSON file in ~/.cache/hebros, kept up to date from git as you
edit.
Setup
Needs Node 22 or newer. Any MCP client works — point it at the hebros binary.
Opencode
In opencode.json:
{
"mcp": {
"hebros": {
"type": "local",
"command": ["npx", "-y", "hebros-mcp", "--root", "/path/to/repo"],
"enabled": true
}
}
}Claude Code
claude mcp add hebros -- npx -y hebros-mcp --root /path/to/repoThe first hebros names the server locally, so its tools appear as
mcp__hebros__get_map. The second is the npm package.
Codex
In ~/.codex/config.toml:
[mcp_servers.hebros]
command = "npx"
args = ["-y", "hebros-mcp", "--root", "/path/to/repo"]--root is optional. Without it, Hebros indexes the folder you run it in, or
whatever HEBROS_ROOT points at.
Related MCP server: Semantic JS MCP
What the agent gets
Tool | Answers |
| What's in this file or folder? Every name with its line number, no code bodies. For a file, also what it imports and what imports it. |
| Where is |
| What does this file or package use, and what uses it? |
| Where is |
| Force a refresh. You rarely need it — the other tools stay current on their own. |
For example, asking find_symbol("buildEdges") gets back:
src/imports.ts:427-445 + function buildEdges: export function buildEdges(...)One line, instead of hunting through folders and opening three files.
Every answer stays under about 6 KB. When there's too much to fit, you get a short summary saying where to look next, rather than a list that quietly stops halfway.
The first question builds the index, which takes well under a second for a few hundred files. After that Hebros asks git what changed and re-reads only those files, so answers come back in milliseconds.
It uses fewer tokens
Every file an agent opens fills up the space it has to think in. A map of a file is much smaller than the file.
Here is what that looks like on a real project of 324 files:
To answer | Without Hebros | With Hebros | |
What's in this file? | read it — 4.5 KB | a map of it — 1.4 KB | 3x smaller |
Where is | search — 8 KB of matches to read | one line — 217 B | 37x smaller |
What's in this project? | a list of files — 13 KB | a map — 365 B | 36x smaller |
Across 230 files, that is roughly 260,000 tokens of reading turned into 52,000.
How much you save depends on what you ask. A name used in 40 places is where it helps most, because searching for it hands back 40 lines to read. A name used once saves only about half. And on a small project — say 20 files — the map is no smaller than a plain file list. What you get there is a precise answer rather than a shorter one.
Good for local models
This helps most when there isn't much room. A model running on your own machine usually has space for 8,000 to 32,000 tokens, so one or two large files can use it all up. The model also has to read the whole prompt before it says anything, so a shorter prompt means a faster first word.
Hebros does the reading up front, on the CPU, and hands over a few hundred bytes of ready-made answer. That leaves the space free for the actual work.
Good to know
TypeScript and TSX only. Other languages need a small adapter.
get_referencesmatches names as text, not by type. For a common name, passfileto narrow it down.It understands tsconfig
pathsand workspace packages (pnpm, npm, yarn).The index is plain JSON. Comfortable up to a few thousand files.
More
docs/DESIGN.md — how the index works and why it's built this way
CONTRIBUTING.md — local setup and ground rules
License
MIT — see LICENSE.
Available Tools
5 toolsfind_symbolFind symbol definitionA
Exact file:line where a function/class/interface/type/const is defined, from the symbol index. Use instead of grepping for definitions. Then read only that line range.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Optional filter: class | function | const | interface | type | enum | method | property. | |
| name | Yes | Symbol name (exact, falls back to word-part match). | |
| file_glob | No | Restrict to files matching a glob, e.g. "packages/ui-web/**". | |
| exported_only | No | Only exported symbols (the public API of an area). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It usefully discloses that results come from the symbol index and are exact file:line locations, implying a read-only lookup. However, it does not mention potential multiple matches, index staleness, or what happens when a symbol is not found.
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 description is compact and information-dense. Each sentence earns its place: what it returns, when to prefer it, and the follow-up action for the agent. No filler or redundant schema repetition.
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?
The tool has no output schema, but the description provides the essential return contract ('Exact file:line') and a practical next step. It is complete enough for straightforward definition lookups, though it could mention disambiguation behavior around multiple matches or how the symbol index stays current.
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 input schema already describes all four parameters with 100% coverage, so the description need not repeat them. The description adds little beyond naming some symbol kinds, while the schema already covers exact/fallback matching, file_glob, and exported_only.
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 clearly states the tool's job: return the exact file:line where a symbol is defined, sourced from the symbol index. It includes a specific resource ('symbol index') and output type, but it does not explicitly differentiate from sibling tools like get_references.
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?
The description gives practical guidance: use this instead of grepping for definitions, and then read only the returned line range. This is clear context, though it does not explicitly name sibling alternatives or state when not to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_depsGet import dependenciesA
Import graph for one file OR a whole directory/package: what it imports and who imports it. Directory mode aggregates edges (N files -> target). Use for impact analysis before refactoring ("what breaks if I change this package?").
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | File or directory path relative to the repo root. | |
| direction | No | Which edges to show. | both |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden, and it explains important behavior: directory mode aggregates edges (N files -> target) and the graph includes both imports and importers. It doesn't detail result shape or directory-scale caveats, but for a non-mutating read tool it is fairly transparent.
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?
Three tight sentences; core behavior is front-loaded, then the special directory-mode behavior, then one practical use case. No repetition or 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?
For a two-parameter read-only graph query with no output schema, the description plus schema covers the caller's main needs: path semantics, edge direction options, directory aggregation, and a motivating scenario. The main gap is that no explicit return structure or size/performance caveat is given.
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 already 100%, so the baseline is 3; the description adds extra meaning by explaining that 'what it imports' corresponds to outgoing edges and 'who imports it' to incoming edges, and by clarifying directory mode as an aggregation behavior for the file parameter.
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 clearly identifies the tool as an import-graph query covering both outgoing and incoming edges for a file or directory/package. It is specific about what it does, though it doesn't explicitly contrast it with siblings like get_references or find_symbol.
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 concrete use case ('impact analysis before refactoring') and when directory mode applies, which orients the agent toward selecting this tool. It doesn't state when not to use it or name alternatives, so it falls just short of full guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_mapGet code mapA
Structure of a file or directory from the prebuilt index: every symbol with its line number and one-line signature, NO bodies. For a file, also shows what it imports (with each dependency's main exports) and who imports it. Cheaper than reading the whole file or globbing directories. Use BEFORE reading any file to decide which exact lines you need.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | File or directory path relative to the repo root (e.g. "src" or "src/server.ts"). "." = whole repo. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full burden of behavioral disclosure. It transparently explains what the tool returns, what it excludes ('NO bodies'), the fact it uses a prebuilt index, and that it is cheaper than alternatives. It could add detail about index freshness or error behavior, but the core behavior is clearly disclosed.
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 description is concise and front-loaded: it states the resource, the exact content of the result, and the key exclusion in the first sentence. The second sentence adds file-specific behavior, and the final sentence gives the practical usage timing. 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?
For a single-parameter tool with no output schema, the description is complete enough: it explains the returned symbols, line numbers, signatures, imports, importers, and the exclusion of bodies. It also provides guidance on when to call it. This gives an agent sufficient context to invoke 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 coverage is 100%, and the single 'target' parameter is already fully documented in the schema, including the '.' special value. The description reinforces the file-or-directory target concept and the prebuilt-index context, but it does not add meaningful param semantics beyond the 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?
The description clearly states the tool's purpose: returning the structure of a file or directory from a prebuilt index, including symbols, line numbers, and one-line signatures while explicitly excluding bodies. It is specific about the resource and content, but it does not explicitly distinguish itself from sibling tools like get_deps, find_symbol, or get_references, some of which may overlap with the reported imports/importers.
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?
The description gives an explicit usage directive: 'Use BEFORE reading any file to decide which exact lines you need.' It also frames when it is better than reading files or globbing directories. However, it does not state when not to use it or mention alternatives among the sibling tools, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_referencesGet symbol referencesA
Where a symbol is used: JSX component usages, call sites (with line numbers), which files import it by name, and where the name is written without being called — string keys, object keys, property reads (how registries, event names and route tables wire things together). Use instead of grep-ing for usages. Heuristic — for a common name, narrow with file.
| Name | Required | Description | Default |
|---|---|---|---|
| file | No | Restrict to one file (repo-relative). | |
| name | Yes | Symbol name (function/class/method/component as written at usage sites). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses that the tool is heuristic, warning that common names may need narrowing, which is a key behavioral trait. It also describes the types of usages returned, but does not mention performance, error handling, or whether it is read-only, leaving some gaps.
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 description is concise and front-loaded with the core purpose: 'Where a symbol is used.' It efficiently lists specific usage types and ends with a practical heuristic. The structure is logical and free of fluff, making it easy for an agent to parse quickly.
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?
The tool has no output schema, so the description needs to convey what the agent should expect. It does so by enumerating the kinds of usages returned (JSX, call sites with line numbers, imports, property reads). It also provides a usage heuristic, which is valuable context. Missing details include handling of no results or potential large result sets, but overall it is adequate for a 2-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?
The schema already provides full descriptions for both parameters (name and file) with 100% coverage. The tool description reinforces the 'file' parameter's purpose with the heuristic 'narrow with file,' but does not add significant new meaning beyond the schema. Baseline of 3 is appropriate since the schema does the heavy lifting.
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 clearly states the tool's function: finding where a symbol is used, listing specific types of usages (JSX, call sites, imports, property reads). It distinguishes itself from siblings by its focus on usages rather than definitions or dependencies. The verb 'get' and resource 'references' make the purpose unambiguous.
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?
The description explicitly says 'Use instead of grep-ing for usages,' providing a clear alternative. It also includes a heuristic: 'for a common name, narrow with file,' which guides when and how to use the tool. However, it does not explicitly compare with sibling tools like find_symbol or get_deps, though the purpose is clear enough to infer appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reindexRefresh the indexA
Incremental git-based refresh (only changed files are re-parsed). Rarely needed — tools auto-refresh.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It discloses the incremental nature ('only changed files are re-parsed') and the fact that tools auto-refresh, which informs the agent that this is an exceptional maintenance action rather than a routine one.
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 convey the mechanism, scope, rarity, and necessity. Every word earns its place, and the key guidance ('Rarely needed') is positioned after the core behavior without clutter.
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 maintenance tool with no output schema, the description is complete: it explains what it does, how it works, and when it should be used. No critical information is missing for an agent to decide whether to invoke it.
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 has zero parameters, and the schema coverage is effectively complete. The description adds meaningful context by implying the refresh uses the git history rather than requiring any input, which is sufficient for a parameterless tool.
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 uses a specific verb ('refresh') with a clear resource ('index') and explains the mechanism ('git-based refresh'). It is immediately distinguishable from the query-oriented sibling tools like get_map and find_symbol.
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?
The description explicitly tells the agent when not to use the tool: 'Rarely needed — tools auto-refresh.' This gives clear context that manual invocation is usually unnecessary, though it does not name specific alternatives for when manual refresh would be appropriate.
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.
5 tool updates
v0.3.0- First observed
find_symbol - First observed
get_deps - First observed
get_map - First observed
get_references - First observed
reindex
TDQS
Scored across 5 tools
Each tool has a distinct primary intent, but get_map, get_references, and get_deps all overlap on reporting 'who imports it', and get_map and find_symbol both expose symbol locations. The descriptions mitigate the ambiguity, but an agent could still misselect for import/usage questions.
Most tools follow a verb_noun snake_case pattern (get_map, get_references, get_deps). find_symbol and reindex are minor deviations but still use the same action-first, lowercase-with-underscore style, so the naming remains predictable.
Five tools is a well-scoped count for a code-intelligence server. Each tool covers a distinct mode of interaction: refresh, definition lookup, structure overview, reference search, and dependency analysis.
The toolset covers the core workflow of navigating a codebase: locating definitions, browsing structure, finding usages, and analyzing dependency impact. The main gap is the lack of fuzzy or pattern-based symbol search, since find_symbol appears to require exact names.
Maintenance
Related MCP Connectors
Give your AI agent a persistent map of your project's structure, dependencies, and bugs.
Stateless TS/JS compiler facts for agents: references, imports, impact. No repo index or OAuth.
Shared memory for coding agents. Stop re-explaining your codebase every session.
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.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceA navigable symbol map of your codebase for coding agents, enabling efficient code navigation and reading only relevant symbols instead of entire files.MIT
- AlicenseNot gradedqualityAmaintenanceProvides structured semantic context for JavaScript/TypeScript codebases, enabling coding agents to navigate, review, and change code with explicit uncertainty.18 npm1MIT
- AlicenseNot gradedqualityBmaintenanceContext compiler for AI coding agents that indexes TypeScript codebases to extract and serve only the relevant symbols and files for a task, reducing token usage and search overhead.1MIT
- FlicenseNot gradedqualityAmaintenanceProvides efficient code navigation and graph-based analysis for AI agents, enabling symbol resolution, callers, implementations, and type schemas with minimal token usage.-