Skip to main content
Glama

jarvis

CI PyPI Python Platforms License: MIT MCP

Local-first code intelligence for coding agents. Precomputed SCIP navigation (go-to-definition, find-references, call/type hierarchy, document symbols), Zoekt lexical search, natural-language semantic search, and cross-repo blast radius — exposed as ten MCP tools for Claude Code, Cursor, or any MCP client.

One indexing CLI writes up, one stdio runtime reads down — the storage seam in ~/.jarvis is the only contract between them. No server, no auth, no network, nothing leaves your machine.

What is it? · How it works · Quick start · MCP tools · Requirements and limits · Indexing · Configuration · Documentation

What is it?

Without jarvis, asking your agent "where is AuthService used?" means grepping for the string, re-reading whole files to filter false positives, and guessing at call sites — burning context window on search instead of reasoning.

With jarvis, the agent calls findReferences and gets exact file-and-range occurrences from a precomputed SCIP index, callHierarchy for the call graph, and semanticSearch for questions like "where is token refresh handled?" in plain language.

Think of it as grep, but matching symbols, definitions, and references — indexed once per repo, answered in milliseconds.

  • Declaration-level navigation without any indexer — a Tree-sitter syntax baseline (17 languages) is built on every jarvis index run from pip-installed grammars, no compiler or build system required — on top of a precomputed SCIP index for full precise navigation (TypeScript/TSX, Python, Java/Kotlin, Swift), Zoekt lexical search, and optional vector search, all from local SQLite/LanceDB files.

  • Read-only by design. jarvis never edits code; it is the retrieval half. If you want an agent that performs semantic renames and refactors, you want Serena — the two are complementary.

jarvis is deliberately narrow: one language per repo, macOS/Linux only, and indexing is an explicit step — see Requirements and limits before installing.

Related MCP server: grepsense

How it works

Storage is the seam. The runtime half only ever reads down into it; the indexing half only ever writes up into it; the two share no other contract. Three load-bearing consequences:

  • The runtime path never writes. Index files are never mutated in place.

  • Publishing is atomic. A reindex writes a new versioned .db, populates the package graph, and runs zoekt-index — only once all of that succeeds does os.replace (POSIX rename(2)) flip the small current pointer. A query already reading the old file keeps working; there is no downtime window, and a failure anywhere leaves the previously published index live.

  • The package graph is rebuilt, not accumulated. Each reindex clears that repo's own outgoing edges before recomputing them, so blastRadius always reflects each repo's last index run.

Layer-by-layer detail, the full index pipeline, and the semantic path are in docs/system-architecture.md. Core query/search logic is ported from an internal reference implementation; the enterprise shell (FastAPI, Postgres, hosted-git auth, Cloud Build) is dropped in favor of a single stdio process reading local SQLite files.

Quick start

1. Install the external indexer binaries (only needed for optional SCIP navigation and Zoekt search — the Tree-sitter syntax baseline ships inside the pip package and needs no external binary): scip, zoekt, per-language indexers:

curl -fsSL https://raw.githubusercontent.com/jarvis-intelligence/jarvis-index/main/setup.sh | sh

2. Install jarvis:

uv tool install jarvis-mcp

3. Index a repo (slug defaults to the directory name):

jarvis index /path/to/your/repo

4. Register the MCP server. Using Claude Code, install the plugin and it registers itself:

/plugin marketplace add jarvis-intelligence/jarvis-index
/plugin install jarvis@jarvis

Any other MCP client (or Claude Code without the plugin) registers manually:

claude mcp add jarvis --scope user -- jarvis-server

That's it — ask your agent "find all references to AuthService" and it will call findReferences instead of grepping.

{
  "mcpServers": {
    "jarvis": {
      "command": "jarvis-server"
    }
  }
}

If your client can't find jarvis-server on PATH (GUI apps often don't inherit your shell's), use the absolute path from which jarvis-server.

git clone https://github.com/phuongddx/jarvis && cd jarvis
uv sync
claude mcp add jarvis --scope user -- uv --directory "$(pwd)" run jarvis-server
uv tool install "jarvis-mcp[watch]"      # + watchdog, for `jarvis watch`
uv tool install "jarvis-mcp[semantic]"   # + lancedb/sentence-transformers, for semanticSearch

