| 1 | # ADR 014 (MCP): Локальные настройки — TOML по `--config` (релиз **2.0**) |
| 2 | |
| 3 | **Статус:** Proposed |
| 4 | **Дата:** 2026-05-16 |
| 5 | **Обновлено:** 2026-05-16 — breaking MCP **2.0**: обязательный `--config`, Tomlyn, без legacy env/META JSON. |
| 6 | |
| 7 | **Канонический текст (KB):** `knowledge/adr/013-agent-notes-mcp-local-settings-toml-v1.md` (репо **agent-notes**), в т.ч. **R7 — major 2.0**. |
| 8 | |
| 9 | ## Связанные ADR |
| 10 | |
| 11 | | ADR | Роль | |
| 12 | |-----|------| |
| 13 | | [008](008-workspace-scope-map-resolution.md) | резолв scope workspace | |
| 14 | | [013](013-localhost-status-surface-v1.md) | секция `[status]` в том же TOML | |
| 15 | |
| 16 | ## Резюме |
| 17 | |
| 18 | - **MCP 2.0:** один локальный TOML по **`--config`** в `mcp.json` (как DBHub), без walk-up и без `AGENT_NOTES_CANON_PATH`. |
| 19 | - Секции: `[knowledge]`, `[workspace]`, `[status]`; `version = 1` в файле — схема TOML, не semver продукта. |
| 20 | - Breaking: `canon_path` → `knowledge_path`; embedded defaults + merge Tomlyn. |
| 21 | - До релиза **1.x** — env + META JSON; после — только TOML. |
| 22 | |
| 23 | --- |
| 24 | |
| 25 | ## Контекст для разработчиков MCP |
| 26 | |
| 27 | Как **DBHub** (`--config path/to/config.toml` в `mcp.json`), без автопоиска по workspace: |
| 28 | |
| 29 | ```json |
| 30 | "agent-notes": { |
| 31 | "command": "D:\\agent-notes-mcp\\AgentNotesMcp.exe", |
| 32 | "args": ["--config", "D:/path/agent-notes-mcp.local.toml"], |
| 33 | "env": {} |
| 34 | } |
| 35 | ``` |
| 36 | |
| 37 | Локальный TOML (`version = 1` в файле): `[knowledge]`, `[workspace]`, `[status]`. Появляется только в **MCP 2.0**. До релиза **1.x** — env + META JSON, без TOML. |
| 38 | |
| 39 | Полная схема и список breaking — **KB ADR 013** (R3, R7). |
| 40 | |
| 41 | --- |
| 42 | |
| 43 | ## Реализация (целевая) |
| 44 | |
| 45 | | Компонент | Ответственность | |
| 46 | |-----------|-----------------| |
| 47 | | **Program.cs** | parse `--config` (alias `--config-file`) **до** `McpServer.RunAsync`; fail fast если путь задан и файл битый | |
| 48 | | **AgentNotes.Core** | `LocalSettingsLoader.Load(configPath)`; Tomlyn; merge поверх embedded defaults | |
| 49 | | **NotesStorage** | settings from loaded file | |
| 50 | | **Embedded** | `Resources/agent-notes-mcp.defaults.toml` | |
| 51 | |
| 52 | ### Приоритет пути к конфигу (**2.0**) |
| 53 | |
| 54 | 1. CLI **`--config`** (абсолютный путь рекомендуется) |
| 55 | 2. Env **`AGENT_NOTES_CONFIG`** — тесты / хосты без `args` |
| 56 | 3. Иначе — **ошибка запуска** с текстом «нужен --config» (legacy `AGENT_NOTES_*` **не** в supported path 2.0) |
| 57 | |
| 58 | **Walk-up:** не реализуем (KB ADR 013). |
| 59 | |
| 60 | ### Приоритет (**1.x**, до 2.0) |
| 61 | |
| 62 | Как сейчас: env `AGENT_NOTES_*`, META JSON — без изменений до тега `2.0.0`. |
| 63 | |
| 64 | ### Поведение при ошибке config |
| 65 | |
| 66 | | Ситуация | Поведение | |
| 67 | |----------|-----------| |
| 68 | | `--config` / `AGENT_NOTES_CONFIG` задан, файл отсутствует или TOML невалиден | **exit ≠ 0**, понятное сообщение в stderr | |
| 69 | | Явный путь не задан (**2.0**) | exit ≠ 0, инструкция по example toml | |
| 70 | |
| 71 | ### Tomlyn |
| 72 | |
| 73 | В **AgentNotes.Core**; тесты с `--config` на fixture в `AgentNotesMcp.Tests`. |
| 74 | |
| 75 | **2.0:** `[workspace]` вместо META JSON; `[knowledge]` для корней; ToolCatalog — **`knowledge_path`**; `LocalSettings` / резолвер без имён `Canon*` в новом API (допустимы private alias на переходе внутри PR). |
| 76 | |
| 77 | ### Миграция 1.x → 2.0 (чеклист) |
| 78 | |
| 79 | 1. Собрать/скачать **agent-notes-mcp 2.0.x**. |
| 80 | 2. Создать TOML из `knowledge/work/local/agent-notes.workspace.example.toml` (схема файла `version = 1`). |
| 81 | 3. В `mcp.json`: `"args": ["--config", "<abs path>"], "env": {}`. |
| 82 | 4. В правилах и playbook: **`canon_path` → `knowledge_path`**. |
| 83 | 5. Удалить `knowledge/META/mcp-resolve-paths-v1.json` из primary KB (после проверки путей в `[workspace]`). |
| 84 | |
| 85 | --- |
| 86 | |
| 87 | ## Техдолг и приборка в коде (релиз 2.0) |
| 88 | |
| 89 | Сейчас логика в **agent-notes-core** + тонкий **AgentNotesMcp**; имена застряли на эпохе env + META JSON. **2.0** — единственный разумный момент для переименований и выкидывания legacy (не тащить «canon» в новый TOML-loader). |
| 90 | |
| 91 | ### Публичный контракт MCP (breaking) |
| 92 | |
| 93 | | Было | Стало | |
| 94 | |------|--------| |
| 95 | | аргумент тула `canon_path` | **`knowledge_path`** (`ToolCatalog`, `ToolHandlers`, manifest export) | |
| 96 | | описания «канон» / `AGENT_NOTES_CANON_PATH` | primary **knowledge root**, путь из **`--config`** | |
| 97 | | `Program.cs` `Version = "0.5.1"` | **`2.0.0`** (+ informational / assembly version) | |
| 98 | |
| 99 | ### AgentNotes.Core |
| 100 | |
| 101 | | Область | Сейчас | 2.0 | |
| 102 | |---------|--------|-----| |
| 103 | | Резолв корня | `ResolveCanonPath`, `TryInferCanonRootFromAgentNotesFilePath`, `EnvCanonPath` | `ResolveKnowledgeRoot` (или `ResolvePrimaryKnowledgeRoot`), настройки из **`LocalSettings`** после Tomlyn | |
| 104 | | Пути scope | `ReadMcpResolvePathsOrDefaults`, `McpResolvePathsDefaults`, `McpResolvePathsConfigModel`, `mcp-resolve-paths-defaults.json` | `WorkspacePaths` / `[workspace]` из TOML + embedded **`agent-notes-mcp.defaults.toml`** | |
| 105 | | META на диске | `knowledge/META/mcp-resolve-paths-v1.json` | **не читать** (реализовано в 2.0); тесты — fixture TOML | |
| 106 | | Параметры API | `canonPath` во всех `*KnowledgeFile*` | `knowledgePath` (или optional `knowledgeRoot`) | |
| 107 | | Внутренние имена | `canonRoot`, `ResolveCanonRootFromNotesPath` | `knowledgeRoot` | |
| 108 | |
| 109 | Дубликаты `.cs` в корне **agent-notes-mcp** — **удалены** при выносе Core (зеркало больше не в репо). |
| 110 | |
| 111 | ### AgentNotesMcp |
| 112 | |
| 113 | | Область | Действие | |
| 114 | |---------|----------| |
| 115 | | `Program.cs` | parse **`--config`** до `McpServer.RunAsync`; fail fast | |
| 116 | | `ToolHandlers` | `canon_path` → `knowledge_path` | |
| 117 | | Тесты | `TempCanon` → `TempKnowledgeRoot`; фикстуры TOML вместо META JSON | |
| 118 | |
| 119 | ### Связанные репозитории (не блокер MCP, но тот же major по смыслу) |
| 120 | |
| 121 | - **Cascade IDE** (`McpAgentNotesService`, `IdeMcpCommandExecutor`): параметр `canon_path` в JSON команд — обновить при поднятии ссылки на Core 2.0. |
| 122 | - **Cursor rules / KB playbook**: `canon_path` в текстах. |
| 123 | - **agent-notes** KB: удалить `knowledge/META/mcp-resolve-paths-v1.json` после кода. |
| 124 | |
| 125 | ### Что не переименовывать в 2.0 (осознанно) |
| 126 | |
| 127 | - Имена **файлов** в репо (`agent-notes.md`, каталог `knowledge/`) — без изменений. |
| 128 | - ADR **012** title «multi-canon» — исторический документ; в новом коде не продлевать термин. |
| 129 | |
| 130 | ### `[[knowledge.read_only]]` — схема в 2.0, маршрутизация позже |
| 131 | |
| 132 | Смысл и роли корней — **KB** [012-multi-canon-workspace-resolution-v1.md](https://github.com/KarataevDmitry/personal-knowledge-base/blob/main/knowledge/adr/012-multi-canon-workspace-resolution-v1.md) (исторически «secondary canon»). В TOML это **не** то же самое, что `[knowledge.roots]`: |
| 133 | |
| 134 | | Секция | Роль | |
| 135 | |--------|------| |
| 136 | | **`[knowledge].primary`** + **`[knowledge.roots]`** | Один **primary** knowledge root: hot-файл, **запись** в `knowledge/`, `[workspace]` (карта scope только из primary). | |
| 137 | | **`[[knowledge.read_only]]`** | Дополнительные корни **только чтение** (group-kb / `AI-Guiders/kb`, kb-public-клон): агент может **читать** карточки, **не** писать туда через MCP. Поле **`id`** — стабильная метка (`group`, `public`) — см. chmod ugo в [015](015-multi-root-read-only-knowledge-routing-v1.md). | |
| 138 | |
| 139 | Пример (опционально в `--config`; в шаблоне `config/agent-notes-mcp.toml` — закомментирован): |
| 140 | |
| 141 | ```toml |
| 142 | [[knowledge.read_only]] |
| 143 | id = "group" |
| 144 | path = "D:/clones/AI-Guiders/kb" |
| 145 | ``` |
| 146 | |
| 147 | **Релиз `2.0.0` (фактически в коде):** |
| 148 | |
| 149 | | Что | Статус | |
| 150 | |-----|--------| |
| 151 | | Парсинг Tomlyn → `LocalSettings.ReadOnlyKnowledgeRoots` | **да** | |
| 152 | | `read_knowledge_file` / `list_knowledge_files` по `knowledge_root_id` read-only | **да** ([015](015-multi-root-read-only-knowledge-routing-v1.md), 2.1) | |
| 153 | | Запрет записи в read-only при `knowledge_root_id` или `knowledge_path` | **да** (2.1) | |
| 154 | | `[routing]` / overlay org в `route_context` | **фаза 2** (KB ADR 013) | |
| 155 | |
| 156 | До multi-KB секцию **можно не заполнять** — поведение как с одним primary. Обязательный минимум конфига: `[knowledge]` + `[workspace]` (или embedded defaults для `[workspace]`). |
| 157 | |
| 158 | **Следующий шаг (2.1, ADR 015):** резолв `knowledge_root_id` → primary (**user**) или read-only (**group**); `write_*` только в primary; status `read_only_routing_enabled`. **Фаза 2:** overlay group в `route_context`. |
| 159 | |
| 160 | --- |
| 161 | |
| 162 | ## Критерии принятия |
| 163 | |
| 164 | - `mcp.json` с `--config` → тот же primary KB root, что раньше через `AGENT_NOTES_CANON_PATH`. |
| 165 | - Информационная версия сборки начинается с **2.0**. |
| 166 | - `env: {}` достаточно при полном TOML. |
| 167 | - Unit-тесты: valid fixture; missing file + `--config` → fail fast. |
| 168 | |
| 169 | --- |
| 170 | |
| 171 | ## Открытые вопросы (MCP) |
| 172 | |
| 173 | 1. Относительный `--config` от cwd — разрешить с warning или только absolute (рекомендация KB: absolute). |
| 174 | |