mcpField
D
docsonar

docsonar

本地服务
github.com/ribhav-jain搜索与检索014 周前更新

关于 docsonar

docsonar 是面向本地文档文件夹的 MCP 服务,适合希望在设备上检索文件而不上传内容的用户。它结合关键词与语义搜索,并将访问限制为只读且仅限已注册文件夹。

主要功能

  1. 01关键词与语义混合搜索
  2. 02索引 TXT、Markdown、PDF、DOCX 和 HTML
  3. 03读取匹配的文件段落
  4. 04查找语义相似的文档
  5. 05增量索引与状态查询

适用场景

  1. 01按主题或标识符搜索笔记
  2. 02定位 PDF 段落并获取页码
  3. 03文件变更后刷新索引

MCP 相关

向 MCP 客户端提供八种工具,用于注册文件夹、索引、搜索、读取文件和查看索引状态。支持 stdio 与 HTTP 传输。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"ribhav-jain-docsonar": {
"command": "uvx",
"args": [
"docsonar"
]
}
}
}
启动命令uvx docsonar

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypidocsonar0.1.1

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

docsonar

PyPI CI Python License: MIT

与文件夹对话。 本地文档搜索 MCP 服务——你的文件永远不会离开你的设备。

docsonar 会将文档文件夹索引到单个 SQLite 数据库中,让任何 MCP 客户端(Claude Desktop、Claude Code 等)都能对这些文档进行关键词与语义混合搜索。完全离线、零配置,设计上只读。

快速开始

Claude Code

添加到项目的 .mcp.json(或所有项目通用的 ~/.claude.json)中:

{
  "mcpServers": {
    "docsonar": {
      "command": "uvx",
      "args": ["docsonar"]
    }
  }
}
Claude Desktop

添加到 claude_desktop_config.json(Settings → Developer → Edit Config)中:

{
  "mcpServers": {
    "docsonar": {
      "command": "uvx",
      "args": ["docsonar"]
    }
  }
}

如果要从源代码检出目录运行:"command": "uv", "args": ["run", "--directory", "/path/to/docsonar", "docsonar"]。

然后直接与它对话:“添加我的 ~/Documents/notes 文件夹,并查找所有关于季度规划的内容。” 首次建立索引时会下载嵌入模型(约 130 MB,仅需下载一次);下载期间关键词搜索仍可立即使用。

如需使用 HTTP 而非 stdio:uvx docsonar --transport http --port 8365。

工具

工具用途
add_folder(path, include_globs?, exclude_globs?)注册文件夹;索引在后台开始
remove_folder(path)取消注册并清除其索引数据
list_folders()已注册文件夹及其文件数量和最近索引时间
search(query, top_k?, folder?, file_type?, mode?)关键词与语义混合搜索(RRF 融合);按相关性排序的段落,包含文件路径、标题/页码位置和摘要
read_file(path, start_line?, end_line?)文件文本(pdf/docx/html 提取的文本);拒绝读取已注册文件夹以外的路径
find_similar(path, top_k?)与指定文件语义最相似的文档
reindex(folder?, force?)增量刷新:重新索引新增或更改的文件,并清除已删除文件的数据
index_status()索引总数、嵌入模型状态、后台任务进度和失败文件

支持的格式:txt、md、pdf(可识别页码,引用格式为 p. 12)、docx、html。

架构

flowchart LR
    Client["MCP client<br/>(Claude Desktop / Code)"] <-->|stdio or HTTP| Server["FastMCP server<br/>8 tools"]
    Server --> Sec["path security<br/>(registered folders only)"]
    Server --> Search["hybrid search<br/>BM25 + cosine KNN + RRF"]
    Server --> Worker["background indexer<br/>(worker thread + queue)"]
    Worker --> Parsers["parsers<br/>txt · md · pdf · docx · html"]
    Parsers --> Chunker["heading/page-aware chunker<br/>~400 tokens, 60 overlap"]
    Chunker --> DB[("SQLite<br/>FTS5 + sqlite-vec")]
    Search --> DB
    Embed["sentence-transformers<br/>bge-small-en-v1.5 (local)"] --> Worker
    Embed --> Search

每个文本块都会保存其位置(例如 Setup > Windows 这样的标题路径,或 PDF 页码范围),因此搜索结果可以引用 report.pdf, p. 12。

设计决策

  • 从设计上确保只读。 没有写入、移动或删除工具,以后也不会有。服务端只会读取你明确注册的文件夹中的文件,并提供符号链接逃逸防护和严格的路径解析,因此客户端行为失常时的影响范围为零。
  • 使用 SQLite 作为唯一存储。 FTS5 在标准库中提供生产级的 BM25 关键词搜索,sqlite-vec 则将向量存储在同一个文件中。只需一个数据库文件,无需运行服务,备份或删除都很简单。
  • 默认使用混合搜索。 BM25 和余弦 KNN 排名通过倒数排名融合(k=60)进行合并。精确标识符和罕见词在关键词搜索中表现更好;改述后的问题在语义搜索中表现更好;RRF 无需校准两者之间的分数。调用方可通过 mode 强制使用其中一种。
  • 使用本地嵌入。 BAAI/bge-small-en-v1.5(384 维)——与经典的 all-MiniLM-L6-v2 属于同一尺寸级别,但在检索基准测试中表现更好。首次建立索引时下载,可在 CPU 上运行,采用延迟加载,因此服务端可瞬间启动。如果模型无法加载,所有功能都会平稳降级为关键词搜索,工具响应也会说明这一点。
  • 专为 LLM 调用方设计的工具接口。 search 会为每个命中项返回足够的信息(路径、位置、分数、片段),让调用方无需再次往返即可决定接下来读取什么;结果带有稳定的 chunk_id;每次降级都会通过 note/embedding_note 字段在响应中说明,而不是直接失败。这里有意不提供“回答问题”的工具——推理由调用模型完成;docsonar 负责检索。
  • 根据内容增量更新,而不只看 mtime。 重新建立索引时会先检查 mtime 和大小,再回退到 SHA-256 内容哈希——内容未变但修改时间有变化的文件会被跳过,已删除的文件会从 FTS 和向量索引中清除。
  • 扫描版 PDF 会明确报错。 没有可提取文本的 PDF 会以清晰的原因报告为失败,而不会被静默地作为空文件编入索引。OCR 不在范围内。

基准测试

合成语料库包含 200 个 Markdown 文件(600 个片段);Intel Core Ultra 5 125U(笔记本电脑,仅使用 CPU)、Windows 11、Python 3.12。使用 uv run python scripts/benchmark.py 重现。

操作结果
建立索引,仅关键词搜索0.7 s(≈280 个文件/s)
建立索引,包含嵌入59 s(≈3.4 个文件/s——受嵌入速度限制)
增量重新建立索引,没有更改0.03 s
关键词搜索中位数 8.9 ms
语义搜索中位数 35 ms
混合搜索中位数 54 ms
嵌入模型加载(每个进程一次)~21 s
数据库大小2.6 MB(仅关键词搜索时为 1.1 MB)

配置

无需任何配置。如需自定义,请在平台配置目录中创建 config.toml(Windows:%LOCALAPPDATA%\docsonar\,macOS:~/Library/Application Support/docsonar/,Linux:~/.config/docsonar/):

embedding_model = "BAAI/bge-small-en-v1.5"  # any sentence-transformers model
chunk_target_tokens = 400
chunk_max_tokens = 512
chunk_min_tokens = 100
chunk_overlap_tokens = 60
max_file_size_mb = 50
extra_ignore_dirs = ["Archive"]

CLI 标志:--transport stdio|http、--host、--port、--db-path、--config。

索引数据库位于平台数据目录中(Windows:%LOCALAPPDATA%\docsonar\,macOS:~/Library/Application Support/docsonar/,Linux:~/.local/share/docsonar/)。

从源代码运行

需要 uv(它会自动安装正确的 Python 版本):

# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

git clone https://github.com/ribhav-jain/docsonar.git
cd docsonar
uv sync --dev    # creates .venv and installs everything, incl. dev tools
运行测试
uv run pytest                          # full suite (~2 s, no model download needed)
uv run pytest -v                       # verbose, one line per test
uv run pytest tests/test_search.py     # one file
uv run pytest -k incremental           # tests matching a keyword
uv run ruff check .                    # lint
uv run mypy src tests                  # strict typecheck
uv run python scripts/benchmark.py     # perf numbers (downloads the real model)
运行服务端
uv run docsonar                                  # stdio — for MCP clients (Claude Desktop/Code)
uv run docsonar --transport http --port 8365     # HTTP — for manual testing (Postman, curl)

VS Code:按 F5——HTTP 服务端和测试套件的启动配置位于 .vscode/launch.json。

无需 MCP 客户端即可试用这些工具

HTTP 服务运行后,端点为 http://127.0.0.1:8365/mcp。较新版本的 Postman 可以直接连接(New → MCP Request,传输方式为 HTTP),并以表单形式显示全部 8 个工具。对于原始 HTTP,MCP 使用 POST 传输 JSON-RPC,需要先发送两个初始化调用,然后再调用工具。每个请求都要包含标头 Content-Type: application/json 和 Accept: application/json, text/event-stream:

// 1. initialize — copy the `mcp-session-id` RESPONSE header and send it
//    back as a request header on every call below
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"postman","version":"1.0"}}}

// 2. initialized notification (expect 202, empty body)
{"jsonrpc":"2.0","method":"notifications/initialized"}

// 3. list the tools
{"jsonrpc":"2.0","id":2,"method":"tools/list"}

然后调用工具——仓库在 examples/sample-docs 中附带了示例语料,供你试用(在 JSON 中使用正斜杠以避免转义;在 Windows 上也可用):

// Register the sample folder (first ever call downloads the embedding model, ~30 s)
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"add_folder",
  "arguments":{"path":"C:/path/to/docsonar/examples/sample-docs"}}}

// Watch indexing progress until indexing.active is false
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"index_status","arguments":{}}}

// Hybrid search — finds the expense-policy PDF, cites its page
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"search",
  "arguments":{"query":"meal reimbursement limit","top_k":3,"mode":"hybrid"}}}

// Semantic search — no keyword overlap needed
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"search",
  "arguments":{"query":"how hot should water be for green tea","mode":"semantic"}}}

// Read a hit (works on PDFs too — returns extracted text)
{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"read_file",
  "arguments":{"path":"C:/path/to/docsonar/examples/sample-docs/expense-policy.pdf"}}}

// "More like this"
{"jsonrpc":"2.0","id":8,"method":"tools/call","params":{"name":"find_similar",
  "arguments":{"path":"C:/path/to/docsonar/examples/sample-docs/espresso-guide.md","top_k":3}}}

// Refresh after files change on disk (force:true rebuilds everything)
{"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"reindex","arguments":{}}}

// Clean up — unregisters the folder and purges its index data
{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"remove_folder",
  "arguments":{"path":"C:/path/to/docsonar/examples/sample-docs"}}}

值得一试的安全检查:使用 read_file 读取注册文件夹之外的任意路径(例如 C:/Windows/System32/drivers/etc/hosts),将返回拒绝信息,而非文件内容。

CI 会在 Linux、macOS 和 Windows 上运行 lint、类型检查和测试套件。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。