MCP tools

| goToDefinition | Resolve a symbol to its defining file and range — SCIP when the file has SCIP definition coverage, otherwise the syntax baseline's declaration; each location carries source ("scip" or "tree-sitter") and positionEncoding | | findReferences | Every occurrence of a symbol across the indexed repo — SCIP-only: without usable SCIP occurrence data it returns requiredCapability/reason/recovery, never an empty list | | callHierarchy | Incoming/outgoing calls for a symbol — SCIP-only (same contract as findReferences) | | typeHierarchy | Supertypes/subtypes — SCIP-only; needs an index built with the bundled scip, see limitations | | documentSymbols | Outline of every symbol defined in one file — routed per file: the SCIP outline when usable, otherwise Tree-sitter declarations; a syntax-served response carries a coverage object (parsed/partial/failed counts and reason) | | searchCode | Zoekt lexical/regex search, optionally filtered to one repo | | semanticSearch | Natural-language search — vector hits fused with Zoekt lexical hits and SCIP symbol-definition matches via reciprocal rank fusion | | blastRadius | Which other indexed repos depend on a package, up to 2 hops | | getIndexStatus | Published commit, freshness, staleness vs. a working tree; capabilities.tools reports per-tool providers, capabilities.syntax reports extraction counts, and freshness names the snapshot generation | | indexRepo | Build an index for a git repo at path so the other tools have something to read. Returns immediately; poll getIndexStatus. semantic defaults to false. |

documentSymbols/goToDefinition are per-file provider routed: a file with usable SCIP coverage is answered by SCIP (full identifiers, references, hierarchies); a file without it is answered by the syntax baseline's real Tree-sitter declarations, whose opaque syntax: identifiers round-trip through goToDefinition. Bare or qualified names search both providers, so an ambiguous name returns combined candidates from both.

Every nav tool takes repo (the slug from jarvis index) plus a tool-specific symbol or path. All tools report failure the same way — a {"error": "..."} payload rather than a transport-level error, so a query bug never kills the stdio server.

Requirements and limits

Read this before installing — jarvis is deliberately narrow.

  • macOS and Linux only. Windows is not supported.

  • One language per repo. Language is detected by extension plurality across git-tracked files; a polyglot monorepo gets indexed as whichever language has the most files. Multi-language merge is out of scope. Override with --language.

  • Build-free syntax baseline covers 17 languages — Python, JavaScript, TypeScript/TSX, Java, Kotlin, Swift, Go, Ruby, Rust, C, C++, C#, PHP, Scala, Bash, and SQL — served by documentSymbols/goToDefinition as declaration outlines. Grammars are pip-installed dependencies of the package itself (no external binary, no download at index time); a repo with none of these still gets Zoekt search.

  • Precise SCIP navigation (findReferences, callHierarchy, typeHierarchy) covers four language families: TypeScript/TSX, Python, Java/Kotlin, Swift. These tools require real SCIP data — without it they explain what is missing and how to retry rather than returning empty results.

  • Navigation and search only — jarvis never edits code. If you want an agent that can perform semantic renames and refactors, you want Serena; the two are complementary.

  • Indexing is a separate, explicit step. Nothing is live-analyzed. Run jarvis index (or jarvis watch) to publish an index before querying.

  • Optional SCIP/Zoekt enrichment requires external binaries that setup.sh installs (the syntax baseline itself ships in the wheel):

    Purpose

    Binary

    Source

    SCIP → SQLite conversion

    scip

    prebuilt, pinned v0.9.0 (minimum — older versions silently drop occurrence ranges)

    Lexical search

    zoekt-git-index · zoekt-webserver

    cross-compiled by our CI — upstream publishes no binaries

    Zoekt symbol queries (sym:)

    universal-ctags

    system package manager via setup.sh — without it sym: silently returns nothing

    TypeScript indexing

    scip-typescript

    npm install -g

    Python indexing

    scip-python

    npm install -g

    Swift indexing

    scip-swift

    prebuilt, macOS arm64 only

    Java/Kotlin indexing

    scip-java

    detect-only — Docker image, asks before pulling

    Options: --only <name> to install one dependency, --force to reinstall, --help for usage. Re-running is safe: anything already present is skipped.

