From 02db589034f194c291dd7f2bfedf434f230aeb11 Mon Sep 17 00:00:00 2001 From: vitya Date: Tue, 12 May 2026 20:15:53 +0300 Subject: [PATCH] =?UTF-8?q?feat(skills):=20using-synology-ops=200.1.1?= =?UTF-8?q?=E2=86=920.1.2=20=E2=80=94=20fill=20body?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filled all sections from source docs: - ~/projects/.workshop/.archive/2026-05-12-using-synology-ops-skill.md - ~/projects/.wiki/concepts/synology-ops-mcp-design.md Sections: When to use (triggers), Inputs, Steps (4 flows), Failure modes, Side effects, What NOT to do (mistakes + red flags). Co-Authored-By: Claude Opus 4.7 (1M context) --- dist-hermes/mcp/using-synology-ops/SKILL.md | 62 ++++++++++++++++++--- skills/using-synology-ops/SKILL.md | 62 ++++++++++++++++++--- 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/dist-hermes/mcp/using-synology-ops/SKILL.md b/dist-hermes/mcp/using-synology-ops/SKILL.md index 4d8c0c9..abb8ab8 100644 --- a/dist-hermes/mcp/using-synology-ops/SKILL.md +++ b/dist-hermes/mcp/using-synology-ops/SKILL.md @@ -1,33 +1,79 @@ --- name: using-synology-ops -version: 0.1.1 +version: 0.1.2 description: Use when diagnosing docker containers on the Synology NAS — the `synology-ops` HTTP MCP server (https://opsmcp.kzntsv.site/mcp) exposes 4 read-only tools — `ops.docker.ps`, `ops.docker.logs`, `ops.docker.inspect`, `ops.docker.stats` — all routed through tecnativa `synology-docker-proxy-ro` with `POST=0` (write-ops return 403). Triggers on container names (`modulair-rag`, `modulair-pipeline`, `lightrag-modulair`, `tier1-converter`, `modulair-mcp`, `synology-ops-mcp`), on NAS-domain words ("на NAS", "Synology", "синолоджи", "Portainer-стек", "ops-mcp", "опс мсп", "opsmcp.kzntsv.site"), or on incident phrases ("падает", "restart-loop", "не стартует", "unhealthy", "посмотри логи") when NAS-context. Read-only by design — no per-session grant needed. Skip for non-incident mentions, "open Portainer GUI" requests, write-ops, and incident phrases on non-NAS hosts (`books-pipeline`, `vps-*` etc. — only the 6 listed above are NAS-hosted). --- # using-synology-ops -Trigger-and-guidance skill для `synology-ops-mcp` — read-only HTTP MCP-сервера на NAS, дающего Claude'у видимость состояния docker-контейнеров без юзера-моста (без Portainer copy-paste). Тело каркаса дописывается во втором проходе из `~/projects/.workshop/.archive/2026-05-12-using-synology-ops-skill.md` (process trace) и `~/projects/.wiki/concepts/synology-ops-mcp-design.md` (canonical design). +Trigger-and-guidance skill для `synology-ops-mcp` — read-only HTTP MCP-сервера на NAS, дающего Claude'у видимость состояния docker-контейнеров без юзера-моста (без Portainer copy-paste). ## When to use -<пусто — заполняется во втором проходе> +**Trigger — любой из трёх сигналов:** + +1. **Контейнерные имена** (явный NAS-signal): + - `modulair-rag`, `modulair-pipeline`, `lightrag-modulair`, `tier1-converter`, `modulair-mcp`, `synology-ops-mcp`, `synology-docker-proxy-ro` + +2. **Доменные слова Synology:** + - «на NAS», «Synology», «синолоджи», «Portainer-стек», «opsmcp.kzntsv.site», «ops-mcp», «опс мсп», «synology-ops» + +3. **Инцидент-фразы** (в NAS-контексте): + - «падает», «restart-loop», «не стартует», «unhealthy», «медленно грузится», «не видит соседа», «посмотри логи», «что с контейнером X» + +**Skip:** упоминание в неинцидент-контексте («modulair-rag deploy запланирован на завтра»), явный отказ («открой Portainer GUI»), инцидент-фразы для non-NAS хостов (`books-pipeline`, `vps-*` и т.д.). ## Inputs -<пусто> +- **Имя контейнера** (если есть) — для скоупинга `logs`/`inspect`/`stats` +- **Симптом** — «падает», «медленно грузится», «не видит соседа» — определяет starting tool +- **Scope** — «один контейнер» vs «весь стек» vs «все на NAS» ## Steps -<пусто> +**Флекс-паттерны — рекомендации, не жёсткий чек-лист.** + +| Сценарий | Старт-тап | Последовательность | +|----------|-----------|-------------------| +| «Контейнер X падает» | `ops.docker.ps({ name: "X", state: "all" })` → видит restart count | `logs({ name: "X", tail: 200, stream: "both" })` → если dependency error → `ps({ name: "" })` → если нет соседа → `inspect({ name: "X" })` | +| «Проверь стек целиком» | `ops.docker.ps({ state: "all" })` | Группировка по stack labels → если problem видны сразу — diagnosis, иначе → ask user | +| «Медленно грузится» | `ops.docker.stats({ name: "X" })` | Если CPU/Mem OK → `logs({ name: "X", since: "5m" })` на стартап-фазу | +| «Не видит соседа в сети» | `ops.docker.inspect({ name: "X" })` | Достать `NetworkSettings.Networks` → сверить с `inspect` соседа | + +**Формат отдачи юзеру:** + +1. **Диагноз** — одна строка («`modulair-pipeline` в restart-loop, ECONNREFUSED `postgres:5432`, контейнера `postgres` в сети `modulair` нет») +2. **Evidence** — 3-5 строк (релевантные логи / env / networks), hard cap 15 строк +3. **Гипотеза следующего шага** — 1-2 строки + +Юзер просит «покажи всё» → отдать всё, дефолт — выжимка. ## Failure modes -<пусто> +| Сценарий | Симптом | Действие | +|----------|---------|----------| +| Контейнер не существует | `ops.docker.logs` error «container not found» | Подсказать доступные: `ps({ state: "all" })` → список | +| Docker proxy недоступен | Timeout / connection refused | «synology-docker-proxy-ro unreachable — check stack health в Portainer» | +| 403 от docker-proxy | Попытка write-op (implicit) | «operation forbidden by tecnativa ACL — это read-only proxy, используй Portainer GUI для restart/exec» | +| Output > 1MB | Логи обрезаны | Вернуть первый MB + `truncated: true, actualBytes: N` | +| Bearer token невалидный | 401 на любой вызов | «check `~/.claude.json` → `mcpServers.synology-ops.headers.Authorization` соответствует ли токену в Portainer stack env» | ## Side effects -<пусто> +- **Latency** — HTTPS round-trip к NAS ~200ms, batch'ить вопросы, не дёргать в цикле +- **Capping** — `logs` cap 1MB, `tail` max 5000 строк — если нужно больше, ask +- **Маскирование** — env-vars с именами `/PASSWORD|TOKEN|SECRET|KEY|PASS|CREDS/i` заменены на `***` в `inspect` — regex может пропустить кастомные ключи, warning не certainty ## What NOT to do -<пусто> +**Common mistakes:** +- ❌ Звонить `logs` без явного `tail` (default 200, но явный = намеренный) +- ❌ Звонить `logs` для всех контейнеров подряд («покажи всё» — сначала `ps`) +- ❌ Интерпретировать `***` в env как «вижу пароль» — это masked, может быть кастомный ключ +- ❌ Пытаться write-ops (restart/exec/prune) через MCP — 403, направлять юзера в Portainer GUI +- ❌ Кэшировать `ps` long-term — состояние NAS меняется, перезвонить + +**Red flags:** +- 🔴 Дёргать в цикле — latency ~200ms через HTTPS, собрать вопросы в один batch +- 🔴 Проверять non-NAS контейнеры этим MCP (`books-pipeline`, `vps-*`) — они не видны synology-ops-mcp +- 🔴 Env-masked regex — не гарантия, могут быть кастомные ключи (`DB_URI`, `API_CREDENTIALS` и т.п.) diff --git a/skills/using-synology-ops/SKILL.md b/skills/using-synology-ops/SKILL.md index 4d8c0c9..abb8ab8 100644 --- a/skills/using-synology-ops/SKILL.md +++ b/skills/using-synology-ops/SKILL.md @@ -1,33 +1,79 @@ --- name: using-synology-ops -version: 0.1.1 +version: 0.1.2 description: Use when diagnosing docker containers on the Synology NAS — the `synology-ops` HTTP MCP server (https://opsmcp.kzntsv.site/mcp) exposes 4 read-only tools — `ops.docker.ps`, `ops.docker.logs`, `ops.docker.inspect`, `ops.docker.stats` — all routed through tecnativa `synology-docker-proxy-ro` with `POST=0` (write-ops return 403). Triggers on container names (`modulair-rag`, `modulair-pipeline`, `lightrag-modulair`, `tier1-converter`, `modulair-mcp`, `synology-ops-mcp`), on NAS-domain words ("на NAS", "Synology", "синолоджи", "Portainer-стек", "ops-mcp", "опс мсп", "opsmcp.kzntsv.site"), or on incident phrases ("падает", "restart-loop", "не стартует", "unhealthy", "посмотри логи") when NAS-context. Read-only by design — no per-session grant needed. Skip for non-incident mentions, "open Portainer GUI" requests, write-ops, and incident phrases on non-NAS hosts (`books-pipeline`, `vps-*` etc. — only the 6 listed above are NAS-hosted). --- # using-synology-ops -Trigger-and-guidance skill для `synology-ops-mcp` — read-only HTTP MCP-сервера на NAS, дающего Claude'у видимость состояния docker-контейнеров без юзера-моста (без Portainer copy-paste). Тело каркаса дописывается во втором проходе из `~/projects/.workshop/.archive/2026-05-12-using-synology-ops-skill.md` (process trace) и `~/projects/.wiki/concepts/synology-ops-mcp-design.md` (canonical design). +Trigger-and-guidance skill для `synology-ops-mcp` — read-only HTTP MCP-сервера на NAS, дающего Claude'у видимость состояния docker-контейнеров без юзера-моста (без Portainer copy-paste). ## When to use -<пусто — заполняется во втором проходе> +**Trigger — любой из трёх сигналов:** + +1. **Контейнерные имена** (явный NAS-signal): + - `modulair-rag`, `modulair-pipeline`, `lightrag-modulair`, `tier1-converter`, `modulair-mcp`, `synology-ops-mcp`, `synology-docker-proxy-ro` + +2. **Доменные слова Synology:** + - «на NAS», «Synology», «синолоджи», «Portainer-стек», «opsmcp.kzntsv.site», «ops-mcp», «опс мсп», «synology-ops» + +3. **Инцидент-фразы** (в NAS-контексте): + - «падает», «restart-loop», «не стартует», «unhealthy», «медленно грузится», «не видит соседа», «посмотри логи», «что с контейнером X» + +**Skip:** упоминание в неинцидент-контексте («modulair-rag deploy запланирован на завтра»), явный отказ («открой Portainer GUI»), инцидент-фразы для non-NAS хостов (`books-pipeline`, `vps-*` и т.д.). ## Inputs -<пусто> +- **Имя контейнера** (если есть) — для скоупинга `logs`/`inspect`/`stats` +- **Симптом** — «падает», «медленно грузится», «не видит соседа» — определяет starting tool +- **Scope** — «один контейнер» vs «весь стек» vs «все на NAS» ## Steps -<пусто> +**Флекс-паттерны — рекомендации, не жёсткий чек-лист.** + +| Сценарий | Старт-тап | Последовательность | +|----------|-----------|-------------------| +| «Контейнер X падает» | `ops.docker.ps({ name: "X", state: "all" })` → видит restart count | `logs({ name: "X", tail: 200, stream: "both" })` → если dependency error → `ps({ name: "" })` → если нет соседа → `inspect({ name: "X" })` | +| «Проверь стек целиком» | `ops.docker.ps({ state: "all" })` | Группировка по stack labels → если problem видны сразу — diagnosis, иначе → ask user | +| «Медленно грузится» | `ops.docker.stats({ name: "X" })` | Если CPU/Mem OK → `logs({ name: "X", since: "5m" })` на стартап-фазу | +| «Не видит соседа в сети» | `ops.docker.inspect({ name: "X" })` | Достать `NetworkSettings.Networks` → сверить с `inspect` соседа | + +**Формат отдачи юзеру:** + +1. **Диагноз** — одна строка («`modulair-pipeline` в restart-loop, ECONNREFUSED `postgres:5432`, контейнера `postgres` в сети `modulair` нет») +2. **Evidence** — 3-5 строк (релевантные логи / env / networks), hard cap 15 строк +3. **Гипотеза следующего шага** — 1-2 строки + +Юзер просит «покажи всё» → отдать всё, дефолт — выжимка. ## Failure modes -<пусто> +| Сценарий | Симптом | Действие | +|----------|---------|----------| +| Контейнер не существует | `ops.docker.logs` error «container not found» | Подсказать доступные: `ps({ state: "all" })` → список | +| Docker proxy недоступен | Timeout / connection refused | «synology-docker-proxy-ro unreachable — check stack health в Portainer» | +| 403 от docker-proxy | Попытка write-op (implicit) | «operation forbidden by tecnativa ACL — это read-only proxy, используй Portainer GUI для restart/exec» | +| Output > 1MB | Логи обрезаны | Вернуть первый MB + `truncated: true, actualBytes: N` | +| Bearer token невалидный | 401 на любой вызов | «check `~/.claude.json` → `mcpServers.synology-ops.headers.Authorization` соответствует ли токену в Portainer stack env» | ## Side effects -<пусто> +- **Latency** — HTTPS round-trip к NAS ~200ms, batch'ить вопросы, не дёргать в цикле +- **Capping** — `logs` cap 1MB, `tail` max 5000 строк — если нужно больше, ask +- **Маскирование** — env-vars с именами `/PASSWORD|TOKEN|SECRET|KEY|PASS|CREDS/i` заменены на `***` в `inspect` — regex может пропустить кастомные ключи, warning не certainty ## What NOT to do -<пусто> +**Common mistakes:** +- ❌ Звонить `logs` без явного `tail` (default 200, но явный = намеренный) +- ❌ Звонить `logs` для всех контейнеров подряд («покажи всё» — сначала `ps`) +- ❌ Интерпретировать `***` в env как «вижу пароль» — это masked, может быть кастомный ключ +- ❌ Пытаться write-ops (restart/exec/prune) через MCP — 403, направлять юзера в Portainer GUI +- ❌ Кэшировать `ps` long-term — состояние NAS меняется, перезвонить + +**Red flags:** +- 🔴 Дёргать в цикле — latency ~200ms через HTTPS, собрать вопросы в один batch +- 🔴 Проверять non-NAS контейнеры этим MCP (`books-pipeline`, `vps-*`) — они не видны synology-ops-mcp +- 🔴 Env-masked regex — не гарантия, могут быть кастомные ключи (`DB_URI`, `API_CREDENTIALS` и т.п.)