local-corporate-kb

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.

Category
Visit Server

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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured