你的编码代理在仓库中查找内容时非常擅长,只要这些内容是文本。让 Claude Code 或 Cursor 查询传感器数据表中关于工作温度的说明时,它会使用 grep,却找不到任何内容,随后要么猜测要么放弃,因为数据表是 PDF,决策记录是 Word 文件。
索引 docs 文件夹,然后告诉我传感器数据表中关于工作温度的说明以及哪个 ADR 决定了遥测存储。
带有配置和故障排除的逐步版本在文档中:如何让 Claude Code 或 Cursor 在仓库中搜索 PDF 和 Word 文档.
为什么 grep 返回空结果?
因为 PDF 和 DOCX 并未以纯文本形式存储其单词。DOCX 实际上是一个 zip 压缩包;PDF 则压缩了其文本流。逐字节搜索时,这些单词根本不存在。我们在一个小型仓库中进行了测试:一个 PDF 数据表、一个架构决策记录、一个 DOCX 格式的需求文档,以及一个源代码文件。
$ grep -ri "TimescaleDB\|operating temperature\|I2C" docs/
$ grep -rn "datasheet" src/
src/sensor.py:1:MAX_TEMP_C = 85 # see docs/datasheet
唯一的匹配是一条指向文档的代码注释,而代理无法读取该文档。这就是差距所在:常量背后的原因、设计背后的决策、测试背后的需求往往正好存在于这些文件中。
建立索引后会有什么变化?
代理获得了文档检索工具。请在仓库根目录注册服务器,使仓库被挂载为存储文件夹:
claude mcp add groupdocs-search -- docker run --rm -i \
-v "$(pwd)":/data ghcr.io/groupdocs-search/search-net-mcp:latest
然后相同的问题会得到答案。这是服务器在我们的测试仓库中返回的内容(路径相对于仓库根目录显示):
-> add_to_index {"documentsPath":"docs","indexName":"gateway"}
<- Indexed 'docs' into index 'gateway': 3 document(s) added,
3 in the index.
-> search {"query":"TimescaleDB","indexName":"gateway"}
<- documentsFound 1: docs/adr-007-telemetry-storage.docx
-> get_text_fragments {"query":"I2C","indexName":"gateway"}
<- === docs/requirements-v2.docx (1 occurrence(s)) ===
…REQ-15: the I2C bus runs at 400 kHz.…
=== docs/tmp117-sensor-datasheet.pdf (1 occurrence(s)) ===
…I2C address selection: ADD0 pin to GND gives 0x48…
一次查询同时找到了需求和数据表中的行,这类交叉引用手动操作非常繁琐,且 grep 无法实现。在我们的小型索引中,搜索在首次调用后返回的时间为 80 到 240 毫秒。
代理已经熟悉的循环
user agent Search MCP server
| "What does the datasheet say about I2C addresses?" |
|---------------->| |
| |-- search {"query":"I2C"} --------------->|
| |<- requirements-v2.docx, |
| | tmp117-sensor-datasheet.pdf ------------|
| |-- get_text_fragments {"query":"I2C"} --->|
| |<- "...ADD0 pin to GND gives 0x48..." -----|
|<- "0x48 with ADD0 to GND, 0x49 to V+ (datasheet, p.1); |
| REQ-15 runs the bus at 400 kHz." |
search 返回匹配的文件,get_text_fragments 返回带有少量上下文的匹配行,代理会引用两者。这相当于 grep 的功能,但扩展到了 82 种格式:PDF、DOCX、XLSX、PPTX、HTML、Markdown,甚至是有人导入仓库的电子邮件线程。
告诉代理何时使用它
代理会遵循项目指令来决定何时使用工具。在 CLAUDE.md 或 AGENTS.md 中的三行指令可以区分出尝试使用 grep、失败并放弃的代理,以及首先搜索索引的代理:
PDF, DOCX and XLSX files under docs/ are indexed in the groupdocs-search MCP index
'docs'. grep cannot read them: use search (quote phrases) and get_text_fragments
for anything in specs, datasheets or ADRs, and cite the file.
Run update_index (indexName: docs) after pulling changes.
还有两点注意事项。索引会写入挂载文件夹根目录下的 .groupdocs-search-index/,因此请将其加入 .gitignore。在拉取代码后,update_index 只会重新读取有变动的部分,因此保持索引最新只需一次调用。
Cursor 与 VS Code
相同的容器可在任何 MCP 客户端中使用。在 VS Code 中,工作区的 .vscode/mcp.json 可以挂载当前打开的任意文件夹,从而使索引随项目而动:
{
"servers": {
"groupdocs-search": {
"type": "stdio",
"command": "docker",
"args": [ "run", "--rm", "-i",
"-v", "${workspaceFolder}:/data",
"ghcr.io/groupdocs-search/search-net-mcp:latest" ]
}
}
}
Cursor 在 .cursor/mcp.json 中的 mcpServers 下使用相同的 command 和 args。将配置文件提交后,项目中的每位开发者都能获得该工具;请将索引本身排除在 git 之外。
为什么不先将所有文件转换为文本?
可以的:让代理在需要时转换每个 PDF,或在仓库中放置 Markdown 副本。对于少量文件这两种方式都可行。索引只会进行一次转换,并通过一次调用保持最新,并在代理读取任何内容之前就告知哪个文件相关,这一步可以让长会话的上下文保持简短。其背后的引擎是 GroupDocs.Search,它直接读取 Office 和 PDF 文档,而无需你维护转换器。
真实的限制
- 在评估模式下,索引最多容纳 100 个文档,搜索最多返回 10 条结果;请先调用
get_license_status。 - 全文本检索,而非语义检索:代理必须使用文档中的词汇,或尝试其变体。
- 不支持 OCR:仅有扫描图像且没有文本层的数据表只能通过文件属性进行索引。
- 仅限 Docker。在 Linux 上,添加
--user "$(id -u):$(id -g)"以便容器能够将索引写入你拥有的仓库。
常见问题
Claude Code 能读取我仓库中的 PDF 文件吗?
使用 grep 无法实现。借助 GroupDocs.Search MCP 服务器,它可以在本地搜索并引用 PDF,而无需先进行转换。
它在 Cursor 和 VS Code 中也能工作吗?
可以。 在 .cursor/mcp.json 或 .vscode/mcp.json 中使用相同的 docker run 参数;VS Code 可以挂载 ${workspaceFolder}。
索引会出现在我的提交中吗?
只有在你允许的情况下才会。请将 .groupdocs-search-index/ 加入 .gitignore。
深入了解
- 文档,权威操作指南:如何让 Claude Code 或 Cursor 在仓库中搜索 PDF 和 Word 文档
- 文档中心:GroupDocs.Search MCP 服务器文档中心
- 入门指南:是否需要向量数据库来对文档文件夹进行提问?
- 相关:基于文件的可靠答案:引用原文段落,而非模型记忆
- 相关:AI 代理的项目记忆:每个项目一个索引,保持最新
- 相关:为何 AI 代理不应阅读 300 份合同来回答一个问题
- 相关:使用 AI 代理搜索邮件存档:PST、MSG、EML 及其附件
- 本地部署与安全模型:AI 文档处理的三种架构,以及将文件保留在内部网络的方案
- 问题讨论:GroupDocs Search 论坛
- 源代码:GitHub 上的 GroupDocs.Search.Mcp