
Docsonar
io.github.ribhav-jainPublished by GitHub account ribhav-jainv0.1.1Updated Oct 27, 2026
Local document search over your folders: hybrid keyword+semantic, fully offline, read-only
Overview
Docsonar is a local, offline MCP server that indexes folders of documents into SQLite and gives an assistant hybrid keyword plus semantic search over them.
- What you can do
- Register, list and remove document folders, with background indexing and status reporting
- Search registered folders with hybrid, keyword-only or semantic modes, returning ranked passages with file path, heading or page location and snippet
- Read extracted text from txt, md, pdf, docx and html files, optionally by line range
- Find documents similar in meaning to a given file
- Reindex incrementally to pick up new or changed files and purge deleted ones
- When to use it
- Useful when an assistant should answer questions from a personal or project document collection on the same machine, with citations to file and page, and without sending files to a cloud service. It suits PDF, Word, Markdown and HTML notes, reports and policies rather than live web or database content.
- Requirements
- Runs as a local stdio process, launched with uvx (uv installs the needed Python). No accounts, API keys or environment variables. The first index downloads a local embedding model of roughly 130 MB; keyword search works before it finishes. Optional config.toml and CLI flags for transport, port, database path and model.
Installation
In SourceWeft
- Open Docsonar in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
docsonar
[PyPI] [CI] [Python] [License: MIT]
Chat with your folders. A local document search MCP server — your files never leave your machine.
docsonar indexes folders of documents into a single SQLite database and gives any MCP client (Claude Desktop, Claude Code, and others) hybrid keyword + semantic search over them. Fully offline, zero configuration, read-only by design.
Quickstart
Claude Code
Add to your project's .mcp.json (or ~/.claude.json for all projects):
Claude Desktop
Add to claude_desktop_config.json (Settings → Developer → Edit Config):
Running from a source checkout instead: "command": "uv", "args": ["run", "--directory", "/path/to/docsonar", "docsonar"].
Then just talk to it: "Add my ~/Documents/notes folder and find everything about quarterly planning." The first index downloads the embedding model (~130 MB, one time); keyword search works immediately while that happens.
For HTTP instead of stdio: uvx docsonar --transport http --port 8365.
Tools
Supported formats: txt, md, pdf (page-aware, cites p. 12), docx, html.
Architecture
Every chunk stores its location (heading path like Setup > Windows, or PDF page range), so search results can cite report.pdf, p. 12.
Design decisions
- Read-only by design. There are no write, move, or delete tools, and there never will be. The server only reads files inside folders you explicitly register — with symlink-escape protection and strict path resolution — so the blast radius of a misbehaving client is zero.
- SQLite as the single store. FTS5 gives production-grade BM25 keyword search in the standard library, and sqlite-vec puts vectors in the same file. One database file, no services to run, trivial to back up or delete.
- Hybrid search by default. BM25 and cosine-KNN rankings are fused with reciprocal-rank fusion (k=60). Exact identifiers and rare terms win on the keyword side; paraphrased questions win on the semantic side; RRF needs no score calibration between them.
modelets the caller force either side. - Local embeddings. BAAI/bge-small-en-v1.5 (384-dim) — same size class as the classic all-MiniLM-L6-v2 but stronger on retrieval benchmarks. Downloads on first index, runs on CPU, lazy-loaded so server startup stays instant. If the model can't load, everything degrades gracefully to keyword search and tool responses say so.
- A tool surface built for an LLM caller.
searchreturns enough per hit (path, location, score, snippet) to decide what to read next without another round trip; results carry stablechunk_ids; every degradation is reported in-band vianote/embedding_notefields instead of failing. There's no "answer the question" tool on purpose — the calling model does the reasoning; docsonar does retrieval. - Incremental by content, not just mtime. Reindexing checks mtime+size first, then falls back to a SHA-256 content hash — touched-but-identical files are skipped, and deleted files are purged from both the FTS and vector indexes.
- Scanned PDFs fail loudly. A PDF with no extractable text is reported as failed with a clear reason rather than silently indexed as empty. OCR is out of scope.
Benchmarks
Synthetic corpus of 200 markdown files (600 chunks); Intel Core Ultra 5 125U (laptop, CPU-only), Windows 11, Python 3.12. Reproduce with uv run python scripts/benchmark.py.
Configuration
Zero config needed. To customize, create config.toml in the platform config directory (Windows: %LOCALAPPDATA%\docsonar\, macOS: ~/Library/Application Support/docsonar/, Linux: ~/.config/docsonar/):
CLI flags: --transport stdio|http, --host, --port, --db-path, --config.
The index database lives in the platform data directory (Windows: %LOCALAPPDATA%\docsonar\, macOS: ~/Library/Application Support/docsonar/, Linux: ~/.local/share/docsonar/).
Running from source
Requires uv (it installs the right Python automatically):
Run the tests
Run the server
VS Code: press F5 — launch configs for the HTTP server and the test suite are in .vscode/launch.json.
Try the tools without an MCP client
With the HTTP server running, the endpoint is http://127.0.0.1:8365/mcp. Recent Postman versions can connect directly (New → MCP Request, transport HTTP) and show all 8 tools as forms. For raw HTTP, MCP is JSON-RPC over POST with two setup calls, then tool calls. Send every request with headers Content-Type: application/json and Accept: application/json, text/event-stream:
Then call tools — the repo ships a sample corpus in examples/sample-docs to play with (use forward slashes in JSON to avoid escaping; they work on Windows too):
Security check worth trying: read_file with any path outside a registered folder (e.g. C:/Windows/System32/drivers/etc/hosts) returns a refusal, not file content.
CI runs lint, typecheck, and the test suite on Linux, macOS, and Windows.
License
MIT
Source: README.md at commit 2b8da82
Tools
0Version history
1- v0.1.1LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts

