Ваш кодовый агент очень хорошо находит вещи в репозитории, пока они представлены в виде текста. Спросите Claude Code или Cursor, что даташит датчика говорит о рабочей температуре, и он выполнит grep, ничего не найдёт и либо будет угадывать, либо сдастся, потому что даташит — это PDF, а запись решения — файл Word. GroupDocs.Search.Mcp работает локально в Docker и предоставляет агенту полнотекстовый индекс этих документов, используя тот же цикл «поиск‑затем‑чтение», который он уже применяет к коду:

Проиндексировать папку 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. После pull команда 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 использует те же command и args в разделе mcpServers файла .cursor/mcp.json. Закоммитьте файл конфигурации, и каждый разработчик проекта получит инструмент; держите сам индекс вне git.

Почему бы не конвертировать всё в текст заранее?

Можно: заставить агента конвертировать каждый PDF по мере необходимости или проверять копии в Markdown в репозитории. Оба подхода работают для небольшого количества файлов. Индекс выполняет конвертацию один раз, поддерживает её актуальной одним вызовом и отвечает, какой файл важен, ещё до того, как агент начнёт чтение, что уменьшает объём контекста длительной сессии. Движок за этим — GroupDocs.Search, который читает Office‑ и PDF‑документы напрямую, без необходимости поддерживать отдельный конвертер.

Честные ограничения

  • В режиме оценки индекс хранит не более 100 документов, а поиск возвращает не более 10; сначала вызовите get_license_status.
  • Полнотекстовый поиск, а не семантический: агент вынужден использовать именно те слова, которые присутствуют в документах, или пробовать варианты.
  • Нет OCR: отсканированный даташит без текстового слоя индексируется только по свойствам файла.
  • Только Docker. На Linux добавьте --user "$(id -u):$(id -g)", чтобы контейнер мог записать индекс в ваш репозиторий.

FAQ

Может ли Claude Code читать PDF‑файлы в моём репозитории?
Не с помощью grep. С сервером GroupDocs.Search MCP он может искать и цитировать их локально, без предварительной конвертации.

Работает ли это в Cursor и VS Code?
Да. Используйте те же аргументы docker run в .cursor/mcp.json или .vscode/mcp.json; VS Code может монтировать ${workspaceFolder}.

Попадёт ли индекс в мои коммиты?
Только если вы позволите. Добавьте .groupdocs-search-index/ в .gitignore.

Углубиться