Skip to main content
Glama

docs-rag-mcp

Это не лучший поисковик по вашим документам. Это фильтр того, во что агенту разрешено верить: устаревшие решения исчезают, порог говорит «я не знаю» вместо того, чтобы выдумывать, и вы всегда видите, почему результат попал в выдачу.

MCP-сервер, который предоставляет папку с markdown-документами любому MCP-клиенту (Claude Code, Claude Desktop, Codex, Cursor, Zed…) как один инструмент поиска — search_notes. Всё выполняется на вашей машине: эмбеддинги проходят через Ollama, и ничто не покидает ваш компьютер ни при индексации, ни при запросе.

npx -y docs-rag-mcp init      # guided questions -> config.json
npx -y docs-rag-mcp index     # builds the index

Пишете документацию, по которой будете искать? От того, как вы структурируете markdown-файл, зависит, насколько хорошо его можно найти. См. AUTHORING.md — краткое руководство по написанию документов, которые хорошо находятся. Пять минут там улучшают каждый поиск.

Что здесь действительно по-другому

Большую часть того, что делает этот инструмент, умеют и другие локальные RAG-серверы. По-настоящему редкая часть — это жизненный цикл документа: индекс знает, что документ устарел, и реагирует на это.

  • Документ с пометкой status: superseded во frontmatter перестаёт возвращаться по умолчанию. Когда он всё же возвращается — потому что вы явно запросили историю — он приходит с пометкой [superseded → reference/auth.md; 2026-03-01], то есть вместе с преемником.

  • Ниже minScore инструмент сообщает "No relevant results (best score 0.41, threshold 0.55)" вместо того, чтобы отдать ближайший найденный шум. Агент, получивший плохое совпадение, принимает его за истину; человек бы заколебался. Порог — это место, где живёт эта неуверенность.

  • Каждый результат показывает, почему он здесь: [semantic 0.712], [both 0.712], [exact match]. Это не чёрный ящик, которому приходится доверять.

Все остальные занимаются свежестью файлов — повторная синхронизация, переиндексация, отслеживание изменений. Никто не занимается свежестью истины. В этом весь смысл этого инструмента.

подход

учитывает жизненный цикл документа?

docs-rag-mcp

dense + lexical, SQLite, Ollama

даstatus/superseded_by, исключаемые по умолчанию архивы, честный ответ об отсутствии результатов

zilliztech/claude-context

hybrid BM25+dense, AST chunking, Milvus

нет

shinpr/mcp-local-rag

semantic+keyword, LanceDB, PDF/DOCX/MD

нет

Zackriya/MCP-Markdown-RAG

markdown, heading chunking, Milvus

нет

proofgeist/obsidian-notes-rag

sqlite-vec + Ollama, graph-aware

нет

patakuti/local-knowledge-rag-mcp

pgvector

нет

Остальное — только локально, нарезка по заголовкам, хранение в SQLite, инкрементальная индексация — это обязательный минимум в этой области, а не отличительная черта. Это в таблице возможностей ниже, а не в основной презентации.

Related MCP server: recall-mcp

Когда это вам не нужно

Честная версия, потому что область продвинулась:

  • Для точных совпадений по символам у вашего агента уже есть grep, а grep быстрее и не требует индекса. Имена функций, коды ошибок, ключи конфигурации: для этого не нужен векторный индекс.

  • Если документов меньше пары десятков, достаточно агентного поиска. Агент читает дерево файлов, ищет grep'ом, открывает то, что выглядит релевантным. Это работает.

  • Anthropic выпустила RAG с векторной БД внутри Claude Code, а затем убрала его (май 2025), потому что агентный поиск показал себя лучше. Cursor, Windsurf, Cline и другие пошли тем же путём. Утверждать обратное было бы нечестно.

Что переживает это — и ради чего всё существует: grep находит то, что вы называете. Когда в документе это называется «окно обновления токена», а вы говорите «срок действия сессии», grep ничего не возвращает, а семантический поиск возвращает документ. А на длинном многослойном корпусе семантический поиск обходится в меньшее число запросов и токенов, чем если бы агент обходил дерево — не «лучшие результаты», а более дешёвые результаты.

Поэтому область применения узкая и конкретная: длинный многослойный корпус решений, спецификаций и ADR в markdown, содержащий устаревшие материалы, где нужно, чтобы агент не воскрешал мёртвое решение.

