silica-core
Provides a Python harness recipe that lets CrewAI agents use Silica's local retrieval tools on indexed files.
Provides the MCP server configuration block for the Hermes harness so it can use Silica's search and read tools.
Provides a Python harness recipe that lets LangGraph agents use Silica's local retrieval tools on indexed files.
Adds the Obsidian bridge so Silica can index and search an Obsidian vault, including extended wikilink tools.
Supports shell-based coding harnesses with direct access to Silica's JSON subcommands, covering Aider, SWE-agent, Plandex, Devin, and SWE-bench.
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., "@silica-coresearch my workspace for 'api_key' and show the top matches"
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.
Lightweight, local evidence retrieval tools for code and research
Silica locates the source, symbol, page, or passage you and your agents need. Maximum signal, minimum machinery.
Silica indexes the markdown, code, PDFs and office files under one root and serves them to Claude Code, Cursor, Hermes, Codex, OpenCode and every other popular harness, as MCP tools or as shell commands that print the same JSON. A hit is a path, a section, a line, a window of text and the numbers to judge it by. The harness owns the loop.
Three commands, then a question asked the way you would ask any other. The
harness calls silica_search, and the answer carries the file, the page and
the line it came from.
Install
In Claude Code, install the plugin instead: it brings its own server, dense leg included.
uv tool install 'silica-core[mcp]' # BM25 over documents and their sections (faster, lighter)
uv tool install 'silica-core[mcp,dense]' # in addition the dense leg: numpy, a static model (still fast, more precise)The second line adds the dense leg: numpy and a static model2vec model, no
torch and no GPU. It stays inert until the model is named and the sections
are embedded — the last stanza of the Quickstart. Take it when the questions
are paraphrases that share no words with the text; an exact term or an
identifier is answered by the lexical leg either way, and only that leg
reports terms_absent.
pipx works the same. The package and the command are silica-core, the
tools are silica_*.
Upgrading from 0.9 or older: the silica command is silica-core since
0.10.0 (silica belongs to silica-harness). A client registered by an older
silica setup still launches silica mcp, which stops starting once uvx
fetches 0.10.0. Run silica-core setup <client> once and it rewrites that
entry.
Related MCP server: TokenLighten
Quickstart
In any folder of markdown, code, PDFs or office files:
silica-core init # adopt the folder: ignore file, vault.yaml, first index; the MCP server serves adopted folders only
silica-core search "leveled compaction" -k 5 # the best located passages
silica-core setup claude # register the MCP server, write the guidance block into ~/.claude/CLAUDE.md
# optional, with the [dense] extra: the dense leg, a static model, nothing leaves the machine
export SILICA_EMBEDDING_MODEL=model2vec/minishlab/potion-retrieval-32M
silica-core index --embedNine arXiv papers, indexed in 2.1 s. The hit names the file, the page and the passage; the page beside it is the check.
Tools
Tool | Shell | Returns |
|
| the inventory and what the index did with each file: |
|
| ranked passages: path, section, line, BM25, matched terms, |
|
| a slice by lines or by heading (a page, in a PDF), the outline, and a |
|
| an AST context pack for one source file inside a character budget |
|
| one atomic write, linted for structure and unresolved wikilinks |
In a source tree every function, method, class and constant is its own unit:
a hit's section is the symbol, span its lines, and
silica_read(path, section=…) serves the body. For a symbol whose name is
known, grep wins; for a question that names none, the search comes first:
the tool description and the block silica-core setup claude writes say so. The
contract, the reply shapes and the acceptance checks are in
TOOLS.md. Nothing needs an API key or a network.
How search says no
A ranked list always has a top, even when the corpus does not answer. Three fields say how much the result is worth:
coverage: the share of the query's idf mass the hit's matched terms carry. Near 1, every rare term matched; near 0, only common words did.terms_absent: query terms that occur nowhere in the corpus.matched_terms: the words this hit actually contains.
raft consensus log replication over the same nine papers: raft and
consensus occur in none of them, coverage falls to 0.19, and the top hit
is about data replication. On 254 papers the top hit of an answered question
carries 0.69 to 1.00; a question the corpus does not cover, 0.44. Silica
exposes the signals; the harness decides whether to stop, read or rephrase.
Benchmarks
nDCG@10 on BEIR SciFact · NFCorpus, the same documents and queries for every arm. BEIR's published BM25 baselines are 0.665 · 0.325. Silica's lexical index needs no model; the others serve lexical search from an index that also holds embeddings.
Mode | Silica | zvec-grep 0.2.2 | ck 0.7.11 |
Lexical | 0.662 · 0.311 | 0.649 · 0.297 | 0.630 · 0.289 |
Hybrid, same | 0.675 · 0.328 | 0.672 · 0.330 |
Code, on the twenty SWE-QA questions zvec-grep publishes for its own benchmark, same embedder, k = 10, scored on the files and symbols the reference answer rests on.
Arm | file hit@5 · @10 | file MRR | symbol hit@10 | symbol recall | chars returned |
Silica, hybrid | 0.85 · 0.90 | 0.68 | 0.75 | 0.24 | 8,266 |
Silica, vectors | 0.80 · 0.85 | 0.67 | 0.65 | 0.21 | 6,225 |
Silica, lexical | 0.65 · 0.75 | 0.47 | 0.45 | 0.14 | 8,194 |
zvec-grep 0.2.2, hybrid | 0.65 · 0.75 | 0.54 | 0.55 | 0.17 | 7,326 |
zvec-grep 0.2.2, vector | 0.60 · 0.80 | 0.61 | 0.55 | 0.18 | 6,821 |
zvec-grep 0.2.2, FTS | 0.45 · 0.60 | 0.36 | 0.45 | 0.11 | 6,690 |
On BEIR the two hybrids tie at the 95% interval: the same vectors rank the same, with no daemon and no vector store. On code, Silica's hybrid file MRR is +0.135 over zvec-grep's hybrid (95% interval +0.01 to +0.27), paired per question. The fusion also gains +0.21 MRR and +0.30 symbol hit over Silica's lexical arm; no reranker or graph expansion is involved.
On this measured scope, Silica is a compact, local, SOTA-competitive retriever: it matches zvec-grep on BEIR and leads the paired SWE-QA code-localization replay with the same embedder.
Retrieval matters only if the agent does less work without losing the answer. These are separate experiments and are not pooled:
Workload and arm | Runs | Quality | Search used | Turns | Tool calls | Seconds | Warm cost |
Repository, search-first contract | 20 | Judge 59.7 | 17/20 | 4.7 | — | 24 | $0.197 |
Repository, same plugin without contract | 20 | Judge 50.6 | 0/20 | 6.5 | — | 28 | $0.180 |
Documents, resident Silica tools | 12 tasks | 12/12 correct | 12/12 | 3.9 | 2.9 | — | $0.20 |
Documents, no plugin | 12 tasks | 12/12 correct | — | 5.0 | 4.0 | — | $0.22 |
The repository result is one repetition: turns improve by 1.75 (95% interval 0.55 to 3.05 fewer), while Judge and cost remain inconclusive. The document rows belong to a 144-run study over twelve questions and a 5.5M-token corpus. They establish less work on that workload, not a universal agent claim.
Corpora, intervals, per-task exceptions and reproduction commands are in benchmarks.
Harnesses
silica-core setup <client> writes the registration into the client's own config
and backs up what was there; for claude it also puts a guidance block, when
to search before grep, into ~/.claude/CLAUDE.md. silica-core setup --list
names the clients: claude, codex, cursor, windsurf, zed, cline,
roo, continue, goose, opencode, openhands, gemini, antigravity, dsh,
hermes, openclaw, agent-zero, claude-desktop, lmstudio,
anythingllm and librechat; shell, python and generic print recipes
for anything else. The server serves the folder the client opens in;
--vault DIR or SILICA_VAULT fixes the root.
Every written block, and the Claude Code plugin, run silica-core mcp --retrieval local-hybrid: potion-retrieval-32M in the server process, index and
vectors built in the background at start, the search lexical and dense: warming until they land. Nothing leaves the machine; the one download is
the model, once. npx skills add kiycoh/silica-core installs the skills (the one
that tells an agent when to reach for the tools, and five that explain,
summarize, compare, schematize and diagram from the indexed documents), and
nothing else. Shell recipes,
Docker and the REPL are in public/harnesses.md.
How the Claude Code plugin works
In Claude Code the plugin is all you need: it brings its own server and the
skills. The Install section above and silica-core setup claude
are for other clients; with both, two servers serve the same folder.
Install
It needs uv on PATH, which starts the server.
claude plugin install silica-core --marketplace kiycoh/silica-coreThat one step works on Claude Code 2.1.275 or later, and
/plugin install silica-core --marketplace kiycoh/silica-core does the same
inside a session. On an older client, add the marketplace first:
claude plugin marketplace add kiycoh/silica-core, then
claude plugin install silica-core@silica-core.
First run
Start Claude Code in the folder you want to search.
Wait for the first start. It is slower than the next ones: uv installs the packages and the server downloads its model, once.
Press Index above the prompt, or type
/silica-init. Nothing is indexed until you do.Ask a question about the folder. Claude searches it with
silica_search. Until the vectors are built the search is lexical, and its replies saydense: warming.
Update
Refresh the marketplace, then the plugin. The new version loads in the next session.
claude plugin marketplace update silica-core
claude plugin update silica-core@silica-coreWhat it runs, reads and downloads
The plugin is an MCP server plus a small mod in hooks/. Neither
one sends your files, prompts or conversation anywhere.
The server starts with
uv run --frozen --project <plugin folder>. The plugin folder is~/.claude/plugins/cache/silica-core/silica-core/<version>, with the versionclaude plugin listshows. The first time, uv installs the packages pinned inuv.lockfrom PyPI (and a Python build if the machine has no Python 3.11 or newer), and the server downloads thepotion-retrieval-32Mmodel from Hugging Face. Nothing else is downloaded.Indexing. In a folder that isn't indexed yet, the mod shows an Index button above the prompt;
/silica-initdoes the same. Either one runsuv run --frozen --project <plugin folder> --extra mcp --extra dense silica-core initin that folder, which writesvault.yamlthere (plus.silicaignorein a code repository) and builds the index under~/.silica. Not here hides the button for that folder. Nothing is indexed until you ask.Search hints. In an indexed folder, when you ask a question that names no file or symbol, the mod adds one line asking Claude to try
silica_searchbefore grep. It also adds the search guidance to the system prompt, unless yourCLAUDE.mdalready has it. The mod reads three environment variables,CLAUDE_CONFIG_DIR,HOMEandUSERPROFILE, only to find thatCLAUDE.mdand to skip your home folder.Docs upkeep. In an indexed folder with a
docs/folder, the mod helps Claude keep the docs in step with the code. It asks; Claude decides, and no write is ever refused.After a write worth recording (a new file, a manifest, 30 changed lines in a turn, or a file an ADR lists), Claude gets one reminder: bring
docs/up to date, or say there is nothing to record.When a turn that wrote under
docs/ends, the mod checks those files for links and code paths that lead nowhere, two ADRs with one number, and an accepted ADR whose Decision changed. Claude fixes what it agrees is a defect or says why it is not; the check asks at most twice a turn.At the start of an interactive session it reads
docs/adr/anddocs/specs/and runsgit, then shows above the prompt how many records name what is not there and how many have files that changed since./silica-docslists them.A record whose frontmatter has
implementation:(implemented,partial,pending,draft,droppedorn/a) is held to it:implementedandpartialname a commit or a path inimplemented_in,pendinganddraftname none,partialanddroppedcarry animplementation_note.
On an older Claude Code
The Index button, /silica-init, the search hints and the docs upkeep
come from the mod, which needs Claude Code 2.1.293 or later. An older client
still runs the server and the skills. Index a folder from a terminal opened
in it instead:
uv run --frozen --project <plugin folder> --extra mcp --extra dense silica-core initWhen it does not work
The silica tools are missing, or Claude Code says it could not connect to
plugin:silica-core:silica-core. The server did not start;/mcpshows its state. The usual causes are uv missing fromPATHand a first install that failed. Start the server by hand in the folder to read the error:uv run --frozen --project <plugin folder> --extra mcp --extra dense silica-core mcp --retrieval local-hybridWhen all is well it prints
serving 5 tools on stdio, waiting for a client; Ctrl+C ends it.No Index button. It never shows in your home folder or in
/, which are too large to index whole. After Not here it stays hidden in that folder, and/silica-initstill indexes it. On a client older than 2.1.293, see above.What this machine can read.
silica-core doctorchecks the install and the folder:uv run --frozen --project <plugin folder> --extra mcp --extra dense silica-core doctor
Uninstall
claude plugin uninstall silica-core@silica-coreThe plugin leaves two things behind:
vault.yaml, and.silicaignorein a code repository, in each folder you indexed;the indexes in
~/.silica/index/, one folder each.
Delete them by hand. An index deleted while the plugin is still installed is rebuilt the next time its folder is searched.
Notes
What it reads: markdown,
.txt,.rstand PDFs with a text layer directly, one PDF page per section; DOCX, EPUB, FB2, RTF, XLS and ODF converted with no extra; scanned PDFs, images, PPTX and XLSX throughsilica-core importwith MinerU; audio and video withffmpegplusSILICA_STT_BASE_URL; CSV readable by line, excluded from search. In a source tree the code lane adds source files and theirjson,yaml,toml,cfgandini.silica-core doctorsays which lanes this machine has.The dense leg: section embeddings that catch a paraphrase sharing no rare word with the answer.
uv tool installstays lexical untilsilica-core index --embed, with the[dense]extra's local model or any OpenAI-compatible/v1/embeddingsendpoint. Text leaves the machine only for a remote endpoint, and only aftersilica-core index --embed --allow-remotegrants that host once. Variables and reply states in TOOLS.md, the ollama recipe in public/harnesses.md.More surfaces:
silica-core mcp --extendedadds the wikilink tools;silica-core connect(extra[connect]) hosts the bridge the Obsidian plugin dials into, so writes land through the vault API while the app is open;silica-core replruns a small reference agent over the same tools, the one surface that needs a model (SILICA_MODEL).Not in the core: no memory lane, prompt injection, summaries or undo journal. Undo is git.
License
MIT. See LICENSE.
Available Tools
5 toolssilica_code_packARead-onlyIdempotent
Use before editing or explaining a source file, or when a traceback or
a diff names file:line: one call serves the file, a #Class.member, or
the symbol at #L<line>, with its supertypes, extenders, callers, the
signatures it names, external dependencies and importers, inside a
character budget. Static AST only, same repo state, same bytes. Check
truncated before treating the target as complete; dropped names what
did not fit. languages lists the parsers this install has.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Root-relative source path, optionally narrowed with '#Class', '#Class.member' or '#L<line>' (the symbol whose declaration spans that line) | |
| sections | No | Sections besides the target: any of 'hierarchy', 'callers', 'neighborhood', 'external', 'importers'. Empty = all | |
| budget_chars | No | Character budget for the whole pack; the target is always served |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), and the description adds real behavioral context on top: static AST only, no repo mutation between calls ('same repo state, same bytes'), an enforced character budget with the target always served, and the `truncated`/`dropped` signals an agent must check before trusting completeness. It also discloses that `languages` reports which parsers this install supports — an environment-dependent limitation.
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?
Four tightly packed sentences with the usage trigger front-loaded and no filler. The telegraphic style ('Static AST only, same repo state, same bytes') and heavy inline backticks make it slightly harder to parse than it needs to be, costing a point on structure.
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?
With no output schema, the description carries the full burden and discharges it: it enumerates the sections returned, explains the budget/truncation contract, names the meta-fields (`truncated`, `dropped`, `languages`), and states the static-analysis limitation. Nothing an agent needs to call and interpret this tool is missing.
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%, so target forms, section names, and the budget default are already documented in the schema. The description reinforces the budget concept ('inside a character budget', 'target is always served') but adds no syntax, format, or default details beyond what the schema states, so the baseline 3 applies.
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 names a specific resource — a 'pack' of structural facts (supertypes, extenders, callers, named signatures, external dependencies, importers) around a file, a `#Class.member`, or the symbol at `#L<line>` — and explicitly scopes it against the sibling tools' territory (raw file reading/searching). An agent can tell what this produces and when it differs from silica_read/silica_search without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete triggers: 'before editing or explaining a source file' and 'when a traceback or a diff names `file:line`'. That is clear when-to-use guidance, but it never names an alternative tool (e.g. 'instead of silica_read') or states an exclusion, so it stops short of the explicit routing a 5 requires.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
silica_filesARead-onlyIdempotent
Ask what the index could see before trusting a search or calling
absence. Inventory of the root and what the index did with each file: indexed
(in the index, matches disk), changed (differs from the index),
excluded (an ignore rule or a type the index does not read; reason
says which), failed (read or conversion error), unconverted (a PDF
whose text layer the index could not read, or an office file with no
extracted .md beside it; reason says which). A PDF is indexed from
its own text layer, one section per page, unless a .md sits beside it —
that sidecar is indexed instead, and both rows carry source_state:
stale means the original changed after the conversion, unverifiable
that the sidecar records no hash of it or its original is not under the
root. index.state is cold when nothing was
ever indexed: an empty listing there is not "no files".
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max entries per page | |
| cursor | No | `next_cursor` from the previous page | |
| folder | No | Root-relative folder to list; empty = the whole root | |
| status | No | Only this status: indexed, changed, excluded, failed, unconverted |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial context beyond them: what each status means, why a file is excluded or unconverted, the PDF-vs-sidecar indexing rule, the stale/unverifiable source_state semantics, and the cold index.state caveat. This is genuinely decision-relevant behavior that no structured field carries.
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?
It is long, but front-loaded with the motivating question and then information-dense: nearly every clause defines a distinct status or state rather than restating. Some parenthetical nesting makes it dense to parse, but little of it is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations covering return semantics, the description carries the full burden and does so: it enumerates all statuses, the reason fields, source_state values, and the cold-index edge case. An agent has enough to interpret the response correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description exceeds it by defining every value the status filter accepts (indexed, changed, excluded, failed, unconverted) and the meaning of each, plus the semantics of the empty-folder default, which helps the agent pick filter values rather than just names.
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 resource and scope ('Inventory of the root and what the index did with each file') with a precise taxonomy of per-file outcomes. It distinguishes itself from the read/search siblings implicitly ('before trusting a search'), but it never names itself as the listing/status tool in a single clean verb+resource clause, so the opening is slightly indirect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear usage context: consult this before trusting a search result or concluding a file is absent. That is real when-to-use guidance rather than vague framing, though it does not explicitly name silica_search/silica_read as the alternatives the agent would otherwise reach for.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
silica_readARead-onlyIdempotent
Read a located slice before citing it: lines start..end, one
section by heading, a PDF page, or the whole file when it fits
max_chars, always with the outline and a version;
truncated and next_start say how to continue. A PDF is served from
its own text layer, page by page: section="p. 8" serves one page —
the whole page, ~1.2k tokens (measured 2026-09-09), so ask for it to cite
a passage a search located, and widen the search's width to explore —
pages counts them, page_map gives the pages the slice covers, and
extract_path is that text on disk, for grep and the harness's own
reader (a cache, rebuilt when the PDF changes, under no version
guard). A PDF or office file with a .md extracted beside it is served
from that instead, and source_state says whether the original still
hashes to what the conversion recorded: stale means the PDF changed
and the .md did not, unverifiable that the sidecar records no hash or
its original is gone. Reading the .md itself, the path a search hit
carries, reports the same source and source_state.
Either way source names the original, and a PDF
with no readable text layer is error.unconverted. Carry
version forward as expect_version to be refused instead of reading
different bytes under an old citation; version is the served text's,
never the original's.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | Last line; 0 = to the end, under max_chars | |
| path | Yes | Root-relative file path (from silica_files or a search hit) | |
| start | No | First line, 1-based | |
| section | No | Serve this heading's section instead (exact title or unique prefix) | |
| max_chars | No | Cap on the served text | |
| expect_version | No | Refuse with error.changed when the file's version differs |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (readOnly, idempotent, non-destructive); the description adds far more: continuation via `truncated`/`next_start`, PDF page size (~1.2k tokens), extract_path as a cache rebuilt when the PDF changes and outside any `version` guard, `source_state` values (stale, unverifiable), and the `error.unconverted`/`error.changed` failure modes. This is unusually rich disclosure for a read 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 lead sentence is well front-loaded, but the body is overstuffed: nested parentheticals, backticked tokens, dated measurements ("measured 2026-09-09"), and cache-internals details make it hard to parse for a read tool. Much earns its place, but the density and length cost 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?
There is no output schema, so the description must describe returns, and it does: outline, version, truncated/next_start, pages, page_map, extract_path, source, and source_state, plus the error cases. For a read tool whose annotations already cover safety, nothing an agent needs to call it correctly is missing.
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%, so the terse per-parameter descriptions already carry the baseline. The prose adds real meaning beyond them: `section="p. 8"` serves one PDF page, `version` is the served text's and never the original's, and `expect_version` is the carry-forward guard that refuses rather than reading different bytes under an old citation.
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+resource ("Read a located slice before citing it") and enumerates the four serving modes: line range, heading section, PDF page, or whole file under max_chars. It distinguishes read from search by role ("a search located" vs. "widen the search's width to explore"), though it never names the sibling silica_search outright, leaving the routing slightly oblique.
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 states the core context clearly: use the read to pull the exact slice a search located so you can cite it, and points to search's `width` when you want to explore rather than cite. However there are no explicit exclusions or prerequisites (e.g., when to prefer silica_files), so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
silica_searchARead-onlyIdempotent
For a question that names no identifier (what a behaviour is, where
it is decided, why), call this before any grep (a Grep tool, or
grep or rg in a shell), Glob or Read: it ranks
passages and, in a source tree, the functions, methods, classes and
constants themselves, by the question's words and their vectors.
Do not grep for the words of a question; grep
for an exact string or a symbol name you already know. Each hit carries
its densest width-char window and line; a PDF's section is a page, so
on a PDF hit widen width (1200-1500) rather than reading the page.
matched_terms are the query terms in the hit; coverage is the share
of the query's idf mass they carry (near 1 = every rare term matched,
near 0 = only the common words); terms_absent are query terms found
nowhere in the corpus. No boolean "no answer" exists: read coverage and
matched_terms and decide to stop or rephrase. A hit the dense leg alone
found carries dense and coverage 0. In a source tree a hit's section
is the symbol, span its lines, and silica_read(path, section=<symbol>) serves its body.
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | Max hits | |
| query | Yes | Concise question or description of the concept or behavior to find; preserve known names and identifiers | |
| width | No | Characters in each hit's window | |
| folder | No | Only documents under this root-relative folder | |
| per_doc | No | Max sections per document | |
| queries | No | More query groups, each ranked on its own and fused with `query` by rank: the concept in one, its identifiers in another |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety and repeatability profile is covered. The description goes well beyond that by disclosing output semantics (matched_terms, coverage as idf mass, terms_absent, the dense-only leg with coverage 0), the absence of any boolean 'no answer', the PDF page/section behavior, and the section/span shape of source-tree hits.
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?
Front-loaded with the decisive trigger before any mechanics, and nearly every clause carries unique information (ranking basis, grep exclusion, width/PDF advice, coverage semantics, symbol routing). It is still a long, unbroken block of prose with several parentheticals, which costs it the top mark.
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?
There is no output schema, and the description compensates by naming the return fields and how to interpret them, describing the source-tree and PDF representations, and warning that no 'no answer' signal exists so the agent must read coverage and matched_terms. For a six-parameter search tool this is essentially 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?
Schema description coverage is 100%, so the baseline is 3 and the schema already documents all six parameters. The description adds operational meaning for `width` beyond 'Characters in each hit's window' by explaining that the window is the densest `width`-char segment and that on a PDF hit one should widen it to 1200-1500 rather than reading the page, plus the fused-queries intent of ranking concept and identifiers separately.
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?
States a concrete verb and resource (ranks passages, and in a source tree the functions/methods/classes/constants, by the question's words and vectors) and pins the exact scenario that selects it: a question naming no identifier. It explicitly contrasts itself with grep, Glob and Read, so an agent can tell it apart without opening the schema or sibling tools.
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?
Gives explicit when-to-use ('For a question that names no identifier... call this before any grep, Glob or Read') and when-not ('Do not grep for the words of a question; grep for an exact string or a symbol name you already know'). It also routes follow-up work to silica_read for symbol bodies, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
silica_write_noteA
Write one note atomically, as given, then lint it: lint lists
structural violations and unresolved wikilinks. Refuses to overwrite
when expect_version does not match or when create_only is set and
the file exists. Undo is git; the core keeps no journal.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Markdown body, written as given; a body escaped twice (no real newline, \n in their place) is decoded first | |
| path | Yes | Root-relative path of the note (.md added when missing) | |
| create_only | No | Refuse when the file already exists | |
| frontmatter | No | Optional YAML frontmatter, serialised on top of the body | |
| expect_version | No | Refuse with error.changed unless the existing file has this version |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only declaring the safety profile, the description adds the critical details: writes are atomic, a lint pass runs afterward and reports structural violations and unresolved wikilinks, overwrites are guarded by version/create_only checks, and rollback is git with no internal journal. That is substantial context beyond readOnlyHint/idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action, then failure conditions, then the recovery model. Every sentence carries information an agent needs.
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 guarded write with full schema coverage and no output schema, the definition is nearly complete. The only residual ambiguity is whether lint results are returned by this call or require a separate invocation, since `lint` in backticks reads like another tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so expect_version, create_only, body decoding, and frontmatter are already documented. The description reinforces the refusal semantics of expect_version and create_only but adds no format or syntax detail the schema lacks. Baseline 3 applies.
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?
States a specific verb+resource ('Write one note atomically') and immediately adds the post-write lint behavior. This cleanly separates it from read-only siblings (silica_read, silica_search, silica_files), none of which mutate notes.
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 'refuses to overwrite when expect_version does not match or when create_only is set and the file exists' clause tells the agent exactly when the call will fail and therefore which mode to pick for new vs. existing notes. It stops short of naming an alternative tool, but no write sibling exists to route to.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.11.0- First observed
silica_code_pack - First observed
silica_files - First observed
silica_read - First observed
silica_search - First observed
silica_write_note
TDQS
Scored across 5 tools
Each tool targets a distinct action: inventory (silica_files), semantic search (silica_search), slice reading (silica_read), symbol packing (silica_code_pack), and note writing (silica_write_note). However, silica_code_pack and silica_read both return code context and could be confused for symbol retrieval, though descriptions clarify packed vs. located slices.
All tools use the consistent `silica_` prefix followed by a snake_case noun or verb_noun (silica_code_pack, silica_files, silica_search, silica_read, silica_write_note). The pattern is predictable and readable throughout.
Five tools are well-scoped for a code and document indexing core: inventory, search, read, pack, and note writing. Each covers a distinct slice of the lifecycle without redundancy.
The surface covers discovery (search, files), reading (read, code_pack), and note creation, but lacks explicit update/delete operations for notes and any index management (e.g., rebuild or reindex). These gaps are minor and can be worked around with external tools like git.
Maintenance
Related MCP Connectors
Workspace knowledge bases agents ingest, search, and query over MCP.
Search GitHub, npm, PyPI, StackOverflow, ArXiv from one MCP — built for coding agents.
Securely search and manage workspace context files for AI agents and teams.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceProvides a local-first code indexing and search engine for coding agents via MCP, enabling precise codebase queries, symbol lookup, and freshness-aware retrieval.-
- FlicenseNot gradedqualityAmaintenanceLocal-first MCP toolkit that provides coding agents focused repository context via read_file, search_files, and edit_file tools, reducing token usage and task cost.1-
- AlicenseNot gradedqualityBmaintenanceProvides IDE-like coding capabilities for AI agents via MCP, enabling semantic code retrieval, symbol-level editing, refactoring, and navigation across many programming languages.MIT
- AlicenseCqualityBmaintenanceLocal-first MCP runtime for coding agents with bounded workspace access, content-preconditioned writes, AST search, LSP navigation and diagnostics, and Git status/diff. Designed to give coding agents useful repository access without treating unrestricted shell access as the default integration boundary.133MIT