[2026-06-25] taiga-vault: family/how-to/htpc-emulators-setup.md family/how-to/htpc-gaming-plans.md family/how-to/kraken-access.md family/how-to/openmediavault-rpi5.md family/how-to/time-machine.md family/how-to/wireguard-vpn.md personal/documents/todo-list.md personal/plans/extract-stable-prompt-blocks.md personal/plans/hermes-whale-system-prompt.md personal/plans/thread-scoped-memory.md
This commit is contained in:
@@ -1,114 +1,25 @@
|
||||
# obsidian-mcp-wrapper
|
||||
|
||||
> **Файл**: `~/scripts/obsidian-mcp-wrapper.js`
|
||||
> **Назначение**: прокси-обёртка над `obsidian-mcp`, решает четыре системных бага
|
||||
|
||||
---
|
||||
status: deprecated
|
||||
superseded_by: personal/projects/personal-os/obsidian-mcp-setup.md
|
||||
reason: >-
|
||||
wrapper не используется с 2026-05. Реальность: Hermes native MCP client →
|
||||
mcpvault
|
||||
---
|
||||
|
||||
## Проблемы, которые решает
|
||||
# obsidian-mcp-wrapper — УСТАРЕЛ
|
||||
|
||||
### 1. ZodError при инициализации (obsidian-mcp v1.0.6)
|
||||
> **⚠️ Этот документ не отражает реальность.** Wrapper не используется с мая 2026.
|
||||
> См. `personal/projects/personal-os/obsidian-mcp-setup.md` и
|
||||
> `personal/tech/obsidian-mcp-ecosystem.md`.
|
||||
|
||||
`obsidian-mcp` падал с ZodError сразу после запуска. Причина: Hermes отправляет
|
||||
`notifications/initialized` с полем `"id": null`, а obsidian-mcp v1.0.6 использует
|
||||
`.strict()` валидацию и не принимает лишние поля.
|
||||
Актуальная архитектура: **Hermes native MCP client → spawn `mcpvault /Users/admin/obsidian`**
|
||||
(пакет `@bitbonsai/mcpvault` v0.12.1). Конфиг в `~/.hermes/config.yaml` → `mcp_servers.obsidian`.
|
||||
|
||||
**Fix**: wrapper перехватывает все notification-сообщения (без `result`/`error`) с `id === null`
|
||||
и удаляет поле `id` перед передачей в child.
|
||||
Wrapper (`~/scripts/obsidian-mcp-wrapper.js`) когда-то решал проблемы старого пакета `obsidian-mcp`
|
||||
(автор Steven), который падал с ZodError, race condition и UTF-8 chunk split.
|
||||
После смены пакета на `@bitbonsai/mcpvault` — wrapper стал не нужен.
|
||||
|
||||
### 2. Race condition при gateway restart
|
||||
Корень проблем с `patch_note` (`"String not found"`) — exact string match в самом mcpvault,
|
||||
**не в транспорте**. Workaround: использовать Hermes `patch()` с fuzzy matching.
|
||||
|
||||
При рестарте Hermes gateway поднимает новый процесс `obsidian-mcp-wrapper`. Первые
|
||||
параллельные tool-вызовы приходят пока child ещё инициализируется (~500ms) → они
|
||||
тайм-аутились, circuit breaker открывался (3 фейла → 60s cooldown).
|
||||
|
||||
**Fix**: wrapper буферизует все tool-вызовы до завершения handshake
|
||||
(`initialize` → ответ → `notifications/initialized`), потом флашит очередь.
|
||||
|
||||
### 3. Corrupted large payloads (UTF-8 chunk split)
|
||||
|
||||
При больших tool-вызовах (~200KB+) Node.js доставляет stdin в нескольких chunk-ах.
|
||||
Старый код делал string split — JSON разрезался по байтам → UTF-8 multibyte символы
|
||||
портились, `JSON.parse` падал, сообщение дропалось молча.
|
||||
|
||||
**Симптом**: `edit_note` с большим контентом тихо зависал (30s timeout), в логах:
|
||||
```
|
||||
[obsidian-wrapper] Non-JSON from Hermes (forwarding verbatim): {"jsonrpc": "2.0", "method": "tools/call", "id": 3, "params": {"name": "edit-not
|
||||
```
|
||||
|
||||
**Fix**: stdin и stdout читаются через `Buffer.concat` + `Buffer.slice` на `0x0a`.
|
||||
Строка собирается полностью до передачи в `JSON.parse`.
|
||||
|
||||
### 4. Per-call watchdog (зависший child)
|
||||
|
||||
Если child не ответил на `tools/call` / `tools/list` / `resources/*` за **5s** —
|
||||
watchdog убивает процесс. После авторестарта call автоматически уходит в голову
|
||||
очереди и ретраится.
|
||||
|
||||
**Fix**: `armWatchdog(callLine)` → `setTimeout 5000ms` → `child.kill()` → `startChild()`.
|
||||
|
||||
---
|
||||
|
||||
## Как работает
|
||||
|
||||
```
|
||||
Hermes (stdin) → wrapper → obsidian-mcp (child)
|
||||
↑ auto-restart при краше (до 10 раз)
|
||||
```
|
||||
|
||||
**Состояния**:
|
||||
- `ready = false` — child стартует, все tool-вызовы в очередь
|
||||
- `ready = true` — handshake завершён, очередь флашится, всё проходит напрямую
|
||||
|
||||
**Restart логика**:
|
||||
1. Child упал → `ready = false`, `restarts++`
|
||||
2. Новый child спавнится
|
||||
3. Wrapper реплеит сохранённый `initialize` → ждёт ответа с `serverInfo`
|
||||
4. Отправляет `notifications/initialized` (не форвардит Hermes — он не просил)
|
||||
5. `ready = true` → флаш очереди
|
||||
|
||||
**Shutdown**:
|
||||
На stdin EOF (`Hermes` закрыл процесс) — child убивается без авторестарта, wrapper выходит чисто.
|
||||
|
||||
**Логи** (все в stderr с timestamp):
|
||||
```
|
||||
[obsidian-wrapper] 2026-05-09T12:00:00.000Z Spawning obsidian-mcp (vault=/Users/admin/obsidian)
|
||||
[obsidian-wrapper] 2026-05-09T12:00:00.500Z Hermes → child (handshake complete): notifications/initialized
|
||||
[obsidian-wrapper] 2026-05-09T12:00:00.501Z Child ready — flushing queue (3 items)
|
||||
[obsidian-wrapper] 2026-05-09T12:00:01.200Z Stripped id:null from notification: notifications/initialized
|
||||
[obsidian-wrapper] 2026-05-09T12:00:06.000Z WATCHDOG: child did not respond in 5000ms for tools/call #7 — killing and restarting
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Конфиг Hermes
|
||||
|
||||
`~/.hermes/config.yaml`:
|
||||
```yaml
|
||||
obsidian:
|
||||
command: node
|
||||
args: [/Users/admin/scripts/obsidian-mcp-wrapper.js]
|
||||
```
|
||||
|
||||
Wrapper сам вызывает `/opt/homebrew/bin/obsidian-mcp /Users/admin/obsidian`.
|
||||
|
||||
---
|
||||
|
||||
## Производительность
|
||||
|
||||
- Инициализация: ~587ms (без ZodError)
|
||||
- Overhead wrapper: negligible (pure Node.js child_process, нет npm-зависимостей)
|
||||
- MAX_RETRY: 10
|
||||
- CALL_TIMEOUT_MS: 5000ms (watchdog)
|
||||
|
||||
---
|
||||
|
||||
## История
|
||||
|
||||
**2026-05-09 (1)** — создан после диагностики 58 ошибок `obsidian/... call failed` в логах Hermes.
|
||||
Корневая причина — ZodError + race condition при старте. Wrapper написан вместо патча
|
||||
исходников obsidian-mcp (патч не нужен, wrapper чище и не ломается при обновлении пакета).
|
||||
|
||||
**2026-05-09 (2)** — фикс large payload: Buffer-based line splitting вместо string split
|
||||
(`edit_note` с большим контентом молча дропался). Добавлен per-call watchdog (5s timeout → kill & retry).
|
||||
MAX_RETRY повышен с 5 до 10.
|
||||
Историческая документация по wrapper сохранена ниже для ретроспективы.
|
||||
|
||||
Reference in New Issue
Block a user