Предварительные требования

  • Node.js ≥ 22.5 — индекс использует встроенный модуль node:sqlite, поэтому собирать нативные зависимости не нужно. В зависимости от версии Node вы можете увидеть однострочное предупреждение в stderr (ExperimentalWarning: SQLite is an experimental feature); оно безвредно.

  • Ollama с моделью эмбеддингов. Модель требуется и для построения индекса, и при каждом поиске — запрос эмбеддится на лету, поэтому Ollama должна работать всякий раз, когда используется MCP-сервер, а не только при индексации.

# install Ollama from https://ollama.com, then:
ollama pull bge-m3

Установка

Опубликованный пакет не требует клонирования и сборки:

npx -y docs-rag-mcp init      # guided questions -> writes config.json
npx -y docs-rag-mcp index     # builds the index

Если вы планируете использовать хук автоматической переиндексации, установите его глобально:

npm i -g docs-rag-mcp

npx заново резолвит пакет при каждом запуске и скачивает его при первом использовании. Для MCP-сервера это неважно — он запускается один раз за сессию, — но хук рассчитан на завершение за ноль секунд и запускается после каждого изменения файла; глобальная установка полностью устраняет эти накладные расходы. docs-rag scaffold сам определяет глобальную установку и записывает более короткую форму команды.

Предпочитаете редактировать конфиг вручную? Скопируйте config.example.json в config.json и задайте vaultPath. У всего остального разумные значения по умолчанию.

git clone https://github.com/andreaselmi/docs-rag-mcp
cd docs-rag-mcp
yarn install
yarn setup          # -> config.json
yarn index
yarn build          # compiles to dist/

Скрипты yarn сопоставляются один-к-одному с подкомандами (setupinit, serve, index, search, scaffold). При создании проекта из исходников передайте --local: он запишет node /abs/path/dist/server.js в сгенерированные файлы вместо команды npx, которая разрешилась бы в опубликованный пакет, а не в ваше рабочее дерево.

Команды

docs-rag init                 interactive wizard, writes config.json
docs-rag scaffold <dir>       give a project its own scoped instance
docs-rag index                build or update the index
docs-rag search "question"    query the index from the terminal
docs-rag serve                run the MCP server on stdio
docs-rag hook                 Claude Code hook entry point (auto re-index)

Каждая команда принимает --config <path>.

Проверьте поиск из терминала

docs-rag search "how do we handle authentication"

Вы увидите подходящие разделы, каждый с причиной, по которой он был возвращён:

[semantic 0.712]  reference/auth.md › Auth > How the client refreshes the token
[both 0.688]      decisions/2026-01-session-length.md › Session length  [2026-01-14]
[exact match]     reference/errors.md › Error codes > ERR_TOKEN_EXPIRED

Это ровно тот поиск, который будет использовать MCP-клиент, — сначала проверьте его здесь.

Чтобы пропустить папки для одного запроса, передайте --exclude (фрагменты путей через запятую, без учёта регистра):

docs-rag search "how do we handle auth" --exclude archive,drafts

MCP-инструмент предоставляет то же самое в виде опционального массива exclude в search_notes, так что в разговоре можно попросить «найди, но проигнорируй папку archive».

Некоторые папки (archive, plans по умолчанию — см. defaultExclude) пропускаются при каждом запросе, а не только когда вы передаёте --exclude. Чтобы всё же найти в них для одного запроса, передайте --all (CLI) или searchAll: true (параметр инструмента). Тот же флаг снова включает документы с пометкой superseded/archived во frontmatter, которые тоже скрыты из обычного поиска.

Два поисковых трека и метки

Плотные эмбеддинги слабы ровно в том, чем полны спецификации: аббревиатуры, коды ошибок, имена функций, номера версий. Поэтому каждый запрос выполняется по двум трекам, а затем объединяется.

  • Семантический трек ранжирует каждый чанк по косинусному сходству и применяет пороги.

  • Лексический трек — это полнотекстовый поиск (FTS5), ограниченный редкими терминами вашего запроса. «Редкость» измеряется относительно вашего собственного индекса: термин подходит, если он встречается не более чем в max(5, lexicalMaxDocFreq × total chunks) чанках и не более чем в половине из них. Запуск FTS по каждому слову затопил бы результаты совпадениями по частым терминам; фильтр редкости — это то, что обеспечивает точность.

Метка на каждом результате говорит, какой трек его туда поместил:

метка

значение

[semantic 0.712]

найдено по смыслу, косинусный балл 0.712

[both 0.712]

найдено обоими треками — самый сильный сигнал

[exact match]

