faq-rag
FAQ RAG MCP Server
Небольшое приложение для генерации с дополнением поиском (Retrieval-Augmented Generation, RAG), созданное для технического упражнения Glean Solutions Engineering. Оно индексирует предоставленные FAQ-файлы в Markdown, находит релевантные фрагменты с помощью косинусной близости, формирует обоснованный ответ через LLM и предоставляет результат в виде одного локального MCP-инструмента: ask_faq.
Проект полностью кроссплатформенный: все команды настройки и запуска используют uv и одинаковы на Windows, macOS и Linux. Передаёте это пользователю Windows с Claude Code? Начните с START_HERE_WINDOWS.md. В репозитории есть CLAUDE.md — runbook по настройке, который Claude Code читает автоматически, а также переносимое определение .mcp.json в области проекта для сервера faq-rag.
Объяснение за тридцать секунд
При запуске процесса Python читает FAQ-файлы, разбивает их на фрагменты примерно по 200 символов, создаёт эмбеддинги, нормализует их и кэширует индекс в памяти. На каждый вопрос он создаёт эмбеддинг вопроса, ранжирует фрагменты по косинусной близости, отправляет четыре лучших текстовых фрагмента настроенной LLM и возвращает только готовый ответ и имена файлов-источников.
flowchart LR
A[FAQ Markdown files] --> B[~200-character chunks]
B --> C[Document embeddings cached in RAM]
Q[Question] --> D[Query embedding]
C --> E[Cosine similarity]
D --> E
E --> F[Top 4 text chunks]
F --> G[Grounded LLM generation]
G --> H[answer + sources]
H --> I[MCP client]Эмбеддинги используются только для поиска фрагментов. LLM получает исходный вопрос и извлечённый текст, а не сырые векторы эмбеддингов.
Related MCP server: faq-rag
Точный MCP-контракт
Инструмент: ask_faq
Вход:
{
"question": "How do I reset my password?",
"top_k": 4
}Выход — без дополнительных ключей:
{
"answer": "Use the reset link on the login page [faq_auth.md].",
"sources": ["faq_auth.md", "faq_sso.md"]
}top_k принимает целые числа от 1 до 10 и по умолчанию равен 4.
Почему MCP, а не предложенный HTTP-вариант?
Ядро RAG было бы одинаковым под любой обёрткой. MCP выбран потому, что ИИ-клиент может обнаружить схему инструмента, решить, когда его вызывать, запустить локальный Python-процесс и получить структурированные результаты без собственного HTTP-клиента, порта, URL или health-эндпоинта. MCP улучшает интероперабельность; сам по себе он не улучшает качество поиска.
В этой реализации используется требуемый в задании транспорт stdio. MCP-клиент запускает mcp_server.py как локальный дочерний процесс и обменивается MCP-сообщениями через стандартный ввод и вывод процесса. Сервер не пишет обычные логи в stdout, потому что этот канал зарезервирован для протокольного трафика.
Настройка (любая ОС: Windows, macOS, Linux)
Требования:
Git
uv— он автоматически загружает совместимую версию Python, поэтому отдельная установка Python не нужна. Windows:winget install -e --id astral-sh.uv; macOS:brew install uv.Ключ OpenAI API с доступными кредитами
MCP-клиент, например Claude Code или Cursor
Команды одинаковы в PowerShell, zsh и bash:
git clone https://github.com/cq2wgwtzb5-lgtm/glean-faq-rag-mcp.git
cd glean-faq-rag-mcp
uv syncСоздайте .env.local, скопировав .env.example, затем добавьте в него ключ API в своём редакторе:
OPENAI_API_KEY=your_key_here.env.local игнорируется Git. Никогда не коммитьте и не передавайте его.
Запустите детерминированные тесты (без вызовов API):
uv run pytest -qЗапустите прямой сквозной smoke-тест перед подключением MCP:
uv run rag_core.pyClaude Code автоматически обнаруживает включённый в репозиторий .mcp.json при запуске сессии в этой папке. Следуйте инструкциям docs/WINDOWS_MCP_SETUP.md, чтобы одобрить, проверить и вызвать его (шаги применимы к любой ОС). Пользователи Windows могут также запустить setup_windows.ps1, который оборачивает те же команды uv.
Использование из любого чата на машине
.mcp.json в области проекта загружается только в сессиях, запущенных внутри этой папки. Чтобы сделать ask_faq доступным в каждой сессии Claude Code на машине, зарегистрируйте сервер один раз в области пользователя с абсолютным путём к клону (та же команда на любой ОС):
claude mcp add --scope user faq-rag -- uv run --directory "<absolute path to this repo>" mcp_server.pyСессии внутри репозитория продолжают использовать запись в области проекта; все остальные сессии используют запись в области пользователя. Удалите её командой claude mcp remove --scope user faq-rag.
Оценка
Модульные тесты используют детерминированные фейковые эмбеддинги и не вызывают модели:
uv run pytest -qЖивой оценщик прогоняет пять показательных вопросов через реальные API моделей и проверяет ожидаемые источники, обязательные факты и поведение отказа от ответа:
uv run evaluate.py --output eval-results.jsoneval-results.json намеренно игнорируется, потому что вывод модели и конфигурация аккаунта могут различаться. Захватите отчёт или покажите экран во время собеседования.
Важные проектные решения
Индекс NumPy в памяти
Предоставленный корпус создаёт лишь несколько фрагментов. Векторная база данных добавила бы сложность развёртывания и ревью без улучшения результата. Нормализованные векторы NumPy превращают косинусную близость в простое произведение матрицы на вектор.
Разбиение с учётом границ
Целевой размер остаётся примерно 200 символов, как требуется. Реализация предпочитает границы абзацев, строк, предложений и слов, чтобы текст не разрезался в произвольном месте только ради точного числа.
Один проход эмбеддингов при запуске
Эмбеддинги документов создаются один раз при запуске процесса и кэшируются в оперативной памяти. Каждый вопрос получает новый эмбеддинг запроса. Кэш — это общие данные корпуса, а не память разговора или пользовательской сессии. Когда процесс завершается, кэш исчезает и пересоздаётся при следующем запуске.
Обоснованная генерация и цитирование
Промпт генерации ограничивает модель извлечённым контекстом из FAQ, требует точных цитат с именами файлов и предписывает сообщать, когда FAQ не отвечают на вопрос. Список sources в ответе сохраняет порядок выдачи и содержит только имена файлов из извлечённых фрагментов.
Явное поведение при ошибках
Приложение немедленно завершается с ошибкой, если отсутствует OPENAI_API_KEY, отклоняет пустые вопросы и некорректные значения top_k, использует 30-секундный тайм-аут модели и допускает две повторы SDK. Ошибки остаются ошибками MCP, а не выдуманными ответами из FAQ.
Известные ограничения и развитие в production
В этом упражнении намеренно опущены постоянный индекс, инкрементальная загрузка, контроль доступа, гибридный лексический поиск, реранжирование, сигналы свежести и авторитетности, аудит-логи и персонализация для отдельных пользователей.
В корпоративной системе разрешения должны применяться до поиска, чтобы неавторизованный текст никогда не попадал в контекст модели. Качество поиска также должно использовать лексические, семантические, сигналы свежести, авторитетности и графовые сигналы, а не только косинусную близость. Это ключевые производственные задачи, но их реализация для трёх локальных файлов нарушила бы требование упражнения о лёгком решении.
Структура репозитория
rag_core.py— загрузка, разбиение, эмбеддинги, поиск и генерацияmcp_server.py— один MCP-инструментask_faqповерх stdiofaqs/— предоставленный корпус FAQtests/— детерминированные модульные тесты и тесты конфигурацииevals/cases.json— пять живых оценочных кейсовevaluate.py— запуск живой оценкиpyproject.toml/uv.lock— закреплённое кроссплатформенное окружение (uv sync)setup_windows.ps1— удобная обёртка для Windows вокруг тех же шаговuvCLAUDE.md— автоматическая настройка и обучающие инструкции для Claude Code.mcp.json— переносимая конфигурация MCP для Claude Code в области проектаSTART_HERE_WINDOWS.md— передача пользователю Windows одним промптомdocs/WINDOWS_MCP_SETUP.md— шаги подключения к Claude Codedocs/TALK_TRACK.md— презентация для собеседования и ожидаемые вопросыdocs/REQUIREMENTS_TRACEABILITY.md— карта соответствия задания и кодаdocs/VALIDATION.md— пройденные проверки и оставшаяся граница живых тестов
Безопасность
Не коммитьте ключи API. Проверяйте MCP-серверы перед их включением; локальный stdio-сервер работает с правами пользователя, запустившего клиент. Этот сервер читает только настроенную директорию FAQ и вызывает настроенные модели OpenAI.
Подготовка к собеседованию
Используйте docs/TALK_TRACK.md. В нём объясняется архитектура, причины каждого выбора, чем MCP отличается от HTTP и как это небольшое упражнение соотносится с задачей корпоративного поиска и обоснованных ответов в Glean.
This server cannot be deployed
Maintenance
Related MCP Connectors
Query any docs site via MCP. Submit a URL, ask questions, get cited answers.
Ask any GitHub repository a question. Get source-backed answers.
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Docs Q&A: search 169 data and AI guides, fetch any page as markdown. Read-only, keyless.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables semantic search and question-answering over FAQ documents using RAG (Retrieval-Augmented Generation) with OpenAI embeddings and in-memory vector similarity.-
- FlicenseNot gradedqualityDmaintenanceEnables answering natural-language questions from FAQ documents using vector search and LLM generation via an MCP tool.-
- FlicenseNot gradedqualityCmaintenanceEnables MCP hosts like Cursor or Claude to query an enterprise knowledge base via stdio, providing RAG-based answers with cited sources.-
- FlicenseNot gradedqualityAmaintenanceEnables MCP clients to query a compiled Markdown knowledge base through a single ask tool, returning cited answers grounded in wiki articles over stdio or streamable HTTP.-