Skip to main content
Glama

local-rag-mcp

ci

Сервер MCP только для чтения для семантического поиска по локальному корпусу документов — встраивания на устройстве (Ollama), локальное хранилище Chroma, ничего не покидает хост. Создан для сред, где содержимое корпуса не может уходить в облачный API, и обслуживается одинаково для любого MCP-клиента (Claude Code, Codex, любого, кто говорит на этом протоколе).

Это MCP-обслуживаемый аналог claude-code-session-memory: та же модель встраивания, тот же режим префиксов инструкций, та же методология измерений — один субстрат поиска, два потребителя. В README session-memory приведена полная история оценок (заранее установленные пороги, наборы состязательных запросов, атрибуция регрессий); этот репозиторий применяет ту же дисциплину к серверу, а не к хуку.

Инструменты

Инструмент

Что делает

search_corpus(query, k=4)

Семантический поиск: до k фрагментов с путём источника, путём заголовков, косинусной оценкой, текстом

get_file(path)

Текст индексированного документа (ограничен 50 тыс. символов) — намеренно не универсальный читатель файловой системы

Оба аннотированы как доступные только для чтения. Сбои возвращают структурированные полезные нагрузки {"error": ...} — вышедшая из строя зависимость ухудшает инструмент, но никогда не сессию.

Быстрый старт

git clone https://github.com/wesglockzin/local-rag-mcp
cd local-rag-mcp
python3 -m venv .venv && ./.venv/bin/pip install -r requirements.txt
ollama pull embeddinggemma

# Index the included sample corpus (or point RAG_CORPUS_DIR at your own)
./.venv/bin/python ingest.py

# Register with Claude Code — ABSOLUTE paths on both sides: the MCP client
# launches the server from its own working directory, so relative paths are
# the #1 install failure.
claude mcp add local-rag -- "$PWD/.venv/bin/python" "$PWD/server.py"

Затем спросите Claude Code о том, что знает корпус — «кого вызывают при sev-1?» — и наблюдайте, как он вызывает search_corpus.

Конфигурация — три переменные окружения: RAG_CORPUS_DIR (по умолчанию: ./sample-corpus), RAG_STORE_DIR (по умолчанию: ~/.local-rag-mcp/store), OLLAMA_HOST.

Проектные решения, которые оправдывают себя

  • Сервер только для чтения и никогда не создаёт хранилища. Созданием занимается ингестия. Сервер только для чтения, который тихо инициализирует пустое хранилище, превращает «вы забыли выполнить ингестию» в «поиск ничего не возвращает» — худший сбой, потому что выглядит как ответ.

  • Ингестия с встраиванием-затем-заменой. Старые фрагменты файла удаляются только после того, как каждый новый фрагмент успешно встроен; сбой Ollama в середине файла никогда не оставляет этот файл отсутствующим в индексе.

  • Выведенные из эксплуатации документы предварительно фильтруются, а не пост-фильтруются. Документ с lifecycle: superseded во frontmatter исключается с помощью условия where до векторного поиска, поэтому он никогда не занимает слот результата. Ингестия записывает ключ lifecycle явно в каждый фрагмент — в некоторых версиях хранилища отсутствующий ключ проскальзывает через $ne, поэтому отсутствие не является безопасным значением по умолчанию. (Оригинал этого правила существует потому, что повторная ингестия однажды молча стёрла маркер, и выведенный из эксплуатации документ снова появился в результатах; регрессионный тест теперь это закрепляет.)

  • get_file защищён от симлинков. Читаемы только индексированные пути, и путь, который разрешается в другое место, чем при ингестии, отклоняется — иначе любой, кто может заменить файл корпуса на симлинк, читает за пределами корпуса через сервер. Если файл отсутствует на диске (корпус перемещён, другая машина), вместо него выдаётся индексированный текст фрагментов в порядке фрагментов.

  • Хранилище всегда локально для машины. Это живая база данных на основе SQLite; облачная синхронизация выполняет замену целого файла без транзакционной осведомлённости, и режим отказа — молча повреждённый индекс на машине, которая его не записывала. Синхронизируйте корпус и этот рецепт; каждая машина строит своё хранилище.

  • Каждая ингестия штампует git-коммит корпуса в свой вывод, поэтому сборку индекса можно привязать к точному состоянию корпуса, которое её породило («есть незакоммиченные изменения» само по себе является предупреждающим ярлыком).

  • Асимметричные префиксы встраивания (документированные префиксы инструкций запроса/документа EmbeddingGemma) на обеих сторонах поиска, соответствуя измеренному режиму сопутствующего проекта — там префиксные векторы обгоняют сырой поиск на двузначные проценты, а смешанные префиксные/сырые векторы попадают в некалиброванную полосу.

Соглашения о корпусе

Подходит любой каталог с файлами *.md. Три необязательных ключа frontmatter:

rag: false            # exclude this file from the index entirely
rag_chunk: headings   # heading-split a long document (default: whole-file)
lifecycle: superseded # keep the file, hide it from search

Закоммиченный sample-corpus/ использует все три плюс обычный файл — шесть вымышленных документов платформенной команды, сгенерированных tools/gen_sample_corpus.py (CI проверяет, что закоммиченный корпус соответствует генератору).

Тесты

pip install pytest && python -m pytest -q

Никакого Ollama, никакого хранилища: эмбеддер заглушен, а коллекция — это фикция, записывающая вызовы. Под тестом находятся контракты — проверка аргументов, предварительный фильтр lifecycle, доходящий до хранилища как условие where, гарантия «только чтение, без создания», отказ от симлинков, порядок «встраивание-затем-замена» (включая путь с упавшим эмбеддером), пропуск по допуску mtime и поведение чанкера при слиянии и разделении слишком больших фрагментов.

Известные ограничения

  • Модель доверия: сервер читает любой корпус, на который вы его направляете, и клиенты вставляют извлечённый текст в контекст модели. Индексируйте только доверенный контент — враждебный документ является вектором инъекции в промпт; сервер извлекает, но не санирует. Stdio MCP не имеет уровня аутентификации; он наследует доверие процесса, который его запустил.

  • Оценки сопоставимы только в пределах одного режима встраивания; калиброванный порог «слабого совпадения» зависит от корпуса (в сопутствующем репозитории документирован метод калибровки).

  • Одно хранилище, одна коллекция — маршрутизация по нескольким корпусам выходит за рамки этого проекта.

  • Нет гибридного этапа «ключевые слова + вектор»; запас по перефразированию измерен и документирован в сопутствующем репозитории.

Лицензия

MIT — см. LICENSE.

Автор

Wes Glockzin

-
license - not tested
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 Connectors

  • Securely search and manage workspace context files for AI agents and teams.

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

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

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/wesglockzin/local-rag-mcp'

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