11 KiB
Executable File
[!IMPORTANT] Актуальная конфигурация для Balda (2026-10-09) Текущая Balda использует Codex ACP и Streamable HTTP:
type: http, URLhttp://host.docker.internal:3101/mcp. Указания ниже про Balda + SSE или/sseотносятся к прежним клиентам/развёртываниям. Канонический runbook: personal/projects/balda/setup.
Obsidian MCP — текущая архитектура
Факт: что стоит сейчас
Hermes native MCP client (встроен в Hermes Agent, не wrapper).
Конфиг в ~/.hermes/config.yaml (и в ~/.hermes/hermes-whale/config.yaml):
mcp_servers:
obsidian:
command: mcpvault
args:
- /Users/admin/obsidian
Пакет: @bitbonsai/mcpvault v0.12.1 (npm). Команда mcpvault.
Hermes на старте:
- Читает
mcp_serversиз config.yaml - Спавнит
mcpvault /Users/admin/obsidianкак subprocess - Init + list_tools → регистрирует инструменты как
mcp_obsidian_* - Агент видит инструменты
mcp_obsidian_read_note,mcp_obsidian_patch_note, и т.д.
Схема:
Hermes (native MCP client) → spawn: mcpvault → reads/writes /Users/admin/obsidian/
Инструменты, доступные через эту связку
read_note, write_note, patch_note, list_directory, delete_note, search_notes, move_note, move_file, read_multiple_notes, update_frontmatter, get_notes_info, get_frontmatter, manage_tags, get_vault_stats, list_all_tags.
Факт: что такое ~/scripts/obsidian-mcp-wrapper.js и почему он НЕ используется
Создан 2026-05-09, когда вместо mcpvault стоял npx obsidian-mcp (старый пакет, автор Steven, ещё до переименования в @bitbonsai/mcpvault). Пакет постоянно падал:
- ZodError на
"id": nullв notifications —.strict()валидация - Race condition при рестарте gateway
- UTF-8 chunk split портил большие JSON
- Зависания без watchdog
Wrapper решал всё это. Сейчас НЕ используется. Конфиг в ~/.hermes/config.yaml:
mcp_servers:
obsidian:
command: mcpvault # ← не node wrapper.js
args:
- /Users/admin/obsidian
Почему: после перехода на @bitbonsai/mcpvault (пришёл на смену старому obsidian-mcp), пакет стабильно работает с Hermes native MCP client. Wrapper стал не нужен. Конфиг поменяли, а doc не обновили.
Файл ~/scripts/obsidian-mcp-wrapper.js лежит на диске, не используется. Надо удалить.
Факт: корень проблем с patch_note
mcp_obsidian_patch_note падает с "String not found" — это НЕ проблема транспорта. Это проблема самого mcpvault:
- Файл:
dist/src/filesystem.js, строка 217 - Механизм:
fullContent.split(oldString).length - 1 - Exact string match — без trim, без fuzzy, без нормализации whitespace
Workaround: использовать Hermes patch() (fuzzy matching, 9 стратегий) для сложных строк. mcp_obsidian_patch_note — только для простого текста без спецсимволов.
Fact: Obsidian MCP на Kraken — есть, и это stdio-процесс Hermes
Проверено 2026-09-26. На Kraken MCP-сервер не является отдельным контейнером —
его спавнит агент Hermes как дочерний процесс. Первый поиск «нет контейнера →
нет MCP» был ошибочным: искать надо было процессы, а не docker ps.
# на хосте Kraken
ps aux | grep mcpvault
→ UID 10000 1168741 ... node /opt/data/.local/bin/mcpvault /vault
PPID 5039 → /opt/hermes/.venv/bin/hermes gateway (контейнер hermes-kraken)
Конфиг (/opt/data/config.yaml внутри контейнера hermes-kraken):
mcp_servers:
obsidian:
command: /opt/data/.local/bin/mcpvault
args:
- /vault
mcpvault там — симлинк на npm-пакет: /opt/data/.local/lib/node_modules/@bitbonsai/mcpvault/dist/server.js.
Волт на Kraken — реальный, не пустой
/home/kraken/obsidian -> /srv/dev-disk-by-uuid-49e8f586-…/obsidian
(тот же HDD, что и docker-data)
Внутри: personal/, family/, .obsidian/, .git/, _index.md — полноценная
git-реплика волта Mac. То есть волт существует в обоих местах, а не только на Mac.
Итог: два независимых Obsidian MCP
| Где | Как | Транспорт | Порт |
|---|---|---|---|
| Mac | контейнер obsidian-mcp (mcp-proxy → mcpvault) |
SSE | :3101, публикуется на 0.0.0.0 |
| Kraken | mcpvault как дочерний процесс hermes-kraken |
stdio | нет |
| Kraken (для Балды) | контейнер obsidian-mcp — создан 2026-09-26 |
SSE | :3101, только внутри mattermost_mm-net |
📌 mcpvault не умеет HTTP — только stdio (--help подтверждает: только [vault-path]).
Чтобы отдать его по сети, нужен mcp-proxy (обёртка stdio → SSE). Именно так сделано
на Mac и повторено на Kraken.
Fact: obsidian-mcp на Kraken для Балды (создан 2026-09-26)
Собрано для шага 5 personal/plans/balda-mm-phase4-agents: Балде нужен доступ к волту, чтобы читать документацию при формировании ТЗ.
Точная копия рабочей схемы с Mac — пара mcp-proxy + mcpvault:
| Что | Путь / значение |
|---|---|
| Проект (Mac) | ~/Developer/obsidian-mcp-kraken/ |
| Dockerfile | node:24-bookworm + @bitbonsai/mcpvault@0.11.0 + mcp-proxy@6.4.4 |
| Образ | obsidian-mcp-image:0.1.0 (загружен на Kraken) |
| Compose (Kraken) | /home/kraken/obsidian-mcp/docker-compose.yml |
| Контейнер | obsidian-mcp, сеть mattermost_mm-net |
| Волт | /srv/dev-disk-by-uuid-49e8f586-…/obsidian → /vault :ro |
| Команда | mcp-proxy --port 3101 -- mcpvault /vault |
🔴 Волт смонтирован только для чтения (:ro). Балда читает документацию, но не
правит её. Запись в волт через Балду — отдельное решение, требует апрува Alex.
services:
obsidian-mcp:
image: obsidian-mcp-image:0.1.0
container_name: obsidian-mcp
restart: unless-stopped
command: ["--port", "3101", "--", "mcpvault", "/vault"]
volumes:
- /srv/dev-disk-by-uuid-49e8f586-…/obsidian:/vault:ro
networks:
- mm-net # mattermost_mm-net, external
Питфоллы, пройденные при сборке
| # | Питфолл | Симптом | Фикс |
|---|---|---|---|
| 1 | --host у mcp-proxy нет |
контейнер падает на разборе аргументов | только --port N -- <cmd> <args>; слушает 0.0.0.0 по умолчанию |
| 2 | Точка монтирования должна существовать в образе | mkdir -p /vault в Dockerfile + WORKDIR /vault |
иначе mcpvault стартует не в том каталоге |
Проверка
# /sse отвечает 200 (и локально, и из docker-сети Kraken)
curl -s -o /dev/null -w "%{http_code}\n" http://obsidian-mcp:3101/sse
# ⚠️ Порт именно 3101, НЕ 8080. Проба на 8080 даёт "Connection refused" при живом
# контейнере — mcp-proxy слушает порт из --port.
✅ ПРИМЕНЕНО 2026-09-26. Конфиг Балды на Kraken теперь содержит оба сервера:
runtime:
mcp_servers:
executor-mcp:
type: http # ⚠️ НЕ streamable-http — валидатор: stdio|http|sse
url: "http://balda-executor-mcp:8890/mcp"
obsidian:
type: sse # ⚠️ НЕ http — у obsidian-mcp SSE-транспорт
url: "http://obsidian-mcp:3101/sse"
balda:
mcp_servers:
- executor-mcp
- obsidian
🔴 Тип транспорта — источник двух подряд ошибок. Obsidian отдаёт SSE, поэтому
type: sse. Если поставить type: http, Балда упадёт с
failed to init MCP session: … session not found.
Полная таблица типов — personal/tech/balda-executor-mcp §10e.
Бэкапы: config.yaml.bak-obsidian-20260926-214849 (на Kraken, рядом с config.yaml).
⚠️ Туннель к Obsidian MCP не нужен — Балда ходит по docker-сети по имени
obsidian-mcp. Наружу порт не публикуется.
Эволюция Obsidian MCP у нас
| Период | Что было | Проблемы |
|---|---|---|
| До 2026-05-09 | npx obsidian-mcp (пакет Steven, прямой) |
ZodError, race condition, UTF-8 chunk split, зависания |
| 2026-05-09 → ? | npx obsidian-mcp через wrapper |
Wrapper решил проблемы |
| Сейчас | mcpvault (Hermes native MCP client) |
Стабильно. patch_note exact match — единственная боль |
Рекомендация по замене (2026-06-24)
При проблемах с mcpvault (зависания, память, exact match) — cyanheads/obsidian-mcp-server:
obsidian_replace_in_noteс regex + flexible whitespace (решает exact match)- 9.7K dl/week, dual transport (stdio + HTTP), active
- Требует Obsidian Local REST API plugin (Obsidian должен быть открыт)
- Есть Docker support (
ghcr.io/cyanheads/obsidian-mcp-server)
Подробнее: personal/tech/obsidian-mcp-ecosystem.md
См. также
personal/tech/obsidian-mcp-ecosystem.md— обзор всех 6 реализаций- ⚠️
personal/projects/personal-os/obsidian-mcp-wrapper.md— УСТАРЕЛ, не отражает реальность