MCP server for Obsidian — semantic knowledge graph with auto-classification, DAG hierarchy, and cross-domain bridge detection
Project description
NOUZ — Семантический движок знаний для Obsidian
Структура возникает из содержания.
Что такое NOUZ
MCP-сервер для Obsidian, который даёт ИИ-агенту инструменты для осмысленной работы с базой знаний. NOUZ создаёт в базе семантическое многомерное пространство, в котором агент видит структуру, понимает принадлежность каждой заметки к доменам и находит нетривиальные связи между идеями.
В основе — векторные эмбеддинги, косинусное сходство и коррекция анизотропии трансформеров. Всё это работает локально.
Научные основы
- Mean subtraction — удаление анизотропии эмбеддингов (Su et al., 2021; Ethayarajh, 2019)
- Двунаправленная причинность — sign сверху вниз, core_mix снизу вверх; формализация у Ellis, 2024
- core_drift — сигнал рассогласования, аналог ошибки предсказания в предиктивном кодировании (Friston, 2010)
- Аналогические мосты — структурный изоморфизм, вдохновлён теорией структурного отображения (Gentner, 1983)
Подробное изложение: Рекурсивная самоорганизация как универсальный принцип — междисциплинарная модель, из которой вытекают архитектурные решения NOUZ.
Быстрый старт
pip install nouz-mcp
OBSIDIAN_ROOT=/path/to/vault nouz-mcp
Без config.yaml сервер запускается в режиме LUCA — граф без семантики, работает сразу.
Или из исходников:
git clone https://github.com/KVANTRA-dev/NOUZ-MCP
cd NOUZ-MCP
pip install -r requirements.txt
OBSIDIAN_ROOT=./vault python server.py
Подключение к Claude Desktop, Cursor, Opencode или любому MCP-клиенту:
{
"mcpServers": {
"nouz": {
"command": "nouz-mcp",
"env": {
"OBSIDIAN_ROOT": "/path/to/vault",
"MODE": "prizma",
"EMBED_API_URL": "http://127.0.0.1:1234/v1"
}
}
}
}
Как это работает
Ядра и призма
Сначала вы описываете домены своей базы — минимум два, обычно три-четыре. Опишите что это за область, чем она занимается, чем отличается от других. Сервер превращает эти тексты в векторы-эталоны (calibrate_cores) и сохраняет их в SQLite.
Дальше каждая заметка проецируется на эти векторные оси. Агент видит вашу базу через призму ядер, потому что смысловое пространство структурировано по понятной системе.
Примеры ядер: Физика / Технология / Гуманитарные науки. Или: Клиентский опыт / Архитектура / Бизнес-модель. Область применения не ограничена.
Типы сущностей
Каждая заметка в графе — сущность. Тип определяет её роль в иерархии:
Ядро (L1) — корень домена. Создаётся вручную, знак задаётся вручную. Якорь, от которого растёт ветка.
Паттерн (L2) — область знаний внутри ядра. Знак задаётся вручную как намерение. Может получить второй знак, если содержание тянет к другому домену.
Модуль (L3) — функциональная группировка. Наследует знак от родительского паттерна по иерархической связи.
Квант (L4) — атомарная единица знаний. Одна идея, один концепт — но развитая и самодостаточная. Знак рассчитывается автоматически по содержимому. Если квант про нейросети живёт в модуле про системное мышление, его знак отразит реальное содержание, а не положение в дереве. Это не ошибка системы — мысль действительно может жить на стыке доменов.
Артефакт (L5) — след деятельности. Лог, черновик, референс, мысль, входящие данные. Прикрепляется к любому уровню через иерархическую, семантическую или временную связь.
Знак: намерение vs реальность
Знак (sign) — символ домена, к которому принадлежит заметка. Один или составной: TS, SH.
sign (Намерение): L1 → L2 → L3 сверху вниз, задаётся человеком
core_mix (Реальность): L4 → L3 → L2 снизу вверх, считается автоматически
core_mix — агрегированный состав ядер по всем дочерним заметкам снизу вверх. Когда sign и core_mix расходятся, возникает core_drift. Это не ошибка — сигнал: «Этот модуль заявлен как T, но 45% контента — S. Стоит пересмотреть структуру?»
Механизм аналогичен предиктивному кодированию: верхние уровни иерархии задают ожидания, нижние возвращают сигнал рассогласования.
Три режима работы
| Режим | Граф | Семантика | Иерархия |
|---|---|---|---|
| LUCA | ✅ | ❌ | Свободная, без проверок |
| PRIZMA | ✅ | ✅ Ядра, мосты, drift | Свободная, без проверок |
| SLOI | ✅ | ✅ | Строгая 5-уровневая |
LUCA — чистый граф. Только структура, которую вы задаёте вручную. Никаких эмбеддингов, никаких эталонов. Подходит для начала: выстроить иерархию, провести связи, понять форму базы. Работает без config.yaml.
PRIZMA — граф плюс семантика. Сервер начинает «видеть»: классифицирует заметки по ядрам, находит мосты между доменами, отслеживает дрейф. Уровни используются для удобства, строгое соблюдение необязательно. Рекомендуемый режим для большинства задач.
SLOI — всё то же, плюс строгая иерархия. Если L4-заметка помещена под L2-родителем — это ошибка, и сервер скажет об этом. Для тех, кому важна чистота структуры.
Связи
Связи в NOUZ — осознанный выбор: зачем одна заметка ссылается на другую.
| Тип | Кто создаёт | Смысл |
|---|---|---|
hierarchy |
Только человек | Структурное решение. По этой связи передаётся sign. |
temporary |
Человек или ИИ | Артефакт ещё не прирос к графу. Позже станет hierarchy — или уйдёт. |
semantic |
ИИ предлагает, человек решает | Две заметки из разных доменов говорят об одном и том же. |
tag |
ИИ предлагает, человек решает | Заметки делят скрытый концепт, хотя полные тексты разные. |
analogy |
ИИ предлагает, человек решает | Заметки занимают аналогичную позицию в структуре графа, несмотря на разное содержание. |
Семантические мосты
Две заметки из разных ядер, чьи тексты семантически близки. Заметка про термодинамическую энтропию и заметка про сжатие данных — обе про эффективность кодирования информации, хотя домены разные. Агент находит это через косинусную близость полных эмбеддингов.
cosine(embed(A), embed(B)) ≥ 0.55 → семантический мост
Мост предлагается только между заметками из разных ядер. Если знак заметки определён уверенно (sign_source = auto), мосты к своему ядру не предлагаются — домен закрыт. Если знак слабый (weak_auto), мосты предлагаются в обе стороны: домен неопределён, и связи помогают разобраться.
Теговые мосты
Заметки, чьи отдельные теги близки в пространстве эмбеддингов, хотя полные тексты разные. Тег «энтропия» близок к тегу «хаос» — но сами заметки могут быть о разном. Теговый мост выявляет скрытый концепт, который полный текст пропускает.
cosine(embed(tag_A), embed(tag_B)) ≥ 0.72 → теговый мост
Порог выше (0.72 vs 0.55), потому что короткие слова шумнее длинных текстов — baseline косинуса у них выше.
Аналогические мосты
Заметки из разных ядер, которые занимают аналогичную позицию в графе. Разное содержание, похожая структурная роль.
Сходство считается по четырём компонентам с весами:
core_mix angle × 0.35
level match × 0.25
degree similarity × 0.20
tag overlap × 0.20
─────────────────────────
structural_sim ≥ 0.55 → аналогический мост
Вдохновлено теорией структурного отображения (Gentner, 1983): аналогии — это отображения между реляционными структурами, а не поверхностное сходство.
Зачем три типа?
Каждый тип ловит свой вид связи. Семантический — «заметки об одном и том же». Теговый — «делят скрытый концепт». Аналогический — «играют одну и ту же роль в структуре». Если два типа подтверждают связь — она надёжная. Один тип — слабый сигнал, но заслуживающий внимания.
Уверенность знака
Не все классификации одинаково надёжны. Сервер различает:
max_cosine ≥ confident_cosine → sign_source = "auto" (уверенный)
max_cosine < confident_cosine → sign_source = "weak_auto" (относительная догадка)
auto — домен закрыт: мосты к своему ядру не предлагаются. Сервер уверен в принадлежности заметки.
weak_auto — домен открыт: мосты предлагаются в обе стороны. Заметка ближе к одному ядру, но не уверенно — возможно, короткая, на нестандартном языке или действительно на стыке.
Порог по умолчанию — 0.6. Для большинства моделей (e5, BGE, multilingual) это работает. Для nomic-embed (baseline 0.74–0.83) — поставьте 0.75. Для тесных доменов с высоким пересечением — можно опустить до 0.5.
Анизотропия и mean subtraction
Трансформерные эмбеддинги имеют известную проблему: все векторы сжаты в узкий конус, и косинус между любыми двумя текстами завышен вне зависимости от их смысловой близости. Это свойство архитектуры, описанное в работах Gao et al. (2019) и Ethayarajh (2019).
NOUZ применяет mean subtraction (Su et al., 2021): вычитает средний вектор эталонов из каждого вектора перед сравнением. Это убирает общий компонент — «конус» — не разрушая семантику. Результат виден в отчёте калибровки как pairwise_cosine_centered.
Формула сущности
format_entity_compact показывает позицию заметки в графе одной строкой:
(дети)[уровень·знак]{родители}
Каждая группа показывает знаки сущностей с количеством. Скобки детей и родителей опускаются, если пусты. Пример:
(3A2B)[4C]{D}
Читается: у заметки 3 дочерних с знаком A и 2 с знаком B, сама она на уровне 4 с знаком C, её родитель — знак D. По этой строке агент видит контекст заметки без чтения всего графа.
Инструменты и зачем они нужны
| Инструмент | Зачем нужен агенту |
|---|---|
suggest_metadata |
Главный инструмент. Говорит: какой знак, какой уровень, какие мосты, есть ли drift. Агент вызывает его перед записью — чтобы не гадать. |
write_file |
Создать или обновить заметку с правильным YAML. Проверяет циклы в DAG перед записью. |
read_file |
Прочитать заметку и её метаданные. Переиндексирует в БД — при следующем suggest_metadata данные актуальны. |
calibrate_cores |
Векторизовать эталонные тексты ядер. Запускается один раз после настройки конфигурации или при изменении эталонов. |
recalc_signs |
Пересчитать автоматические знаки всех заметок по эмбеддингам. Запускается после калибровки. |
recalc_core_mix |
Пересчитать агрегацию снизу вверх: L4 → L3 → L2. Запускается после recalc_signs. |
suggest_parents |
Найти родителей по семантической близости. Для заметок без родителей. |
list_files |
Список файлов с фильтрами по уровню, знаку, подпапке. |
get_children / get_parents |
Траверс графа вниз и вверх. |
format_entity_compact |
Формула сущности — быстрый обзор позиции в графе. |
index_all |
Полная переиндексация хранилища. После крупных изменений. |
embed |
Получить вектор для любого текста. |
Типичный сценарий работы агента
-
Новая заметка. Агент пишет текст → вызывает
suggest_metadata→ получает sign, level, мосты, drift-предупреждения → записывает с правильным YAML черезwrite_file. -
Сирота нашла дом. Агент видит заметку без родителей →
suggest_parents→ предлагает связи → человек подтверждает. -
Drift обнаружен.
suggest_metadataвозвращаетcore_driftwarning → «Модуль заявлен как T, но 45% контента — S. Пересмотреть структуру?» -
Мост между мирами. Агент видит, что квант про энтропию и квант про сжатие данных связаны семантическим мостом → предлагает связь → человек решает.
Конфигурация
Создайте config.yaml рядом с сервером:
mode: prizma
# Необязательно: имя корневой заметки (исключается из семантических операций)
meta_root: "Моя база знаний"
# Описания доменов — пишите ЧТО это, а не перечисляйте ключевые слова
etalons:
- sign: T
name: Технология
text: "программирование архитектура инфраструктура машинное обучение нейросети
алгоритмы фреймворки базы данных облачные вычисления"
- sign: S
name: Наука
text: "физика химия биология математика формальная логика теоремы космология
квантовая механика научная методология"
- sign: H
name: Гуманитаристика
text: "философия психология социология история литература искусство этика
когнитивные науки эпистемология лингвистика"
thresholds:
sign_spread: 0.05 # минимальный разброс для классификации
confident_cosine: 0.6 # порог уверенности знака
pattern_second_sign_threshold: 30.0 # % порог для составных знаков
semantic_bridge_threshold: 0.55 # семантические мосты
structural_bridge_threshold: 0.55 # аналогические мосты
Качество эталонов важнее количества. После записи запустите calibrate_cores и проверьте pairwise_cosine_centered. Значения выше 0.4 между разными ядрами означают, что эталоны семантически перекрываются — перепишите с более доменно-специфичным языком и меньшим количеством общих слов.
| Переменная | По умолчанию | Описание |
|---|---|---|
OBSIDIAN_ROOT |
./obsidian |
Путь к хранилищу |
MODE |
luca |
luca, prizma или sloi |
EMBED_PROVIDER |
openai |
openai, lmstudio, ollama, gigachat |
EMBED_API_URL |
http://127.0.0.1:1234/v1 |
Эндпоинт для эмбеддингов |
EMBED_API_KEY |
(пусто) | API-ключ, если нужен |
EMBED_MODEL |
(пусто) | Имя модели |
Мета-корень
Узел уровня 0 (meta_root в конфиге) — верхний якорь иерархии. Индексируется для видимости в графе, но исключён из всех семантических операций: эмбеддинги, sign, core_mix. Без него заметки первого уровня болтаются в пустоте.
Приватность
| Компонент | Локально? |
|---|---|
| Эмбеддинги (LM Studio / Ollama) | ✅ Да |
| Ваши заметки (сырые файлы) | ✅ Да |
| Сервер NOUZ | ✅ Да |
| Контекст AI-агента (Claude, ChatGPT) | ❌ Уходит в облако |
NOUZ работает полностью локально. Но если вы подключаете облачного агента — контекст, который он видит, уходит к провайдеру. Используйте локальных агентов, если приватность критична.
Разработка
git clone https://github.com/KVANTRA-dev/NOUZ-MCP
cd NOUZ-MCP
pip install -e .
python -m pytest test_server.py
Ссылки
- 🌐 Сайт
- 📦 PyPI
- 🗂️ Glama Registry
- 💬 Telegram
- 🐙 GitHub
- 📄 Статья "Рекурсивная организация как универсальный принцип"
MIT License © 2026 KVANTRA
Косинусы считаются. Синтаксис меняется. Семантика остаётся.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nouz_mcp-2.2.3.tar.gz.
File metadata
- Download URL: nouz_mcp-2.2.3.tar.gz
- Upload date:
- Size: 40.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe645f9b8ef1ba61c8f6607f70c95ad461faad07fc4664b1b1590edbf967b996
|
|
| MD5 |
6ae1ce49e25c2040dad30e20fb723c81
|
|
| BLAKE2b-256 |
8d0392df7db6f35c6581e0200eb4f1a8b25342ee7041f71fffbc13ccc8015a7f
|
File details
Details for the file nouz_mcp-2.2.3-py3-none-any.whl.
File metadata
- Download URL: nouz_mcp-2.2.3-py3-none-any.whl
- Upload date:
- Size: 31.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a7db08c9e19d7996dba98a41af46973fd9bf58a286ea245a99c4a13cb68c137
|
|
| MD5 |
9d3f89beabfdff6785490253d302bdf9
|
|
| BLAKE2b-256 |
4b47c6ec96cf9649e0a6aad284e98f1f877b777fd27aba57e8d6d97204aaa836
|