Indexing a repo

jarvis index /path/to/your/repo            # slug defaults to the directory name
jarvis index /path/to/your/repo --slug foo # or pick one explicitly
jarvis index /path/to/your/repo --scheme MyScheme # Swift repo with an ambiguous Xcode scheme
jarvis index /path/to/your/repo --language python # force the language instead of detecting it from git-tracked files
jarvis index /path/to/your/repo --semantic-include vendor/generated # force-include a path the generated-file filter would otherwise skip
jarvis index /path/to/your/repo --no-scip   # skip optional SCIP enrichment; the syntax baseline + Zoekt still publish (exit 0)
jarvis index /path/to/your/repo --scip      # re-enable SCIP enrichment (both flags persist per repo)
jarvis list
jarvis status foo
jarvis reindex foo
jarvis forget foo
jarvis dashboard [--port N] [--no-open]    # localhost web console over ~/.jarvis

status (as shown by both list and status) is one of indexing (run in progress), indexed (baseline published, SCIP usable/disabled/unsupported), partial (published, but the snapshot has documented syntax/SCIP extraction gaps), degraded (published, but the enabled SCIP stage failed, is missing, or is watch-suppressed — exit 0, cause and jarvis reindex <slug> --scip recovery recorded), or failed (a required stage/storage/publication failure — nothing new published; the previous snapshot stays live).

--semantic-include is repeatable — pass it once per path prefix to force-include several. Like --scheme and --language, once set there is no flag to clear it; change it by re-running jarvis index with the new value(s).

Language detection counts source files by extension across git-tracked files and picks the winner — one language per index:

Extensions

Indexer

.ts .tsx

scip-typescript

.py

scip-python

.java .kt

scip-java

.swift

scip-swift

Ties break by fixed priority (.ts.tsx.py.java.kt.swift). .git, node_modules, .venv, __pycache__, dist, and build are skipped. Reading git rather than walking the filesystem is deliberate: a walk also counts gitignored scratch directories, which can outnumber a repo's own code and pick a language it doesn't use.

The pipeline then runs in stages: capture tracked files and build the syntax baseline (scratch) → optional SCIP indexer + scip expt-convert (failures degrade to exit-0, never blocking the baseline) → zoekt-index into ~/.jarvis/.zoekt (its failure fails the run) → optional semantic embeddings → graph edge update → publish everything as one immutable ~/.jarvis/scip/_/<slug>/_/index-<sha>-<generation>.db snapshot → atomic current pointer flip → registry update → old snapshots retired.

The scip/_/<slug>/_/ path shape reuses the vendored IndexConnectionCache's (project, repo, branch) 3-tuple layout with the outer two pinned to _ (see src/jarvis/config.py). It is not a user-facing contract — only <slug> matters when calling tools.

Swift indexing works end-to-end. It requires scip >= v0.9.0: older converters cannot read scip.proto's typed_range oneof, which is the only range encoding scip-swift emits, and silently produce an index with no navigable positions. jarvis index refuses an older scip rather than publishing one.

Indexing a Swift repo with code-signed app-extension targets additionally requires scip-swift >= v0.1.2: earlier versions pass no code-signing overrides to xcodebuild, which then fails provisioning for every signed target before compiling anything. Because setup.sh skips any dependency that is merely present, an existing install is not upgraded by re-running it — use sh ./setup.sh --only scip-swift --force.

Dashboard

jarvis dashboard          # serves http://127.0.0.1:6080 and opens a browser

A localhost web console over the same ~/.jarvis data the CLI and MCP server read — watch index runs and call the tools from a browser, no MCP client involved:

  • Repos — every registered repo with status, freshness, and a live tail of its index log; index a path, reindex, or forget a repo (forget makes you type the slug to confirm).

  • Repo detail — one repo's published snapshots, per-tool capabilities, recovery guidance, package-graph edges, and storage footprint.

  • Search — one query answered three ways (Zoekt lexical, semantic vector, SCIP symbols), scoped to one repo or across all, with an in-browser source viewer for any hit.

  • Playground — invoke any of the ten MCP tools with typed parameters and inspect the raw JSON response.

