localscope-mcp
localscope-mcp gives AI assistants private, offline codebase analysis via four MCP tools.
Index a repository locally (
localscope_index): files, symbols, import graph, optional embeddings; respects.gitignore, persists incrementally, and watches for file changes.Search code (
localscope_search) by natural-language meaning, symbol name, or fragment; results include file, lines, symbol, score, and match type.Analyze change impact (
localscope_impact) for a file path or symbol: direct dependents, transitive dependents, symbols at risk, and fuzzy suggestions.Show index status (
localscope_status): file/chunk/symbol counts, embedder mode, and timestamp.Everything runs fully offline with zero network calls; optional semantic search uses a local ONNX embedder with automatic fallback to lexical/symbol matching.
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., "@localscope-mcpwhat breaks if I rename parseConfig?"
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.
localscope
A local code analyst for your AI assistant — and for you.

localscope is an MCP server that indexes your repository on your machine — files, symbols, imports, references, optional embeddings — and lets Claude, Cursor, Codex, Windsurf, or any MCP client answer questions like:
"Where does X break if I change Y?"
without a single byte of your code leaving your machine. And when there's no AI client around, localscope explore puts the same graph in your terminal.
$ localscope explore
change what? parseConfig
parseConfig function · src/utils/config.ts:6
AppConfig interface · src/utils/config.ts:1
… 4 more
[enter]
Impact of changing parseConfig
2 files affected · 2 direct · 0 transitive
Breaks first
src/main.ts
src/services/server.ts
Esc back to search · Ctrl-C exitCommands
Command | What it does |
| Interactive impact browser: type a symbol or file, see what breaks — fzf-style, in your terminal. |
| The same impact analysis, plain text to stdout — pipe it, grep it, put it in CI |
| Build or refresh the local index (incremental — unchanged files are skipped) |
No AI client, no network, no leaving the repo. The MCP server and the CLI share one index.
Related MCP server: Paparats MCP
Why
Cloud code-search tools are great — until the repo is under NDA, on an air-gapped machine, or you simply don't want your code on someone else's servers. localscope gives assistants codebase vision with a hard guarantee: zero network calls, zero telemetry, zero config.
localscope | cloud tools | |
Code leaves machine | never | yes |
Setup |
| API key, upload |
Works offline | yes | no |
Impact analysis | AST symbols + call graph | varies |
Quickstart
Requirements: Node 18+.
Claude Code:
claude mcp add localscope -- npx localscope-mcpCursor (.cursor/mcp.json):
{
"mcpServers": {
"localscope": { "command": "npx", "args": ["localscope-mcp"] }
}
}Any MCP client — stdio server, one command:
npx localscope-mcpOptional: semantic search with local ONNX embeddings (still offline — the model runs on your CPU):
npm install -g @huggingface/transformersNot installed? localscope automatically falls back to lexical + symbol search. No error, no setup step.
Tools
localscope_index
Build the local index: files, symbols, import graph, embeddings if available. Respects .gitignore and skips node_modules, dist, lockfiles, binaries. Typical repo indexes in well under a second.
Persistent and incremental. The index is cached on disk (under ~/.cache/localscope/<repo-digest>/) and reused across sessions: re-running localscope_index only re-extracts files whose mtime/size changed, and localscope_search / localscope_impact load the persisted index automatically — no full re-index in every session. While the server runs, a file watcher keeps the index fresh: edit a file, and the update lands in the background within ~300ms. Set LOCALSCOPE_CACHE_DIR to relocate the cache.
localscope_search
Find code by meaning ("retry with backoff"), by symbol name ("parseConfig"), or by fragment. Each hit shows file, lines, symbol, score, and how it matched — semantic, lexical, or symbol. Identifiers are split camelCase-aware, so "parse config" finds parseConfig.
localscope_impact
The headline tool. Give it a file path or a symbol name and it walks the reverse dependency graph:
Direct dependents — files importing the target; these break first
Transitive dependents — everything downstream, up to
max_depthhopsSymbols at risk — exported functions/classes in the target and why each is fragile
Fuzzy suggestions — typo in the name? It suggests what you meant
localscope_references
A local "find all usages": every call site and read of a symbol, with exact line numbers per file. where is parseConfig called? → src/main.ts:4 and friends — from the AST reference graph, offline.
localscope_definition
A local "go to definition": file, line span, kind, and export status of a symbol.
localscope_status
Index stats: files, chunks, symbols, embedder mode, timestamp.
Privacy guarantee
localscope makes no outbound network calls — not for search, not for models, not for updates. The ONNX embedder (if you install it) downloads its model once from Hugging Face into your local cache, then runs fully offline. You can verify it yourself: src/services/embedder.ts is the only module that touches @huggingface/transformers, and only when you've installed it.
Air-gap friendly. NDA friendly. Paranoia friendly.
Performance
Measured on ripgrep (233 source files, 110 in Rust), M1 MacBook Air, default Node heap:
Operation | Time | Result |
Cold index, ONNX embeddings | ~2 min | 2,786 symbols · 9,288 references · 3,277 chunks |
Cold index, lexical only (no transformers installed) | ~2 s | same graph, no semantic search |
Re-open (warm cache, incremental) | 1.3 s | zero re-extraction |
| < 10 ms | from the in-memory graph |
The index persists to disk (~75 MB for ripgrep); every session after the first is the warm number. The file watcher keeps it fresh while the server runs — editing a file lands in the index within ~300 ms.
Star it
If localscope saved you a refactor-induced bug, ⭐ star the repo — it helps others find it.
How impact analysis works
Parse each file with tree-sitter (WASM — no native builds, no language servers). Accurate symbols — functions, classes, interfaces, types, methods, constants — with real line spans and export status. Grammars ship inside the package: TypeScript/TSX, JavaScript, Python, Go, Rust, Java, Ruby, PHP, C, C++, C#. No grammar available (exotic file, pruned install)? localscope falls back to regex extraction — zero-config either way.
Record references, not just imports: every identifier use (call sites, type references) goes into the symbol graph, so impact analysis answers "who actually calls this", not just "who imports the file it lives in".
Resolve imports into a file graph. TypeScript-style
.js→.tsmapping included (ESM-style imports resolve correctly).Answer "who breaks?" by traversing the reverse graph and cross-referencing the symbol table.
No LSP server. No language server per language. No daemon. Just reading files fast and getting the graph right.
HTTP mode (optional)
stdio is the default and right for local use. If you need HTTP (e.g. a shared dev-machine setup):
LOCALSCOPE_TRANSPORT=http LOCALSCOPE_PORT=3000 npx localscope-mcp
# MCP endpoint: http://127.0.0.1:3000/mcpBinds to 127.0.0.1 only, rejects non-local origins. Do not expose it to the network.
Configuration
Zero required. Everything is optional:
Env var | Default | Purpose |
|
|
|
|
| HTTP port |
| auto-detect | Path to ripgrep binary, if you have one |
|
| Base dir for persisted indexes |
Development
git clone <repo> && cd localscope
npm install
npm test # 62 tests
npm run build
npx @modelcontextprotocol/inspector node dist/index.jsCI runs typecheck, lint, and tests on Node 18/20/22 across Linux, macOS, and Windows.
License
MIT
Available Tools
4 toolslocalscope_impactAnalyze change impactARead-onlyIdempotent
Answer "where does X break if I change Y?" from the local import graph and symbol table — entirely offline.
Args:
target (string): file path relative to repo root (e.g. 'src/utils/parse.ts') OR a symbol name (e.g. 'parseConfig')
path (string): repo root previously indexed, default "."
max_depth (number): reverse-dependency walk depth 1-10, default 5
response_format ('markdown' | 'json'): default 'markdown'
Returns: Direct dependents (files importing the target), transitive dependents, and exported symbols at risk.
Use when: "what breaks if I refactor/delete this?", "who uses this function?". Requires localscope_index first.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Repository path (must match a previously indexed root) | . |
| target | Yes | File path (e.g. 'src/utils/parse.ts') OR symbol name (e.g. 'parseConfig', 'UserService') | |
| max_depth | No | How deep to walk the reverse dependency graph | |
| response_format | No | Output format: 'markdown' for human-readable or 'json' for machine-readable | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already cover the read-only, idempotent, non-destructive safety profile, and the description adds valuable operational context: the analysis is entirely offline, requires a previously indexed repo, and walks the reverse-dependency graph. The 'what if I change Y' phrasing clearly refers to a hypothetical, not an actual mutation, so there is no contradiction.
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 main question is front-loaded, and the Args, Returns, and Use-when sections are clearly separated and easy to scan. It is somewhat repetitive with the input schema's parameter docs, but the structure and short sentences make the tool's invocation model easier to understand at a glance.
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?
Because there is no output schema, the description responsibly describes the return kinds: direct dependents, transitive dependents, and at-risk exported symbols. It also covers the indexing prerequisite and offline behavior; only exact result formatting and behavior for unindexed paths are left unstated, and those are reasonably expected from the schema and annotations.
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 schema already documents all four parameters with types, defaults, and constraints. The description adds some useful framing, such as 'target' being relative to the repo root and 'path' being a previously indexed root, but it mostly restates what the schema already provides, so it meets rather than significantly exceeds the baseline.
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 frames the tool as a change-impact analysis utility ('where does X break if I change Y?') over the local import graph and symbol table, which is specific and distinguishes it from the indexed/search/status siblings in name and behavior. It is clear, though it does not explicitly name or contrast sibling alternatives in prose.
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 provides concrete 'Use when' triggers such as 'what breaks if I refactor/delete this?' and 'who uses this?', plus the necessary prerequisite 'Requires localscope_index first'. What is missing is an explicit 'don't use this if...' or a direct pointer to a sibling tool for alternative query types.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
localscope_indexIndex repository locallyARead-onlyIdempotent
Build a local, private index of a repository: files, symbols (functions/classes/types), import graph, and optional embeddings. Zero network calls — the index never leaves the machine.
Args:
path (string): repository root, default "."
max_files (number): safety cap, default 50000
response_format ('markdown' | 'json'): default 'markdown'
Returns: File/chunk/symbol counts, embedder mode (onnx or lexical), duration.
Use when: the user asks to index/analyze the codebase, or before localscope_search / localscope_impact on a repo not indexed yet in this session.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Repository path to index (absolute, or relative to the directory the server was started in) | . |
| max_files | No | Safety cap on number of files to index | |
| response_format | No | Output format: 'markdown' for human-readable or 'json' for machine-readable | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotation contradiction: readOnlyHint=true conflicts with the description's claim that the tool 'builds' an index, which implies a state-changing operation. The description does add useful offline/privacy context, but the contradiction misleads an agent about whether this tool has side effects.
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 well-structured and compact: core purpose and privacy stance are front-loaded, followed by labeled Args, Returns, and Use when sections. Every part earns its place, and the Returns section compensates for the absence of an output schema.
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 tool with only optional parameters and no output schema, the description covers purpose, parameters, return values, usage conditions, and privacy/network behavior. The main gap is that it does not clarify index persistence or re-indexing behavior, but the definition is otherwise sufficiently complete.
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 describes all three parameters with defaults, ranges, and enum values, so schema coverage is 100%. The description's Args section mostly restates the same information without adding meaningful semantic detail 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 action: 'Build a local, private index of a repository' and enumerates what it indexes (files, symbols, import graph, embeddings). This differentiates it sharply from sibling tools like localscope_search and localscope_impact.
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 'Use when' section explicitly says to use this tool when the user asks to index/analyze the codebase, and before localscope_search / localscope_impact on a repo not indexed yet. This provides concrete conditions and names sibling tools, making the choice unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
localscope_searchSearch code semanticallyARead-onlyIdempotent
Search the local index for code or docs by meaning, symbol name, or fragment. Combines embeddings (if installed) with lexical identifier matching — all offline.
Args:
query (string): what to find, e.g. "retry with backoff", "parseConfig", "where do we validate webhooks"
path (string): repo root previously indexed, default "."
limit (number): max results 1-100, default 20
response_format ('markdown' | 'json'): default 'markdown'
Returns: Hits with file, line range, symbol, score, snippet, and how it matched (semantic/lexical/symbol).
Use when: "where is X handled?", "find code that does Y". Requires localscope_index first.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Repository path (must match a previously indexed root) | . |
| limit | No | Maximum results to return | |
| query | Yes | Natural-language query, symbol name, or code fragment to find | |
| response_format | No | Output format: 'markdown' for human-readable or 'json' for machine-readable | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive behavior. The description adds value beyond these annotations by disclosing offline execution, conditional embedding use, and the hybrid semantic/lexical matching mechanism. It leaves some edge cases unspecified, such as behavior when the index is stale, but it neither contradicts the annotations nor omits the core safety profile.
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 efficient and well organized: a one-sentence purpose, then compact Args/Returns/Use-when sections. It also front-loads the meaningful distinction from the title and siblings. No sentence is filler, and the 'Use when' pattern makes the tool immediately actionable.
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?
Because there is no output schema, the description properly compensates by specifying the return shape: file, line range, symbol, score, snippet, and match type. It also states the prerequisite index, the offline constraint, and both supported response formats. For a read-only search tool, this is enough for correct invocation.
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 has 100% parameter description coverage, so the structured fields document each argument. The description adds a few example values for query ('retry with backoff', 'parseConfig') and restates defaults, but most of its parameter information duplicates the schema. This is a reasonable baseline, not an exceptional contribution.
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 opens with a specific verb and resource: 'Search the local index for code or docs by meaning, symbol name, or fragment.' It also distinguishes itself from siblings by explaining it combines embeddings with lexical identifier matching, while tool names like localscope_index, localscope_impact, and localscope_status clearly cover different operations.
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 provides concrete usage triggers ('Use when: ...') and the critical prerequisite 'Requires localscope_index first,' plus illustrative query patterns. It does not explicitly exclude sibling tools, such as advising when localscope_impact would be preferable, but it gives enough context for selection in most cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
localscope_statusShow index statusARead-onlyIdempotent
Show whether a repository root has a local index, its stats (files/chunks/symbols), and the active embedder mode. Read-only, offline.
Args:
path (string): repo root, default "."
response_format ('markdown' | 'json'): default 'markdown'
Returns: Indexed state, counts, embedder mode, indexedAt timestamp.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Repository path to check | . |
| response_format | No | Output format: 'markdown' for human-readable or 'json' for machine-readable | markdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnlyHint, idempotentHint, and destructiveHint, so the description's main addition is the 'offline' characteristic and the explicit listing of returned fields (stats, embedder mode, indexedAt). This adds context beyond the annotations, enriching the agent's understanding of what to expect without contradicting the hints.
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 well-structured with a concise one-sentence purpose statement followed by clear Args and Returns sections. Every sentence adds value—no fluff. The key information is front-loaded, and formatting aids readability.
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 read-only status tool with no output schema, the description fully covers what is returned (indexed state, counts, embedder mode, timestamp) and parameter details. Combined with the annotations (safe, idempotent), it is complete for an agent to correctly invoke and interpret the result. Sibling differentiation is clear.
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%, with both 'path' and 'response_format' having descriptions in the input schema. The description essentially repeats the parameter semantics (defaults, format options) without adding new meaning. Since coverage is high, the baseline of 3 applies; the description does not need to compensate.
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 states a specific verb 'Show' and clearly defines the resource: whether a repository root has a local index, its stats (files/chunks/symbols), and the active embedder mode. This clearly distinguishes it from siblings like localscope_index (which likely creates/updates an index), localscope_search (searching), and localscope_impact (impact analysis).
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 implies usage by naming the exact information it provides (index status, stats, embedder mode), but it does not explicitly state when to use this tool versus alternatives. There is no mention of 'use this when you need to check status' or 'for searching use localscope_search instead.' The 'Read-only, offline' note hints at safe usage but doesn't provide routing 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.
4 tool updates
v0.1.1- First observed
localscope_impact - First observed
localscope_index - First observed
localscope_search - First observed
localscope_status
TDQS
Scored across 4 tools
Each tool has a clearly distinct role: building an index, searching it, analyzing impact, and checking status. There is no overlap or ambiguity among the four operations.
All tool names follow a uniform 'localscope_' prefix with a simple lower-case verb: index, search, impact, status. The naming pattern is consistent and predictable.
Four tools make for a compact, focused surface that covers the core workflows of indexing, querying, impact analysis, and health checks. It is well-scoped for a local code intelligence server without being bloated or thin.
The set covers build, search, impact analysis, and status, which is strong. A minor gap is the lack of an explicit delete/clear index operation, but re-indexing effectively replaces the index, so this is a small omission rather than a critical failure.
Maintenance
Related MCP Connectors
Codebase intelligence for AI agents — dead code, blast radius, ownership.
Codebase graphs, caller impact analysis, and recorded project context for AI coding agents.
Code intelligence platform for AI agents. 20 tools for architecture, security & impact analysis.
Deterministic context layer for your codebase: change impact, blast radius, answers with receipts.
Related MCP Servers
- AlicenseAqualityAmaintenanceA local-first codebase intelligence tool that enables AI assistants to research codebases using semantic search, multi-hop relationship discovery, and structural parsing. It allows users to extract architectural patterns and institutional knowledge across 30+ programming languages through an MCP-compatible interface.21,427MIT
- AlicenseNot gradedqualityBmaintenanceProvides AI coding assistants with deep, semantic understanding of local codebases via AST-aware chunking, cross-repo symbol graphs, and architectural memory, enabling context-aware code search and dependency tracing.10MIT
- AlicenseAqualityBmaintenanceEnables AI coding assistants to analyze codebases locally before generating code, reducing duplication and enforcing architecture boundaries.13MIT
- AlicenseNot gradedqualityAmaintenanceProvides a dependency graph of any local repository with tools for change impact, transitive dependents, health audits, and more, enabling AI coding agents to see structure and refactor safely.4,9124MIT