local-corporate-kb
Local RAG knowledge base for Qwen Code, enabling document indexing and semantic search via MCP tools. Supports metadata filtering and document retrieval without external dependencies.
README
Локальная корпоративная база знаний для Qwen Code
Это локальный MVP корпоративного RAG: документы индексируются Python-процессом, embeddings сохраняются в проверяемый файловый кэш, а при поиске целиком находятся в RAM. Qwen Code остаётся единственной генеративной моделью и получает найденные фрагменты через read-only MCP tools. MCP-сервер не формулирует финальные ответы, не исполняет shell-команды и не изменяет документы.
Проект рассчитан на Python 3.12, uv и официальный MCP Python SDK v2. Зафиксированная версия SDK
указана в uv.lock; сторонний пакет fastmcp не используется.
Архитектура
Confluence export
↓
knowledge/*.md, *.html, *.txt
↓
loader + normalizer + structural chunker
↓
local feature hashing (по умолчанию) или локальная embedding-модель
↓
NumPy matrix in RAM
↓
MCP stdio
↓
Qwen Code CLI
DocumentLoader безопасно обходит только KB_KNOWLEDGE_DIR, нормализует Markdown/TXT и переводит
экспортированный HTML в Markdown-подобный текст. StructuralChunker сохраняет путь заголовков,
списки, таблицы и code fences. KnowledgeService координирует кэш и работает только через
интерфейс KnowledgeStore; MCP-слой не знает о NumPy.
В RAM находятся документы, чанки, отображение chunk_id -> index и нормализованная NumPy-матрица
[chunk_count, embedding_dimension]. Cosine similarity считается как matrix @ query_vector.
На диске в .cache/kb/ находятся только:
manifest.json— версии схемы, идентичность модели, chunking config и knowledge hash;documents.json— нормализованные документы и metadata;chunks.json— чанки без отдельной копии embedding;embeddings.npy— матрица без pickle.
Это не Vector DB: нет отдельного сервиса, индекса ANN, SQL или сетевого API. Диск используется для ускорения старта, но поиск выполняется полным cosine scan по NumPy-матрице в памяти.
Первый запуск
Убедитесь, что доступен Python 3.12. Глобальный uv не нужен: setup-скрипт создаст .venv,
установит uv непосредственно в него и синхронизирует базовые зависимости из lock-файла.
Hugging Face, PyTorch и sentence-transformers в базовую установку не входят:
./scripts/setup-venv.sh
source ./scripts/activate-venv.sh
После активации command -v uv должен указывать на .venv/bin/uv. Скрипт удаляет действующие
shell alias/function с именем uv, ставит .venv/bin первым в PATH и экспортирует UV_BIN:
command -v python
command -v uv
echo "$UV_BIN"
Полностью локальный режим по умолчанию использует hash provider и не требует модели или сети:
./scripts/dev.sh index-hash
./scripts/dev.sh search-hash
Hash provider строит локальные lexical vectors из слов и символьных триграмм. Он пригоден для полностью автономного поиска по совпадающей терминологии, но не понимает смысл и синонимы так же хорошо, как semantic embedding model.
Для качественного semantic search сначала положите заранее полученные и одобренные model files в локальный каталог. Этот проект не скачивает их. Например:
models/Qwen3-Embedding-0.6B/
После этого активируйте окружение, укажите только локальный путь и постройте индекс:
./scripts/dev.sh install-semantic
source ./scripts/activate-venv.sh
export KB_EMBEDDING_PROVIDER=sentence_transformers
export KB_EMBEDDING_MODEL="$KB_PROJECT_ROOT/models/Qwen3-Embedding-0.6B"
export KB_EMBEDDING_LOCAL_FILES_ONLY=true
./scripts/dev.sh index-semantic
./scripts/dev.sh search "Какой сервис владеет дневными лимитами?"
local_files_only=true, HF_HUB_OFFLINE=1 и TRANSFORMERS_OFFLINE=1 запрещают обращения к
Hugging Face. Если model files отсутствуют, индексирование завершится понятной ошибкой без попытки
скачивания. По умолчанию выбирается CUDA, затем MPS, затем CPU.
scripts/start-mcp.sh по умолчанию запускает MCP с KB_EMBEDDING_PROVIDER=hash, поэтому обычное
подключение Qwen полностью offline. Для локальной semantic-модели явно передайте provider и путь в
environment Qwen-конфигурации. Все runtime wrappers используют uv run --offline --no-sync:
после установки они не обращаются к package registry и не меняют окружение.
CLI
uv run --offline --no-sync kb index
uv run --offline --no-sync kb index --force
uv run --offline --no-sync kb search "Как рассчитывается дневной лимит?" --top-k 5
uv run --offline --no-sync kb search "Как рассчитывается дневной лимит?" --service limits-service
uv run --offline --no-sync kb search "Как рассчитывается дневной лимит?" --document-type business_rule
uv run --offline --no-sync kb documents
uv run --offline --no-sync kb stats
uv run --offline --no-sync kb eval
uv run --offline --no-sync kb eval --top-k 5
У search, documents, stats и eval есть --json. В этом режиме stdout содержит только JSON,
а логи остаются в stderr.
Если кэша нет или он несовместим, обычный поиск при KB_AUTO_INDEX=false завершится практичным
сообщением Run: ./scripts/dev.sh index. Это предотвращает неожиданную сетевую активность во время
MCP discovery.
Подключение к Qwen Code
Скопируйте examples/qwen-settings.example.json в .qwen/settings.json проекта и замените все
/ABSOLUTE/PATH/... реальными абсолютными путями. Не рассчитывайте на раскрытие ${PROJECT_ROOT}
в JSON. В command указан абсолютный путь к .venv/bin/python, а в args — запуск модуля
corporate_kb.mcp.server. Поэтому Qwen не зависит от глобальных python, uv, PATH, shell
activation или wrapper-скрипта.
Минимальная форма server entry:
{
"command": "/absolute/path/to/repository/.venv/bin/python",
"args": ["-m", "corporate_kb.mcp.server"],
"cwd": "/absolute/path/to/repository",
"env": {
"PYTHONPATH": "/absolute/path/to/repository/src"
}
}
Альтернатива через CLI (выполняйте из корня этого репозитория, подставив абсолютные пути):
qwen mcp add \
--scope project \
--timeout 120000 \
--include-tools kb_search,kb_get_document,kb_list_documents,kb_stats \
-e KB_KNOWLEDGE_DIR=/absolute/path/to/repository/knowledge \
-e KB_CACHE_DIR=/absolute/path/to/repository/.cache/kb \
-e KB_EMBEDDING_PROVIDER=hash \
-e KB_EMBEDDING_LOCAL_FILES_ONLY=true \
-e HF_HUB_OFFLINE=1 \
-e TRANSFORMERS_OFFLINE=1 \
-e PYTHONUNBUFFERED=1 \
-e PYTHONNOUSERSITE=1 \
-e PYTHONPATH=/absolute/path/to/repository/src \
-e KB_AUTO_INDEX=false \
local-corporate-kb \
/absolute/path/to/repository/.venv/bin/python \
-m corporate_kb.mcp.server
stdio — транспорт по умолчанию, поэтому --transport http здесь не нужен. Синтаксис команды
сверен с официальной документацией Qwen Code,
но в среде разработки этого репозитория qwen не был установлен, и команда локально не выполнялась.
JSON-конфигурация также задаёт cwd, trust: false и allowlist из четырёх tools.
Проверка подключения:
qwen
/mcp
Тестовый запрос:
Используй corporate knowledge MCP.
Найди, какой сервис владеет дневными лимитами,
объясни правило и обязательно укажи использованные источники.
Сервер предоставляет только:
kb_search— поиск сtop_k,min_scoreи metadata filters;kb_get_document— полный нормализованный документ поdocument_id;kb_list_documents— metadata документов без embeddings;kb_stats— состояние индекса и абсолютные пути.
Ручной запуск stdio server:
KB_LOG_LEVEL=DEBUG ./.venv/bin/python -m corporate_kb.mcp.server
stdout зарезервирован для MCP-протокола; все application logs направляются в stderr.
Добавление Confluence-страницы
Экспортируйте страницу в HTML либо сохраните её как Markdown и положите внутрь knowledge/.
Поддерживаются .md, .markdown, .html, .htm, .txt. Скрытые каталоги, .git, .cache,
__pycache__, node_modules, бинарные и неподдерживаемые файлы игнорируются. После изменения
перестройте индекс; при обычном запуске несовпадение knowledge_hash также инвалидирует кэш.
Пример front matter:
---
document_type: service
service: limits-service
domain: payments
status: current
authority: confluence
authority_priority: 80
owner: limits-team
source_id: "confluence-12345"
source_url: "https://confluence.example.com/pages/12345"
last_reviewed: "2026-07-20"
custom_field: "неизвестные поля тоже сохраняются"
---
# Limits Service
Без front matter заголовок берётся из первого H1 или имени файла, source_id — из относительного
пути, status=current, authority=local_file, authority_priority=50.
Кэш и конфигурация
Пересобрать кэш:
./scripts/dev.sh index
Полностью удалить его можно командой rm -rf .cache/kb, после чего снова выполнить kb index.
Запись каждого файла атомарна, а manifest.json заменяется последним. Повреждение JSON/NumPy,
несовпадение схемы, модели, dimension, query instruction, chunking config или knowledge hash приводит
к понятной invalidation, а не к неясной NumPy-ошибке.
Все параметры перечислены в .env.example. Основные:
KB_EMBEDDING_PROVIDER=sentence_transformers|hash;KB_EMBEDDING_MODEL=./models/Qwen3-Embedding-0.6B— локальный каталог model files;KB_EMBEDDING_LOCAL_FILES_ONLY=true— fail-closed запрет сетевой загрузки модели;KB_EMBEDDING_DEVICE=auto|cpu|mps|cuda;KB_EMBEDDING_DIMENSION=1024;KB_CHUNK_SIZE_TOKENS=700,KB_CHUNK_HARD_MAX_TOKENS=900,KB_CHUNK_OVERLAP_TOKENS=80;KB_AUTO_INDEX=false.
Относительные пути разрешаются относительно текущего project working directory; kb stats
показывает итоговые абсолютные пути.
Проверки
./scripts/dev.sh lint
./scripts/dev.sh typecheck
./scripts/dev.sh test
./scripts/dev.sh check
Обычный shell-скрипт scripts/dev.sh также объединяет повседневные команды:
./scripts/dev.sh install
./scripts/dev.sh install-semantic
./scripts/dev.sh test
./scripts/dev.sh lint
./scripts/dev.sh typecheck
./scripts/dev.sh index-hash
./scripts/dev.sh search-hash
./scripts/dev.sh index
./scripts/dev.sh search
./scripts/dev.sh index-semantic
./scripts/dev.sh eval
./scripts/dev.sh serve
Тесты всегда инжектируют hash provider и не требуют интернета, Hugging Face, GPU, Qwen Code, Docker
или внешней БД. MCP integration test использует официальный v2 Client напрямую с объектом
MCPServer и in-memory transport — сетевой порт не поднимается.
Ограничения MVP и развитие
- Полный brute-force cosine scan подходит для небольшой локальной базы, но не для миллионов чанков.
- Любое изменение документа полностью перестраивает индекс; per-document incremental rebuild нет.
- Нет Confluence REST API, OAuth, фоновой синхронизации и HTML-адаптеров под каждый вариант экспорта.
- Нет reranker, hybrid/BM25 retrieval и отдельной оценки authority при ранжировании.
- Точный token counter реальной модели не используется для предварительного chunking: интерфейс
TokenCounterотделён, поэтому его можно подключить без связи chunker с SentenceTransformer. - MCP работает только через локальный stdio subprocess.
Для перехода на настоящую Vector DB нужно реализовать PostgresKnowledgeStore или
QdrantKnowledgeStore с тем же контрактом KnowledgeStore, выбрать реализацию при сборке
KnowledgeService и сохранить API сервиса/MCP без изменений. Следующим этапом стоит добавить
инкрементальный cache manifest, batch upsert, hybrid retrieval и production evaluation corpus.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.