Local-first MCP server that indexes a codebase into SQLite once and then lets AI agents search it instantly — offline, private, and with zero dependencies via literal substring search, incremental indexing, per-language stats, and root listing.
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., "@Local-first MCP server that indexes a codebase into SQLite once and then lets AI agents search it instantly — offline, private, and with zero dependencies via literal substring search, incremental indexing, per-language stats, and root listing.index my project and search for "TODO" across all roots"
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.
locidx
Local-first code indexer and search. Index a codebase once, then search it instantly — offline, private, and with zero dependencies.
locidx builds a SQLite index of your project, respects .gitignore-style
rules, updates incrementally, and gives you three ways to query it: a CLI, an
interactive TUI, and a Model Context Protocol
server so AI agents can search your code too.
Why locidx?
Zero dependencies. Python 3.9+ standard library only. No
pip installbattle royale — the indexer, CLI, TUI, and MCP server all usesqlite3,curses, andjson.Private and local-first. Everything lives in SQLite files on your machine. No network, no telemetry, no "send us your code" to get search.
Fast and incremental. Only files whose mtime changed are re-read. Searching reads the database, never the filesystem.
gitignore-aware. Real
.gitignoresemantics: negation, anchoring,**, directory-only patterns — plus optional--ignoreglobs and per-directory.locidxignorefiles.One tool, three interfaces. Terminal, TUI, and MCP — the same index serves all three.
Related MCP server: Code-Index-MCP
Install
# From source (no install needed to run — just clone and use ./locidx)
git clone https://github.com/wenn-id/locidx
cd locidx
# Or install the package (creates the `locidx` command)
python -m pip install .You can also run it straight from the checkout without installing:
python -m locidx.cli --helpQuick start
# 1. Index a project (creates .locidx.sqlite inside it)
locidx index ~/src/myproject --stats
# 2. Search it
locidx find "def parse_" ~/src/myproject
# 3. Language stats
locidx stats --json ~/src/myprojectGlobal database
By default locidx index creates a per-project database
(.locidx.sqlite in the indexed folder). That keeps everything self-contained
and shareable.
For a single machine-wide index across many projects, add --global:
locidx index ~/src/project-a --global
locidx index ~/src/project-b --global
locidx search "TODO" --global # searches every indexed root
locidx roots # list all indexed roots
locidx clear # wipe the global indexCLI reference
Command | Description |
| Build or update the index |
| Search inside a project's own index |
| Search the global index |
| Per-language file/line stats |
| List indexed roots |
| Wipe the global index |
Interactive TUI
locidx tui [PATH]/— enter a search queryj/k— move through resultso— open the selected file in$VISUAL/$EDITORg/G— jump to top / bottomq— quit
The TUI is a thin wrapper over the same search core, so results in the terminal and the TUI are always identical.
MCP server
locidx speaks the Model Context Protocol over stdio, so any MCP client
(Claude, code agents, custom tooling) can search your indexed code with
structured results.
# Run the server directly
locidx mcpConfigure it in your MCP client, e.g. Claude Desktop:
{
"mcpServers": {
"locidx": {
"command": "locidx",
"args": ["mcp"]
}
}
}MCP tools
Tool | Description |
| Literal substring search; returns matching lines with paths and line numbers |
| Incrementally index a directory |
| Per-language file/line statistics |
| List every indexed root |
The server is a minimal JSON-RPC 2.0 implementation over stdio with zero
dependencies — no mcp SDK required.
How it works
┌─────────────────────────────┐
.gitignore ──► │ │
│ locidx index PATH │
source tree ──► │ ┌──────────────────┐ │
│ │ incremental walk │─────┼──► .locidx.sqlite
│ └──────────────────┘ │ (SQLite)
└─────────────────────────────┘
│
┌─────────────┼──────────────┐
▼ ▼ ▼
locidx find locidx stats locidx mcp
(CLI) (CLI/TUI) (MCP server)locidx indexwalks the tree, applies ignore rules, and stores each text file's path, size, mtime, a SHA-256 content hash, and the text itself in SQLite.Unchanged files (same size + mtime) are skipped on subsequent runs.
Queries (
find,stats, TUI, MCP) read only from SQLite — the filesystem is never touched again.
Ignore rules
locidx honors .gitignore and .locidxignore files at any depth, plus
--ignore globs:
# .gitignore
*.log # everywhere
build/ # directory only
/src/generated/ # anchored
!keep.log # re-include
node_modules/ # handled out of the box--no-ignore disables all ignore handling.
Project layout
locidx/
├── locidx/
│ ├── cli.py # argparse CLI
│ ├── tui.py # curses TUI
│ ├── indexer.py # incremental walk + content hashing
│ ├── search.py # literal substring search
│ ├── stats.py # language detection + aggregation
│ ├── ignore.py # gitignore-style matching
│ ├── db.py # tiny SQLite wrapper (schema + helpers)
│ ├── mcp.py # MCP entrypoint
│ ├── server.py # JSON-RPC 2.0 stdio server
│ └── tools.py # agent-friendly tool wrappers
└── tests/ # stdlib unittest suite (runs in CI without install)Development
# Run the test suite (stdlib only)
python -m unittest discover -s tests -v
# Or with pytest, if you have it
python -m pytest -qCI runs the same unittest command across Python 3.9–3.12.
License
MIT — do whatever you want with it, but please star it if it saves you time.
Available Tools
4 toolsindexA
Index a directory so it can be searched later. Incremental: only changed files are re-read.
| Name | Required | Description | Default |
|---|---|---|---|
| root | Yes | Directory to index | |
| no_ignore | No | Disable .gitignore/.locidxignore | |
| extra_ignores | No | Extra ignore globs |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. The incremental note ('only changed files are re-read') is a useful behavioral disclosure. However, it doesn't describe side effects or prerequisites, which keeps it at a minimum viable level.
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 concise sentences, no filler, information-dense.
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 simple indexing tool with well-documented parameters, the description provides essential purpose and a behavioral caveat. No output schema is present, so the outcome is implied by 'searched later', which suffices.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline of 3. Description adds no extra parameter details, just restates the primary action.
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?
Clear verb 'Index' with resource 'a directory' and outcome 'so it can be searched later'. Distinguishes from sibling tools 'search', 'stats', 'roots' by the action.
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 phrase 'so it can be searched later' implies a preparatory use case. Does not explicitly name alternatives or exclusions, but the purpose alone differentiates it from search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rootsA
List every indexed root in the global database.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full responsibility for behavioral disclosure. It states a read-only list operation but does not disclose return format, potential volume, ordering, authentication requirements, or any other side effects. The minimal sentence offers little beyond the literal action.
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 a single eight-word sentence that states the action directly, with no filler. It is appropriately sized and front-loaded, scoring high for conciseness.
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 no parameters and no output schema, the description conveys the core purpose but leaves the term 'indexed root' undefined and does not specify the output structure. However, for such a simple operation, this is a minor gap, so the description is mostly 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 is empty and there are zero parameters, so the description has nothing to add semantically. Per the rubric, 0 parameters merits a baseline of 4, and the description appropriately focuses on the operation itself rather than parameter details.
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 'List' with a clear resource 'every indexed root in the global database.' It distinguishes from sibling tools like search, index, and stats by focusing on enumeration of roots rather than querying or modifying them.
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 no guidance on when to use this tool versus the sibling tools (search, index, stats). There is no mention of alternatives, prerequisites, or exclusions, leaving the agent to infer usage from the tool name and description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchA
Search previously indexed files for a literal substring. Returns matching lines with file path and line number.
| Name | Required | Description | Default |
|---|---|---|---|
| root | No | Optional project root to search within | |
| query | Yes | Literal substring to search for | |
| max_results | No | Maximum results (default 100) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that matching is literal (not regex/fuzzy) and describes the return format, providing useful behavioral detail. It does not discuss edge cases like case sensitivity, but those are not critical 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no fluff, front-loading the core purpose and then adding return-value detail. Every word 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 low-complexity tool with a fully descriptive schema, the description covers the essential behavioral and output aspects. It does not need to explain return values (no output schema exists, but the description already does) or additional edge cases.
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 all parameters already described clearly. The description reinforces the 'literal substring' aspect for the query parameter but does not add significant meaning beyond what the schema provides.
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 searches previously indexed files for a literal substring and specifies the output (matching lines with file path and line number). This distinctively differentiates it from siblings like index, stats, and roots.
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 phrase 'previously indexed files' implies the tool should be used after indexing has occurred, giving clear context. It does not explicitly name alternatives or exclusions, but the context is unambiguous enough for a simple search tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statsB
Per-language file and line statistics for an indexed tree (or all trees).
| Name | Required | Description | Default |
|---|---|---|---|
| root | No | Optional project root |
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 does not explicitly state that this is a safe read-only operation, nor does it describe potential side effects, performance characteristics, or required permissions.
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 a single sentence that is front-loaded with the core purpose and avoids any filler. Every word contributes value.
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 description is adequate for a one-parameter tool with no output schema, but it lacks specific details about what 'file and line statistics' includes (e.g., counts, code vs. blank lines) and the return format. It is not misleading but leaves room for ambiguity.
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 description adds meaningful context beyond the schema by clarifying that 'root' is optional and that omitting it applies to all trees. This supplements the schema's brief 'Optional project root' description.
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's purpose as providing per-language file and line statistics, with a scope of an indexed tree or all trees. It distinguishes from siblings by the unique 'statistics' resource, though it lacks an explicit action verb.
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?
No explicit guidance is given about when to use this tool versus alternatives. The mention of 'indexed tree' implies a prerequisite that data must be indexed, but it does not elaborate on conditions or exclusions.
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.0- First observed
index - First observed
roots - First observed
search - First observed
stats
TDQS
Scored across 4 tools
Each tool has a clear, distinct purpose: search for content, index for building, stats for metrics, and roots for listing indexed directories. No overlap or ambiguity exists.
All tool names are single, lowercase words (search, index, stats, roots) with a consistent style. They are short, memorable, and follow a predictable pattern.
The server has exactly 4 tools, which is well within the ideal 3–15 range. Each tool is essential and earns its place for the server's indexing-and-search purpose.
The tool surface covers the full lifecycle: indexing a directory, searching it, getting statistics, and listing all indexed roots. There are no obvious dead ends or missing core operations.
Maintenance
Related MCP Connectors
Resolve coordinates and geographic identifiers to loc_id, crosswalks, boundaries, and exports.
Retrieve loc_id boundary metadata, polygons, scopes, comparisons, and bounded exports.
Filtrix MCP for image/video generation. Portal: https://agent.filtrix.ai/
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceDocdex is a lightweight, local documentation indexer/search daemon. It runs per-project, keeps an on-disk index of your markdown/text docs, and serves top-k snippets over HTTP or CLI for any coding assistant or tool—no external services or uploads required.1,055 npm16MIT
- AlicenseNot gradedqualityAmaintenanceLocal-first code indexer that provides deep code understanding for Claude and other LLMs with symbol/text search across 48+ languages, semantic search capabilities, and real-time index updates through the Model Context Protocol.56MIT
- AlicenseNot gradedqualityCmaintenanceA local code indexing and search library that enables AI agents to perform semantic and keyword searches across codebases using tree-sitter and SQLite. It provides tools for indexing projects and finding precise code definitions without requiring external APIs, Docker, or server infrastructure.279 npm340MIT
- FlicenseNot gradedqualityCmaintenanceLocal-first, durable knowledge-card RAG for Codex, enabling search, retrieval, and maintenance of reusable experience cards.-