только лексика. Балл намеренно не показан: косинусное значение — не причина, по которой этот результат здесь, и его вывод предполагал бы обратное

Лексические результаты ограничены (2 слота) и всегда идут после семантических, поэтому совпадение по редкому термину может дополнить ответ, но никогда не подменит его.

Модели эмбеддингов

Подходит любая модель эмбеддингов, доступная в Ollama, — задайте embedModel в конфиге. По умолчанию используется bge-m3, и пороги поставляются настроенными под неё.

Смена embedModel теперь принуждает к полной пересборке. Индекс запоминает, какая модель его построила; открытие с другой моделью отклоняется, а не молча оценивается по несовместимым векторам. Более ранние версии тихо смешали бы их и вернули неверные результаты без какой-либо ошибки.

Некоторым моделям нужен префикс задачи на входе (nomic-embed-text требует search_query: / search_document:). Они находятся в небольшом реестре и применяются за вас. Если вы выберете модель, которой реестр не знает, docs-rag index сообщит об этом — поиск всё равно работает, но никто не проверял соглашение о префиксах или пороги для неё.

Отчёт о калибровке

В конце каждого запуска индексации вы получаете строку вроде:

Calibration: background noise p99 = 0.421 over 500 random pairs -> suggested minScore 0.45 (in use: 0.55, from the model registry).

Он берёт случайные пары чанков из вашего собственного корпуса, которые по определению не связаны, и сообщает, какой балл сходства они всё равно достигают. Это шумовой порог модели: всё, что набирает меньше, неотличимо от двух документов, которые никак не связаны друг с другом.

Используйте его как нижнюю границу, а не как значение для копирования. Если предложенное значение намного выше вашего настроенного minScore, ваш порог пропускает шум. Если намного ниже — вы можете быть строже. Настроенное значение всегда побеждает: отчёт никогда не перезаписывает ваш выбор, он лишь сообщает, что измерил.

Один экземпляр на проект (рекомендуется)

Обычно вам нужна отдельная база знаний на каждый проект. Но вам не нужна копия этого инструмента на каждый проект — установите его один раз, а затем дайте каждому проекту собственный конфиг, зарегистрированный на уровне проекта:

docs-rag scaffold /path/to/some-project     # asks a few questions (or pass flags)

Для этого проекта он записывает:

  • some-project/.rag/config.json — его конфиг (vaultPath — корень проекта; индекс ложится в .rag/index.db, рядом с ним). Повторный запуск scaffold на уже настроенном проекте сохраняет этот файл: настроенные pathBoosts и пороги выживают, и перезаписываются только ключи, которые вы явно передали флагами в этом запуске.

  • some-project/.mcp.json — регистрация MCP на уровне проекта. Существующие серверы в нём сохраняются. Поскольку команда не содержит машинно-зависимых путей, этот файл можно коммитить: любой, кто клонирует репозиторий, получает поиск по его документам без ручной установки.

  • добавляет .rag/index.db* и устаревший шаблон .rag/index.json* в .gitignore проекта.

  • с --hook: some-project/.claude/settings.local.json — хук Claude Code, который переиндексирует в фоне после каждого изменения markdown (см. ниже).

Затем:

docs-rag index --config /path/to/some-project/.rag/config.json

Неинтерактивно, можно автоматизировать скриптами по многим репозиториям:

docs-rag scaffold /path/to/proj --name proj-docs --include "**/docs/**/*.md" \
  --desc "What's in this project's docs" --hook --yes

Как разрешается --config

Каждая команда принимает --config. Конфиг-файл «несёт» в себе собственный индекс (относительный indexPath разрешается рядом с конфиг-файлом), поэтому экземпляры никогда не мешают друг другу. Порядок разрешения:

  1. Абсолютный путь всегда побеждает.

  2. CLAUDE_PROJECT_DIR — переменная, которую Claude Code устанавливает в корень проекта в окружении запускаемых им серверов и хуков.

  3. Подъём от рабочей директории до первого предка, где путь существует. Именно это обеспечивает работу --config .rag/config.json на клиентах, которые не задают собственных переменных окружения.

  4. В противном случае — рабочая директория.

Если --config не указан вовсе, тот же подъём ищет .rag/config.json, так что запуск docs-rag search "…" в любом месте внутри созданного по шаблону проекта просто работает.

Не вписывайте ${CLAUDE_PROJECT_DIR} в аргументы .mcp.json самостоятельно: Claude Code не раскрывает там переменные, поэтому они будут переданы буквально.

