Metadata-Version: 2.4
Name: nouz-mcp
Version: 2.2.3
Summary: MCP server for Obsidian — semantic knowledge graph with auto-classification, DAG hierarchy, and cross-domain bridge detection
Author-email: KVANTRA-dev <your-email@example.com>
License: MIT
Project-URL: Homepage, https://kvantra.tech
Project-URL: Repository, https://github.com/KVANTRA-dev/NOUZ-MCP
Project-URL: Documentation, https://github.com/KVANTRA-dev/NOUZ-MCP#readme
Project-URL: Bug Tracker, https://github.com/KVANTRA-dev/NOUZ-MCP/issues
Keywords: mcp,obsidian,knowledge-graph,semantic-classification,rag,llm,notes,pkm,embeddings,dag
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Text Processing :: Markup :: Markdown
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp>=1.0.0
Requires-Dist: aiofiles>=23.0.0
Requires-Dist: frontmatter>=3.0.0
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: aiosqlite>=0.19.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Dynamic: license-file

# NOUZ — Семантический движок знаний для Obsidian

> Структура возникает из содержания.

[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://python.org)
[![MCP](https://img.shields.io/badge/protocol-MCP_stdio-lightgrey.svg)](https://modelcontextprotocol.io)
[![PyPI](https://img.shields.io/badge/pypi-nouz--mcp-orange.svg)](https://pypi.org/project/nouz-mcp/)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.19595850.svg)](https://doi.org/10.5281/zenodo.19595850)

---

## Что такое NOUZ

MCP-сервер для Obsidian, который даёт ИИ-агенту инструменты для осмысленной работы с базой знаний. NOUZ создаёт в базе семантическое многомерное пространство, в котором агент видит структуру, понимает принадлежность каждой заметки к доменам и находит нетривиальные связи между идеями.

В основе — векторные эмбеддинги, косинусное сходство и коррекция анизотропии трансформеров. Всё это работает локально.

### Научные основы

- **Mean subtraction** — удаление анизотропии эмбеддингов ([Su et al., 2021](https://arxiv.org/abs/2103.15343); Ethayarajh, 2019)
- **Двунаправленная причинность** — sign сверху вниз, core_mix снизу вверх; формализация у [Ellis, 2024](https://doi.org/10.1007/s10701-024-00756-6)
- **core_drift** — сигнал рассогласования, аналог ошибки предсказания в [предиктивном кодировании](https://en.wikipedia.org/wiki/Predictive_coding) (Friston, 2010)
- **Аналогические мосты** — структурный изоморфизм, вдохновлён [теорией структурного отображения](https://en.wikipedia.org/wiki/Structure-mapping_theory) (Gentner, 1983)

Подробное изложение: [Рекурсивная самоорганизация как универсальный принцип](https://doi.org/10.5281/zenodo.19595850) — междисциплинарная модель, из которой вытекают архитектурные решения NOUZ.

---

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

```bash
pip install nouz-mcp
OBSIDIAN_ROOT=/path/to/vault nouz-mcp
```

Без `config.yaml` сервер запускается в режиме **LUCA** — граф без семантики, работает сразу.

Или из исходников:

```bash
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-клиенту:

```json
{
  "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 → аналогический мост
```

Вдохновлено [теорией структурного отображения](https://en.wikipedia.org/wiki/Structure-mapping_theory) (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` | Получить вектор для любого текста. |

### Типичный сценарий работы агента

1. **Новая заметка.** Агент пишет текст → вызывает `suggest_metadata` → получает sign, level, мосты, drift-предупреждения → записывает с правильным YAML через `write_file`.

2. **Сирота нашла дом.** Агент видит заметку без родителей → `suggest_parents` → предлагает связи → человек подтверждает.

3. **Drift обнаружен.** `suggest_metadata` возвращает `core_drift` warning → «Модуль заявлен как T, но 45% контента — S. Пересмотреть структуру?»

4. **Мост между мирами.** Агент видит, что квант про энтропию и квант про сжатие данных связаны семантическим мостом → предлагает связь → человек решает.

---

## Конфигурация

Создайте `config.yaml` рядом с сервером:

```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 работает полностью локально. Но если вы подключаете облачного агента — контекст, который он видит, уходит к провайдеру. Используйте локальных агентов, если приватность критична.

---

## Разработка

```bash
git clone https://github.com/KVANTRA-dev/NOUZ-MCP
cd NOUZ-MCP
pip install -e .
python -m pytest test_server.py
```

---

## Ссылки

- 🌐 [Сайт](https://kvantra.tech)
- 📦 [PyPI](https://pypi.org/project/nouz-mcp/)
- 🗂️ [Glama Registry](https://glama.ai/mcp/servers/KVANTRA-dev/NOUZ-MCP)
- 💬 [Telegram](https://t.me/volnaya_sreda)
- 🐙 [GitHub](https://github.com/KVANTRA-dev/NOUZ-MCP)
- 📄 [Статья "Рекурсивная организация как универсальный принцип"](https://doi.org/10.5281/zenodo.19595850)

---

MIT License © 2026 KVANTRA

*Косинусы считаются. Синтаксис меняется. Семантика остаётся.*

<!-- mcp-name: io.github.KVANTRA-dev/NOUZ-MCP -->
