[2026-09-26] eagle: personal/plans/balda-mm-phase4-agents.md personal/tech/balda-executor-mcp.md
This commit is contained in:
1 parent
c3ced58ee1
commit
218165c8c7
2 files changed
+118
-12
No files matched your search
@@ -14,8 +14,9 @@
|
||||
| 2 | Мост FastAPI :8790 | ✅ работает под launchd, туннель `agents-bridge.qentra.top` заведён Alex'ом |
|
||||
| 3 | Сеть Kraken → Mac | ✅ **Cloudflare Tunnel** (постоянно); LAN остаётся для отладки |
|
||||
| 4 | Секция «Agents» в Dashboard | ✅ активирована и проверена |
|
||||
| 5 | Связка Балда → мост | ✅ конфиг переведён на `type: http`, образ 0.2.0, `tools/list` из docker-сети |
|
||||
| 6 | Obsidian MCP для Балды | ✅ контейнер `obsidian-mcp` на Kraken + `type: sse` в конфиге Балды |
|
||||
| 5 | Связка Балда → мост | ✅ конфиг `type: http`, образ 0.2.0, `tools/list` из docker-сети |
|
||||
| 6 | Obsidian MCP для Балды | ✅ контейнер `obsidian-mcp` на Kraken + `type: sse` в конфиге (транспорт проверен) |
|
||||
| 6a | 🔴 Инструменты MCP в сессии Балды | 🔴 **блокер:** снапшот каталога в `state.db` содержит только `builtin` → Балда «MCP не вижу». См. [[personal/tech/balda-executor-mcp]] §10g |
|
||||
| 7 | Приёмка от аккаунта Alex | 🔴 блокер: авторизация CLI |
|
||||
|
||||
---
|
||||
@@ -292,9 +293,16 @@ lsof -nP -iTCP:8790 -sTCP:LISTEN
|
||||
- obsidian
|
||||
```
|
||||
См. §11 ниже.
|
||||
3. 🟡 Проверить, что инструменты видны в сессии Балды — **постом от админа** в
|
||||
Mattermost. ⚠️ Пост **от имени самого бота** Балда игнорирует (правильно);
|
||||
для теста нужен пост от админского токена (`mattermost mmctl --local token generate admin …`).
|
||||
3. 🔴 **MCP-инструменты не видны в сессии Балды.** Транспорты и сети проверены живьём
|
||||
(оба сервера отвечают 200 из docker-сети), Балда стартует без ошибок и отвечает в чате —
|
||||
но говорит «MCP не вижу». **Корень найден:** снапшот каталога в `state.db`
|
||||
(`balda.appruntime_catalog_snapshot:*`) содержит **только `builtin`** — источники
|
||||
`configured` не скомпилированы; плюс сессия закреплена за старым `RuntimeSnapshotID`.
|
||||
Разбор и механика — [[personal/tech/balda-executor-mcp]] §10g.
|
||||
⏳ Ждёт решения Alex: **A)** вычистить ключи снапшотов из `state.db` (рекомендовано),
|
||||
**B)** полный сброс `state.db`.
|
||||
⚠️ Тест-пост должен идти **от админского токена** — посты от имени самого бота Балда
|
||||
игнорирует (правильно): `docker exec mattermost mmctl --local token generate admin …`.
|
||||
4. 🔴 Логин CLI (Alex вручную) — без него сквозная приёмка невозможна.
|
||||
5. 🔴 **Завести Access Application** на `agents-bridge.qentra.top` — сейчас туннель
|
||||
отвечает 200 без авторизации (проверено). Защита — только `X-Bridge-Secret`.
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# balda-executor-mcp — MCP-сервер делегирования задач (шаг 5 Фазы 4)
|
||||
|
||||
> Создан 2026-09-26. Шаг 5 плана [[personal/plans/balda-mm-phase4-agents]].
|
||||
> Статус: **собран, задеплоен на Kraken, образ обновлён до 0.2.0; конфиг Балды
|
||||
> переведён на `type: http`, Obsidian MCP прописан рядом** — ждёт сквозной проверки в чате.
|
||||
> Статус: **собран, задеплоен на Kraken, образ `0.2.0`; конфиг Балды — `type: http` +
|
||||
> `obsidian: sse`. Балда стартует без ошибок и отвечает в чате.**
|
||||
> 🔴 **Блокер:** MCP-инструменты не попадают в сессию — корень в снапшоте каталога
|
||||
> (`state.db`), см. **§10g**. Ждёт решения Alex (вариант A/B).
|
||||
> Связка: Балда (Kraken) → MCP → мост (Mac :8790) → контейнер-исполнитель.
|
||||
|
||||
---
|
||||
@@ -276,16 +278,112 @@ docker exec balda-executor-mcp python3 -c "import uvicorn, fastapi, httpx; print
|
||||
|
||||
---
|
||||
|
||||
## 10g. 🔴🔴 ГЛАВНЫЙ КОРЕНЬ: MCP-серверы не попадают в сессию из-за снапшота каталога
|
||||
|
||||
Симптом: **все транспорты верны, оба сервера отвечают 200 из docker-сети, а Балда в чате
|
||||
говорит «MCP не вижу, ни одного сервера».** Ошибок в логах нет. `/reset` при этом
|
||||
**перечисляет** серверы — то есть ID прочитаны из YAML, но инструменты не подключены.
|
||||
|
||||
### Диагностика (порядок)
|
||||
|
||||
```bash
|
||||
# 1. Есть ли вообще слова obsidian / executor-mcp в логе Балды?
|
||||
docker logs balda-mm 2>&1 | grep -ci "obsidian" # → 0
|
||||
docker logs balda-mm 2>&1 | grep -ci "executor-mcp" # → 0
|
||||
```
|
||||
|
||||
Если **0** — проблема не в транспорте и не в сети: каталог не публикует эти источники.
|
||||
|
||||
```bash
|
||||
# 2. Что лежит в снапшотах каталога (state.db)
|
||||
STATE=/srv/dev-disk-by-uuid-49e8f586-…/docker/balda/state
|
||||
strings "$STATE/state.db" | grep -o 'balda.appruntime_catalog_snapshot:[a-f0-9]*' | head
|
||||
strings "$STATE/state.db" | grep -A1 'catalog_snapshot' | grep -o '"kind":"[a-z]*","name":"[a-z-]*"' | sort -u
|
||||
```
|
||||
|
||||
**Показательный результат (баг):**
|
||||
|
||||
```json
|
||||
"sources":[{"id":{"kind":"builtin","name":"balda"}, …}]
|
||||
```
|
||||
|
||||
В снапшоте **только `builtin`**. Источников `configured` (наши `executor-mcp`/`obsidian`)
|
||||
нет — значит `PreparePluginCandidate` их не скомпилировала.
|
||||
|
||||
### Механика (по коду, `internal/apps/balda/`)
|
||||
|
||||
| Звено | Файл | Что делает |
|
||||
|---|---|---|
|
||||
| параметры модуля | `catalogapp/module.go` | `params.Norma.MCPServers` ← `runtime.mcp_servers` |
|
||||
| сборка | `catalogapp/runtime.go:81` | `configuredMCP: configuredMCPSources(configured)` |
|
||||
| компиляция | `runtime.go:128` `PreparePluginCandidate` | `sources := [builtin] + r.configuredMCP + skills + plugins` |
|
||||
| публикация | `runtime.go:168` `PublishCandidate` | `persistSnapshot` → `store.PublishApplication` → **`r.mcp.Reconcile(ctx, retained)`** |
|
||||
| привязка к сессии | `runtime.go:188` `ResolveEffectiveSnapshot` | если у сессии есть `record.RuntimeSnapshotID` → берётся **именно он** |
|
||||
| выдача ID | `module.go:57` `AcquireMCPServerIDs(ctx, snapshot.ID)` | ID MCP берутся из **снапшота**, не из конфига |
|
||||
|
||||
🔴 **Два независимых условия, оба обязаны выполниться:**
|
||||
|
||||
1. `PublishCandidate` должен быть **вызван** — он единственный, кто дёргает
|
||||
`mcp.Reconcile`. Вызывается при публикации кандидата (плагины/скиллы/старт).
|
||||
2. Сессия **не должна** быть закреплена за старым `RuntimeSnapshotID`.
|
||||
Привязка вечная: строка `record.RuntimeSnapshotID != ""` → старый снапшот навсегда.
|
||||
|
||||
📌 **Из этого следует:** правка `runtime.mcp_servers` в YAML **не влияет** на уже
|
||||
существующие сессии. Нужно новое состояние каталога + новые сессии.
|
||||
|
||||
### Правило для будущих правок MCP в Балде
|
||||
|
||||
1. Залить конфиг.
|
||||
2. Убедиться, что `PublishCandidate` отработает (новый каталог) — иначе снапшот остаётся старым.
|
||||
3. Создать **новую** сессию (не переиспользовать старую — она прибита к снапшоту).
|
||||
4. Проверить **постом от админского токена** (не от бота — свои посты Балда игнорирует):
|
||||
|
||||
```bash
|
||||
docker exec mattermost mmctl --local token generate admin whale-check --json | jq -r '.[0].token'
|
||||
```
|
||||
|
||||
### Открытый вопрос на конец сессии
|
||||
|
||||
Требует решения Alex (удаление данных → нужно подтверждение):
|
||||
- **A)** точечно вычистить ключи `balda.appruntime_catalog_snapshot:*` из `state.db`
|
||||
(owner/настройки целы, снапшоты пересоберутся) — рекомендовано;
|
||||
- **B)** полный сброс `state.db` (заново `bootstrap-admin` + owner-авторизация).
|
||||
|
||||
⚠️ `catalog-revisions/` на хосте — `drwx------ root`, обычным пользователем не читается
|
||||
(`Permission denied`). Смотреть только через `strings state.db`.
|
||||
|
||||
---
|
||||
|
||||
## 11. Что осталось
|
||||
|
||||
1. ✅ **`runtime.mcp_servers.executor-mcp` → `type: http`** — сделано, залито на Kraken.
|
||||
2. ✅ **`obsidian` прописан рядом** (`type: sse` → `http://obsidian-mcp:3101/sse`).
|
||||
3. ✅ Образ обновлён до `0.2.0` на Kraken, `tools/list` отдаёт 3 инструмента из docker-сети.
|
||||
4. 🟡 Перезапустить Балду и убедиться, что инструменты обоих серверов видны в сессии
|
||||
(последняя правка `type: http` в конфиге **залита в `/tmp/balda-cfg/config.yaml`**, но
|
||||
на момент окончания сессии перезапуск с валидным типом ещё не подтверждён сквозным тестом).
|
||||
5. 🔴 Сквозная приёмка: `executor_run` из чата → задача на Mac → результат.
|
||||
6. 🔴 Логин CLI внутри `balda-executor` — делает **Alex вручную**.
|
||||
4. ✅ Балда перезапущена с валидным типом — **стартует без ошибок**, `Balda bot started`,
|
||||
`type: http` принят валидатором. Сквозной пост отработан, Балда **ответила**.
|
||||
5. 🔴 **Блокер:** Балда отвечает «MCP не вижу». Корень — снапшот каталога (**§10g**):
|
||||
в `state.db` снапшот содержит только `builtin`. Нужно решение Alex (вариант A или B, §10g).
|
||||
6. 🔴 Сквозная приёмка: `executor_run` из чата → задача на Mac → результат.
|
||||
7. 🔴 Логин CLI внутри `balda-executor` — делает **Alex вручную**.
|
||||
|
||||
### Что проверено живьём (2026-09-26, конец сессии)
|
||||
|
||||
| Проверка | Результат |
|
||||
|---|---|
|
||||
| `executor-mcp:8890/mcp` из docker-сети | HTTP 200 + `mcp-session-id` ✅ |
|
||||
| `obsidian-mcp:3101/sse` из docker-сети | 200 + `text/event-stream` + `event: endpoint` ✅ |
|
||||
| `executor-mcp:8890/sse` (не тот эндпоинт) | 404 — правильно ✅ |
|
||||
| `obsidian-mcp:3101/mcp` (не тот эндпоинт) | 400 — правильно ✅ |
|
||||
| туннель `agents-bridge.qentra.top/healthz` из `mattermost` | 200 через Cloudflare ✅ |
|
||||
| Балда после правки `type: http` | старт без ошибок, ответ в чате ✅ |
|
||||
| слова `obsidian`/`executor-mcp` в логе Балды | **0** ❌ → корень в снапшоте (§10g) |
|
||||
|
||||
📌 **Метод проверки транспорта:** у каждого сервера ровно один рабочий эндпоинт.
|
||||
Быстрый тест из `mattermost` (там есть `curl`, в образе Балды — нет):
|
||||
|
||||
```bash
|
||||
docker exec mattermost sh -c 'curl -sS -m 8 -o /dev/null -w "HTTP %{http_code}\n" -H "Accept: text/event-stream" http://obsidian-mcp:3101/sse'
|
||||
```
|
||||
|
||||
## 12. Версии образа
|
||||
|
||||
|
||||
Reference in new issue
Block a user