Подключение к MCP-клиенту

Claude Code

Проектный уровень — это то, что настраивает docs-rag scaffold. Если же вам нужна база знаний в каждой сессии, регистрируйте её на уровне пользователя:

claude mcp add work-docs -s user -- npx -y docs-rag-mcp serve --config ~/vaults/work.json

Проверьте, что сервер подключён, с помощью claude mcp list, а затем задайте вопрос вроде "search_notes: почему мы выбрали X?".

Codex CLI, Cursor, Zed и другие MCP-клиенты

Сервер — это обычный stdio MCP, поэтому любой клиент, понимающий протокол, может запустить его. В ~/.codex/config.toml (Codex CLI):

[mcp_servers.docs-search]
command = "npx"
args = ["-y", "docs-rag-mcp", "serve", "--config", "/absolute/path/to/.rag/config.json"]

Cursor и Zed используют ту же команду и аргументы в своих настройках MCP.

Абсолютный путь в --config — это нужный вариант здесь, потому что он ни от чего не зависит. Относительный путь тоже работает через описанный выше подъём по каталогам — но этот путь проверен самой реализацией и юнит-тестами, а не проверялся на этих клиентах. Если запустите его на одном из них, будем рады отчёту.

Дайте каждому экземпляру собственные serverName и toolDescription: описание — это то, что модель читает, решая, вызывать ли инструмент вообще, поэтому описывайте что находится в этой базе знаний, а не что делает инструмент.

Поддержание индекса в актуальном состоянии

Индекс — это артефакт сборки: index.db, база данных SQLite в режиме WAL, с сопутствующими файлами -wal и -shm. После редактирования документов перезапустите docs-rag index — он инкрементальный и заново встраивает только файлы, у которых изменился mtime. Запущенный MCP-сервер автоматически подхватывает каждый переиндекс, перезапуск не нужен. Устаревший индекс отвечает устаревшим содержимым — это хуже, чем промах.

Автоматический переиндекс (только Claude Code, по желанию)

Выполните scaffold с --hook, и хук PostToolUse от Claude Code будет перезапускать инкрементальный индексатор в фоне всякий раз, когда Claude пишет или редактирует markdown-файл в этом проекте, — с объединением в максимум один запуск за 30 секунд, при этом ни одна правка не теряется. Правки, сделанные вне Claude Code, по-прежнему требуют ручного запуска.

Хук находится в .claude/settings.local.json проекта (личный файл, не коммитится); удалите запись PostToolUse, чтобы отключить его. Если фоновый запуск не срабатывает — чаще всего из-за того, что Ollama не запущена, — вы получаете одно предупреждение за эпизод в сессии, а не за каждое сохранение, а подробности попадают в .rag/hook.log. Другие MCP-клиенты не запускают хуки Claude Code: там переиндексируйте вручную.

Обновление существующего индекса

Первый docs-rag index после обновления — это однократное полное перевстраивание, а не обычный no-op за долю секунды: в схеме появились таблица идентичности модели и таблица FTS5, а старые векторы перенести нельзя. При включённом хуке он запустится в фоне при первой же правке, так что рассчитывайте, что первый запуск займёт минуты, а не секунду.

Обновление с исходного index.json: он переименовывается в index.json.bak и пересобирается с нуля. Удалите .bak, когда результат вас устроит.

Справочник конфигурации

Поле

По умолчанию

Примечания

vaultPath

— (обязательно)

папка для индексирования; абсолютный или относительный к файлу конфигурации путь

includeGlobs

["**/*.md"]

excludeGlobs

["**/node_modules/**"]

ollamaUrl

http://localhost:11434

embedModel

bge-m3

любая эмбеддинг-модель Ollama; её смена вынуждает пересборку

indexPath

index.db

относительно файла конфигурации; SQLite (режим WAL)

topK

8

количество результатов по умолчанию

serverName

docs-search

имя MCP-сервера, отображаемое в кли

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables managing and searching markdown notes with semantic search, question answering, and note generation, and provides an MCP server for GitHub Copilot integration.
    4
  • A
    license
    A
    quality
    D
    maintenance
    Turns a local folder of notes and documents into a searchable knowledge base for AI assistants via MCP, enabling semantic search, reading, and adding notes entirely on-device.
    4
    9
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to list, search, read, and append to Markdown notes through MCP tool calls, making it easy to interact with a second brain folder.

View all related MCP servers

Related MCP Connectors

  • Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.

  • Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.

  • Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/andreaselmi/docs-rag-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server