mcp-local-rag
Search, ingest, expand chunk context, or manage local documents via a local RAG MCP server (tools: query_documents, read_chunk_neighbors, ingest_file, ingest_data, delete_file, list_files). Use when user says "search my docs", "save this page", "read around that chunk", "what did I save about X", or invokes `npx mcp-local-rag`.
git clone https://github.com/shinpr/mcp-local-rag
T=$(mktemp -d) && git clone --depth=1 https://github.com/shinpr/mcp-local-rag "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/mcp-local-rag" ~/.claude/skills/shinpr-mcp-local-rag-mcp-local-rag && rm -rf "$T"
skills/mcp-local-rag/SKILL.mdMCP Local RAG Skills
Tools
| MCP Tool | CLI Equivalent | Use When |
|---|---|---|
| | Local files (PDF, DOCX, TXT, MD). CLI for bulk/directory. |
| — | Raw content (HTML, text) with source URL |
| | Semantic + keyword hybrid search |
| | Remove ingested content |
| | File ingestion status |
| | Database stats |
| | Read N chunks adjacent to a known chunkIndex (context expansion; call after or grep) |
Search: Core Rules
Hybrid search combines vector (semantic) and keyword (BM25).
Score Interpretation
Lower = better match. Use this to filter noise.
| Score | Action |
|---|---|
| < 0.3 | Use directly |
| 0.3-0.5 | Include if mentions same concept/entity |
| 0.5-0.7 | Include only if directly relevant to the question |
| > 0.7 | Skip unless no better results |
Limit Selection
| Intent | Limit |
|---|---|
| Specific answer (function, error) | 5 |
| General understanding | 10 |
| Comprehensive survey | 20 |
Query Formulation
| Situation | Why Transform | Action |
|---|---|---|
| Specific term mentioned | Keyword search needs exact match | KEEP term |
| Vague query | Vector search needs semantic signal | ADD context |
| Error stack or code block | Long text dilutes relevance | EXTRACT core keywords |
| Multiple distinct topics | Single query conflates results | SPLIT queries |
| Few/poor results | Term mismatch | EXPAND (see below) |
Query Expansion
When results are few or all score > 0.5, expand query terms:
- Keep original term first, add 2-4 variants
- Types: synonyms, abbreviations, related terms, word forms
- Example:
→"config""config configuration settings configure"
Avoid over-expansion (causes topic drift).
Result Selection
When to include vs skip—based on answer quality, not just score.
INCLUDE if:
- Directly answers the question
- Provides necessary context
- Score < 0.5
SKIP if:
- Same keyword, unrelated context
- Score > 0.7
- Mentions term without explanation
fileTitle
Each result includes
fileTitle (document title extracted from content). Null when extraction fails.
| Use | How |
|---|---|
| Disambiguate chunks | Use fileTitle to identify which document the chunk belongs to |
| Group related chunks | Same fileTitle = same document context |
| Deprioritize mismatches | fileTitle unrelated to query AND score > 0.5 → rank lower |
Context Expansion (read_chunk_neighbors)
read_chunk_neighbors (CLI: read-neighbors) is an on-demand context expansion utility, not a routine follow-up to every query_documents call. Chunks in this index are semantic units — sentences or paragraphs grouped by topic via Max-Min semantic chunking, not fixed-size text slices. Reading the chunks immediately before and after a target chunk yields coherent surrounding context, not arbitrary fragments.
Each
query_documents result item already includes filePath and chunkIndex. Pass those to read_chunk_neighbors to expand a specific hit in place.
Trigger this tool only when one of these signals is present:
- Insufficient context for your answer: during response generation, the target chunk alone is not enough to reach a grounded conclusion (e.g., it references "this approach" or "as shown above" without the referent).
- Explicit user request for more context: the user asks for surrounding detail ("what comes before that?", "read more around that section", "show me the full explanation").
If neither signal is present, stop at the
query_documents results.
Typical workflow when triggered:
- Identify the specific chunk to expand (from a prior
hit orquery_documents
).grep - Take that chunk's
andfilePath
.chunkIndex - Call
with those values; the response contains the target chunk plus its semantic neighbors, sorted byread_chunk_neighbors
.chunkIndex
See cli-reference.md for output fields and an example.
Ingestion
ingest_file
ingest_file({ filePath: "/absolute/path/to/document.pdf" })
ingest_data
ingest_data({ content: "<html>...</html>", metadata: { source: "https://example.com/page", format: "html" } })
Format selection — match the data you have:
- HTML string →
format: "html" - Markdown string →
format: "markdown" - Other →
format: "text"
Source format:
- Web page → Use URL:
https://example.com/page - Other content → Use scheme:
or{type}://{date}
where{type}://{date}/{detail}
is a short identifier for the content origin (e.g., clipboard, chat, note, meeting){type}
HTML source options:
- Static page → HTTP fetch
- SPA/JS-rendered → Browser/web tool with DOM rendering
- Auth required → Manual paste
If HTTP fetch returns empty or minimal content, retry with a browser/web tool.
Source URLs are normalized: query strings and fragments are stripped. See html-ingestion.md for cases where this matters.
Re-ingest same source to update. Use same source in
delete_file to remove.
CLI commands
CLI subcommands mirror MCP tools. Useful for bulk operations, scripting, and environments without MCP.
,query
,list
,status
output JSON to stdoutdelete
outputs progress to stderringest- Use
on any command for options--help - See cli-reference.md for options and config matching
References
For edge cases and examples:
- html-ingestion.md - URL normalization, SPA handling
- query-optimization.md - Query patterns by intent
- result-refinement.md - Synthesis vs filter strategy, contradiction resolution, chunking
- cli-reference.md - CLI command options, config matching, output conventions