Index and reindex spawn the same detached jarvis index children as the indexRepo MCP tool — same launch records, same per-slug build lock — and a second run for a slug already in flight is rejected. Forget reuses the CLI's own teardown. --port overrides the port; JARVIS_DASHBOARD_PORT does the same via the environment (invalid values fall back to 6080 with a warning); --no-open skips the browser. The server binds 127.0.0.1 only and rejects non-localhost Host headers; like the MCP server it has no auth — a console for your machine, not a network service. Details and troubleshooting: docs/dashboard.md.

Watching a repo (auto-reindex)

jarvis watch /path/to/your/repo             # debounce defaults to 5s
jarvis watch /path/to/your/repo --debounce 3
jarvis watch /path/to/your/repo --scheme MyScheme
jarvis watch /path/to/your/repo --language python
jarvis watch /path/to/your/repo --no-scip   # persist SCIP-off for this repo

Each debounced reindex runs the same staged pipeline as jarvis index. When a SCIP attempt already failed at the current commit, a watch run skips only that SCIP retry (the syntax baseline still publishes); a new commit, an explicit jarvis reindex, or an explicit --scip retries enrichment.

Runs in the foreground (not a daemon) using watchdog — install it with the watch extra. A burst of file changes (e.g. an editor's atomic save touching several files) coalesces into exactly one reindex. The reindex fires once --debounce seconds (default 5) have passed since the last file change — this prevents thrashing on rapid edits. .git, node_modules, .venv, __pycache__, dist, and build are ignored.

Tool details

  • getIndexStatus takes an optional repo_path (the repo's local git working directory) to compare the published commit against git rev-parse HEAD. Omitted, freshness is reported without a staleness check — never stale: true without evidence.

  • searchCode takes query plus an optional repo filter. On first call it lazy-spawns an embedded zoekt-webserver (pidfile'd so a second jarvis process reuses it instead of spawning a duplicate; killed on clean exit via atexit).

  • blastRadius takes repo plus symbol_or_package (e.g. "npm:@scope/ name", the same "{manager}:{name}" string jarvis index derives from each repo's SCIP symbols). Returns every other indexed repo whose package depends on it, up to 2 hops, each tagged with its hop distance. The package graph has no per-node timestamp, so freshness is always "unknown" here — an honest limitation of the schema, not a bug. Cross-repo edges resolve by exact package name against whatever has already been indexed: index the dependency first, or re-run jarvis index/reindex after indexing it, for an edge to appear. Each reindex retracts that repo's own stale edges before recomputing them, so a removed dependency's edge disappears too — the graph always reflects each repo's last index run, not an accumulation of every run it's ever had.

  • semanticSearch takes repo plus a natural-language query. Requires the optional semantic extra. Results fuse a LanceDB vector search over tree-sitter-chunked code with searchCode's Zoekt hits via reciprocal rank fusion. Raises a clear error if the repo has never been indexed with the extra installed (jarvis reindex <slug> after installing it builds the missing table); indexing itself is non-fatal — a failure there never blocks the rest of jarvis index. Semantic indexing also respects .gitignore (on top of the hardcoded ignore-directory list) and skips any file over 1 MB, in addition to the existing generated-file banner/long-line detection — --semantic-include overrides all three.

Known upstream limitations

These are real behaviors of the underlying SCIP tooling (scip expt-convert as of v0.9.0, scip-java, scip-kotlinc), not jarvis bugs:

  • typeHierarchy returns an explicit {"error": ...}, not empty arrays, on indexes built with an unpatched upstream scip — that converter declares global_symbols.relationships in its schema but never writes it. An empty result would wrongly assert "no supertypes"; the error says "cannot tell" instead. setup.sh installs a fork build carrying the fix, so a fresh jarvis reindex <slug> makes the tool work. Reported upstream: scip-code/scip#464, fix scip-code/scip#465 (open, CI green).

  • displayName / kind are backfilled from the symbol string. The converter never populates global_symbols.display_name/.kind, so query.py's _display_and_kind parses both from the SCIP symbol string whenever the database columns are empty (which they still normally are) — documentSymbols returns real values in practice; only a genuinely unparseable symbol falls through to null.

  • searchCode's repo filter matches Zoekt's own repository name, which jarvis index now names after the slug via zoekt-index -meta — so this no longer diverges for repos indexed with current code. Shards published by an older jarvis still carry their old directory-derived name until you jarvis reindex <slug>.

  • scip-java can't index Android/Gradle repos at all — its Gradle plugin keys off Gradle's standard source sets, which AGP replaces with its variant model, so the build emits zero SCIP shards (scip-java#177).

  • Kotlin indexing requires an exact Kotlin version matchscip-kotlinc is compiled against one pinned Kotlin release (SCIP_JAVA_KOTLIN in setup.sh, currently 2.2.0); its compiler-plugin API is internal and unstable even across patch releases, so any other version fails. Both cases are detected automatically from the indexer's own failure output and degrade to exit-0 degraded (SCIP skipped, syntax baseline still published) rather than failing outright.

  • Maven-built Java repos need bash >= 4.4 on macOS — scip-java's generated javac wrapper (#!/usr/bin/env bash, set -eu) expands "${LAUNCHER_ARGS[@]}" unguarded, which errors on bash < 4.4; macOS ships only 3.2, so the build dies at default-compile with LAUNCHER_ARGS[@]: unbound variable. setup.sh works around it by linking first on PATH for the indexer. If no bash >= 4.4 is installed, indexing fails with the remedy rather than degrading — unlike the two cases above, this one is fixable (brew install bash).

Configuration

Data directory (default ~/.jarvis):

JARVIS_DATA_DIR=/custom/path jarvis index /path/to/repo

Environment variables:

  • JARVIS_DATA_DIR — override default ~/.jarvis for all indexes and registry

  • JARVIS_FALLBACK_SEARCH_ONLYremoved. No longer read; jarvis prints a one-line note if your shell still exports it. Replaced by the reversible persisted --scip/--no-scip flags on index/reindex/watch.

  • JARVIS_EMBEDDING_QUERY_PREFIX / JARVIS_EMBEDDING_DOC_PREFIX — override the query/document instruction prefix applied before embedding. Auto-detected for bge-m3, e5, and nomic-embed; set these if using a different model that needs one — semanticSearch warns when an unlisted model has no prefix configured.

jarvis index --no-semantic skips the semantic (vector) stage even when the semantic extra is installed. The MCP indexRepo tool passes it by default, so an agent tool call never implicitly downloads embedding weights.

Agent skills

Three agent skills ship in the Claude Code plugin, under plugin/skills/:

  • jarvis-setup — install, register, index, verify.

  • jarvis-use — prefer jarvis for structural queries (find references, go-to-definition, hierarchy).

  • jarvis-issues — file jarvis bugs/features via gh.

Install them, and register the MCP server, with:

/plugin marketplace add jarvis-intelligence/jarvis-index
/plugin install jarvis@jarvis

See Quick start above for the manual registration alternative.

Standards

Blob decoding follows the SCIP protocol: scip_pb2.py is generated from scip.proto at scip-code/scip tag v0.9.0 (regenerated up from v0.7.0, which lacked the typed_range oneof scip-swift requires), and occurrence/relationship blobs are decoded as real scip.Document / scip.SymbolInformation messages.

The SQLite layer (documents, chunks, global_symbols, mentions, defn_enclosing_ranges) is not part of that published spec — it is the output shape of the experimental scip expt-convert sub-command, verified by hand against a real index. Treat it as a moving target across scip releases.

Tests

uv run pytest

Integration tests that shell out to the real scip-python / scip / zoekt-index binaries are marked integration:

uv run pytest -m "not integration"   # unit only
uv run pytest -m integration         # real-binary pipeline

Documentation

All 4 planned phases are shipped — see plans/0724-2316-jarvis-mcp-implementation/plan.md.

License

MIT

Available Tools

9 tools
blastRadiusA

2-hop bounded BFS over the package dependency graph: every other indexed repo whose package directly (1 hop) or transitively through one intermediary (2 hops) depends on symbol_or_package as registered for repo (built by codeintel index, e.g. "npm:@scope/name"). The graph has no per-node timestamp, so freshness is always reported as unknown here — an honest limitation, not a bug.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
symbol_or_packageYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden. It discloses the bounded BFS behavior, the dependency on 'codeintel index', and the honest limitation that freshness is always 'unknown' because the graph lacks per-node timestamps. This adds genuine transparency beyond 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense without being verbose, front-loading the core algorithm. The first sentence is somewhat dense with parentheticals, but every clause contributes value, and the limitation note is concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists, return values are covered. The description explains the graph traversal logic, indexing prerequisite, and a known limitation, which is sufficient for selecting and invoking the tool correctly. It omits details like authentication, but those are unlikely to be critical for this dependency-graph query tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description gives meaningful context for both parameters: `symbol_or_package` is a package identifier (with example) and `repo` is where it is registered. It does not fully specify input formats for `repo` or possible variations of `symbol_or_package`, so it only partially compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it performs a '2-hop bounded BFS over the package dependency graph' to find repos depending on a given symbol/package. The verb and resource are specific, and the example (npm:@scope/name) distinguishes it from sibling code-navigation tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It conveys that this tool is for package dependency analysis, not code-level references, and mentions it relies on prior indexing. However, it does not explicitly state when not to use it or name an alternative, though the sibling context makes this reasonably clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

callHierarchyA

Single-level incoming/outgoing call hierarchy for symbol within repo.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
symbolYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since annotations are absent, the description carries the behavioral disclosure burden. It adds the limitation 'single-level' and the scope 'incoming/outgoing', which are important behavioral traits beyond the schema. It does not mention side effects or prerequisites, but for a read-only hierarchy tool this is largely sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that immediately conveys the core function. Every word adds value, with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, an output schema, and the description covering purpose and limitations, it is largely complete. It lacks explicit usage alternatives and deeper parameter definitions, but these are not critical for a low-complexity read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must compensate. It contextualizes `symbol` as the target and `repo` as the container, giving basic meaning, but does not define what constitutes a valid symbol or repository. This leaves some ambiguity for an AI agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns a single-level call hierarchy (incoming/outgoing) for a named symbol in a repo, using the specific resource and scope. This distinguishes it from siblings like findReferences and typeHierarchy, which serve different code navigation purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when a call relationship view is needed, but provides no explicit guidance on when to prefer this over siblings (e.g., findReferences) or when not to use it. No alternatives or exclusions are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

documentSymbolsA

List every top-level symbol (with its range) defined in path within repo.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
repoYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the burden of explaining behavior. It discloses the core behavior of listing top-level symbols with ranges, but does not explicitly state that it is a read-only operation or mention any edge cases, errors, or performance characteristics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence of 13 words, immediately front-loading the action ('List') and the resource ('every top-level symbol'). There is no filler or redundant information, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simplicity of the tool (two string params) and the existence of an output schema, the description provides sufficient context for invocation. It specifies the scope and what is returned (symbols with ranges), though it does not cover potential edge cases or limit behaviors.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero description coverage for the two parameters, so the description must compensate. It does so by clarifying that 'path' is a file path 'within repo', establishing the relationship between the parameters and their roles. This adds meaning beyond the bare schema types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'List' and identifies the resource as 'every top-level symbol (with its range)' scoped to 'path within repo'. This clearly distinguishes it from siblings like goToDefinition, findReferences, and searchCode, which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for obtaining an overview of symbols in a file, but it does not explicitly state when to use this tool over alternatives or provide any exclusions. It relies on the agent inferring context from sibling tool names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

findReferencesB

Every occurrence of symbol within repo, definition sites included.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
symbolYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description should disclose read-only status or side effects. It only notes that definition sites are included, but does not mention whether the operation is safe or depends on an index.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence that is front-loaded and contains no redundant words. Every phrase adds relevant scope.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and has an output schema, so return values are covered. However, the description lacks usage context and any dependence on indexing, making it only minimally complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, and the description only contextualizes the two parameters ('symbol' in 'repo') without adding format or matching semantics (e.g., case sensitivity, path syntax).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool finds every occurrence of a symbol within a repo, with definition sites included. This specific verb+resource phrasing distinguishes it from sibling tools like goToDefinition.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool vs siblings like searchCode or blastRadius. The description only states what it does, with no exclusions or alternative mentions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

getIndexStatusA

Whether repo has a published index, and its freshness. Pass repo_path (the repo's local git working directory) to compare the published commit against git rev-parse HEAD; omitted, freshness is reported without a staleness comparison.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
repo_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It explains the core behavior (published index check) and the conditional staleness comparison when repo_path is passed, adding meaningful behavioral detail. It does not discuss error handling or return format, but the output schema likely 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the main purpose, and the optional parameter behavior is explained efficiently without verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple 2-parameter schema and presence of an output schema, the description sufficiently covers the tool's behavior and the optional parameter's effect. It is complete enough for an agent to invoke it correctly, though it could mention edge cases like missing indexes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 defines repo_path explicitly as 'the repo's local git working directory' and explains its effect, while repo is implicitly defined as the repository identifier. This adds meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks whether a repo has a published index and reports its freshness, using a specific verb and resource. It distinguishes itself from the code navigation siblings by focusing on index status rather than code exploration.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when to use the tool (to check index existence/freshness) and explains the optional repo_path behavior for staleness comparison. It does not explicitly mention alternatives or exclusions, but the purpose is strong enough to make usage obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

goToDefinitionA

Resolve symbol's definition location(s) within repo.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
symbolYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It only states the core action and does not disclose edge-case behavior, such as how multiple definitions are returned, what happens if the symbol is not found, or whether indexing is required. This is a minimal disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with a clear front-loaded verb. Every word contributes to meaning, with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with an output schema available, the description covers the primary purpose. It does not mention prerequisites like indexing, but the low complexity and existence of an output schema keep the baseline high.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has no parameter descriptions (0% coverage). The description places both params in context: 'symbol' is the thing to resolve, 'repo' is the scope. It clarifies the roles but gives no format details (e.g., repo identifier format, symbol qualification). This partially compensates for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Resolve') with a clear resource ('symbol') and outcome ('definition location(s)') within a repo. This effectively distinguishes it from sibling tools like findReferences and documentSymbols.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage: if you need to find a symbol's definition, you use this tool. However, it offers no explicit guidance on when not to use it or alternatives (e.g., 'use findReferences for usages'), so the guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

searchCodeA

Lexical code search via an embedded Zoekt index (lazy-started on first call). repo, if given, is applied as a Zoekt r: query filter scoping results to that one indexed repo; omitted, results span every indexed repo.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoNo
queryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral context beyond the schema: it mentions the index is 'lazy-started on first call' and explains how the repo filter transforms to a Zoekt 'r:' query. This goes beyond a bare statement of function. However, with no annotations, the description still lacks disclosure on result format, limits, or potential side effects (e.g., indexing delays), so it is not fully transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two well-structured sentences: the first clearly states the tool's purpose and mechanism, the second explains the repo parameter's behavior. Every sentence contributes unique information with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a search tool with an output schema present, the description sufficiently covers the core functionality, the lazy-start behavior, and the repo scoping logic. It misses some contextual information like query syntax or limits, but these are less critical given the output schema and the fact that the core behavior is clearly explained. Sibling tools like getIndexStatus could complement but are not strictly required to be mentioned.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides no descriptions (coverage 0%), so the description must compensate. It does explain 'repo' semantics in detail (Zoekt r: filter, scoping vs. all repos), which adds real meaning. However, the required 'query' parameter is not described beyond the general 'lexical code search' phrase, leaving its syntax and expected format ambiguous. Thus partial compensation only.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Lexical code search via an embedded Zoekt index', specifying the verb (search), the resource (code), and the distinguishing mechanism (lexical via Zoekt). This differentiates it from sibling tools like semanticSearch, which implies a non-lexical search, and also names a concrete implementation detail (Zoekt index).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by specifying 'lexical code search' and the repo scoping behavior, but it does not explicitly state when to prefer this over semanticSearch or other siblings, nor does it provide exclusions or alternative tool references. The repo filter is explained functionally, but this is more behavioral than usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

semanticSearchA

Natural-language code search over repo: embeds query, retrieves top vector matches from the repo's semantic index, fuses them with Zoekt lexical hits via reciprocal rank fusion. Requires the repo to have been indexed with the semantic extra installed.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
limitNo
queryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses non-obvious behavior: embedding the query, retrieving top vector matches, and fusing with Zoekt hits via reciprocal rank fusion. It also flags a prerequisite. Lacks error/output details but is quite transparent for a search tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with purpose and algorithm. Every word adds value; no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 discussion is unnecessary. The description covers purpose, mechanism, and prerequisite. It could benefit from mentioning 'limit' or an explicit sibling comparison, but overall it's sufficiently complete for moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 adds meaning to 'repo' and 'query' but omits 'limit', which has a default. Partial coverage—enough to understand core parameters but not complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs natural-language code search over a repo, with a specific verb ('search') and resource ('repo'). It further differentiates from siblings like searchCode by detailing the semantic/vector retrieval and fusion with Zoekt lexical hits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies usage for natural-language queries and gives a prerequisite (repo must be indexed). It does not explicitly name alternatives or exclusions, but the context is clear enough to guide selection among sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

typeHierarchyA

Single-level super/subtypes for symbol within repo.

Returns an explicit error when the index carries no relationship data —
`scip expt-convert` does not populate `global_symbols.relationships`, so
an empty result would wrongly imply the symbol has no supertypes.
ParametersJSON Schema
NameRequiredDescriptionDefault
repoYes
symbolYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses a critical behavior: returning an explicit error when relationship data is absent, and explains the underlying reason (`scip expt-convert` does not populate `global_symbols.relationships`). This goes beyond the tool's nominal function and helps prevent misinterpretation of empty results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is exceptionally concise: two sentences. The first states the core purpose, and the second adds a crucial caveat about error behavior. No unnecessary words or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with an output schema, so it doesn't need to describe the return format. The description covers the main functionality and a significant edge case that could otherwise mislead users. However, it stops short of providing explicit guidance on when to prefer this tool over sibling tools like callHierarchy.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description references `symbol` and `repo` within its sentence, providing minimal contextual clues, but does not elaborate on their meanings, types, or formats. Schema description coverage is 0%, so the description does not significantly augment the schema's parameter definitions beyond the obvious names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns 'Single-level super/subtypes for `symbol` within `repo`', using a specific verb-like purpose that distinguishes it from sibling tools like callHierarchy. The 'single-level' qualifier prevents confusion with transitive or multi-level hierarchies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for type hierarchy queries but does not explicitly mention when not to use it or compare with alternatives like callHierarchy. It does provide a caution about the error condition, which partially guides usage, but lacks explicit when-to-use/versus guidance.

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.

  1. 9 tool updatesv0.2.1
    • First observedblastRadius
    • First observedcallHierarchy
    • First observeddocumentSymbols
    • First observedfindReferences
    • First observedgetIndexStatus
    • First observedgoToDefinition
    • First observedsearchCode
    • First observedsemanticSearch
    • First observedtypeHierarchy

TDQS

A4/5.0

Scored across 9 tools

Disambiguation5/5

Each tool targets a clearly distinct code intelligence operation: symbol listing, definition resolution, references, call/type hierarchies, index status, lexical search, semantic search, and dependency impact analysis. No two tools serve the same purpose.

Naming Consistency4/5

All names are camelCase and reasonably descriptive, but the pattern is not fully uniform: some start with verbs (goTo, find, get, search) while others are noun phrases (callHierarchy, typeHierarchy, blastRadius). This minor inconsistency does not seriously impede readability.

Tool Count5/5

Nine tools is well-scoped for a code intelligence server, covering standard queries without excess. Each tool contributes a distinct capability and none feel redundant.

Completeness5/5

The surface covers core code intelligence workflows: symbol navigation, references, hierarchies, search (both lexical and semantic), index freshness, and dependency blast radius. No obvious dead ends or missing critical operations for the implied scope.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    A
    maintenance
    Local-first codebase intelligence engine providing AI coding agents with a typed MCP toolset for understanding and navigating code repositories.
    100
    52
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides two-modal code search (lexical via Zoekt and semantic via ChromaDB embeddings) for AI coding agents through MCP tools, enabling fast regex and meaning-based code lookup.
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    A local code-intelligence MCP server that provides structural, exact-query, related-search, and research capabilities from a validated repo-local index, enabling agents to perform deterministic lookups, semantic search, and code analysis.
    21
    MIT
  • F
    license
    Not graded
    quality
    A
    maintenance
    Provides a local-first code indexing and search engine for coding agents via MCP, enabling precise codebase queries, symbol lookup, and freshness-aware retrieval.
    -