docs: спек упаковки в плагин Claude Code и публикации через Gitea
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
# Спек: упаковка kompas3d-mcp в плагин Claude Code и публикация через Gitea
|
||||
|
||||
Дата: 2026-07-31 · Статус: согласовано, к реализации
|
||||
|
||||
## 1. Цель
|
||||
|
||||
Сделать так, чтобы возможности этого проекта (MCP-сервер КОМПАС-3D + методические навыки)
|
||||
устанавливались в чужой Claude Code одной командой, а не воспроизведением ручной настройки:
|
||||
клонировать репозиторий, собрать `.NET`, прописать абсолютный путь в `.mcp.json`, скопировать навыки.
|
||||
|
||||
Аудитория — автор и узкий круг знакомых, с прицелом на возможную публичность. Отсюда: структура и
|
||||
README сразу рассчитаны на постороннего, но вылизанный онбординг (мастера установки, автодиагностика
|
||||
всех отказов) в объём не входит.
|
||||
|
||||
**Вне объёма этой спеки:** сценарий выполнения задач в репозитории (рабочий цикл доработки MCP) —
|
||||
прорабатывается отдельно и с нуля; `docs/superpowers/NEXT-SESSION.md` пока остаётся как есть.
|
||||
|
||||
## 2. Исходные факты (проверены)
|
||||
|
||||
- `git.shahovalov.ru/mikhail/claude-plugins` **редиректит** на `home-repo-cc` — репозиторий
|
||||
переименован. Каталог плагинов = `home-repo-cc` (`.claude-plugin/marketplace.json`, плагин
|
||||
`obsidian-autodoc`).
|
||||
- `home-repo-cc` — **приватный** (Gitea API отдаёт 404 без токена). `kompas3d-mcp` — **публичный**,
|
||||
релизы включены.
|
||||
- Marketplace поддерживает source-тип **`git-subdir`** (`{url, path, ref?, sha?}`, разрежённый клон) —
|
||||
плагин может физически жить в подкаталоге другого репозитория.
|
||||
- Плагин объявляет MCP-серверы через `.mcp.json` в своём корне; в путях доступна переменная
|
||||
`${CLAUDE_PLUGIN_ROOT}`. Плагин копируется в кеш `~/.claude/plugins/cache` при установке.
|
||||
- `.agents/skills/` в этом репозитории — побайтово идентичная копия `.claude/skills/` (untracked):
|
||||
дублирование навыков между харнессами уже началось вручную.
|
||||
- Сервер: `net8.0-windows`, x64, вендорские interop-DLL АСКОН в `libs/kompas-interop` (4.4 МБ,
|
||||
в репозитории). Ни WinForms, ни WPF не используются.
|
||||
|
||||
## 3. Принятые решения
|
||||
|
||||
| Вопрос | Решение |
|
||||
| --- | --- |
|
||||
| Аудитория | автор + знакомые; структура «как для чужого», публичность — потом |
|
||||
| Источник бинаря | готовый `win-x64` из Gitea Release, собирается CI |
|
||||
| Состав плагина | навыки `kompas-3d`, `kompas-fdm-design`; команда `/kompas:doctor`; MCP-сервер |
|
||||
| Каталог | остаётся приватным `home-repo-cc`, доступ знакомым выдаётся в Gitea |
|
||||
| Раскладка | плагин лежит в `kompas3d-mcp/plugin/`, каталог ссылается через `git-subdir` |
|
||||
| Имя плагина | `kompas` |
|
||||
|
||||
`kompas`, а не `kompas-3d`: пространство имён даёт `/kompas:doctor`, навыки становятся
|
||||
`kompas:kompas-3d` / `kompas:kompas-fdm-design`, и это совпадает с именем MCP-сервера (`mcp__kompas__*`).
|
||||
|
||||
Субагент `kompas-sdk-research` и база `docs/Kompas3D_SDK/` (14 МБ, 2466 файлов) **в плагин не входят** —
|
||||
это инструмент разработки сервера, а не построения деталей.
|
||||
|
||||
## 4. Раскладка
|
||||
|
||||
```
|
||||
kompas3d-mcp/
|
||||
plugin/ ← весь плагин, единственный источник истины навыков
|
||||
.claude-plugin/plugin.json
|
||||
skills/kompas-3d/SKILL.md
|
||||
skills/kompas-fdm-design/{SKILL.md,references/}
|
||||
commands/doctor.md → /kompas:doctor
|
||||
.mcp.json
|
||||
scripts/launch-kompas-mcp.ps1
|
||||
server.lock.json
|
||||
README.md
|
||||
adapters/{codex,opencode}/
|
||||
tools/sync-agent-assets.ps1
|
||||
.gitea/workflows/{ci.yml,release.yml}
|
||||
```
|
||||
|
||||
`plugin/.claude-plugin/plugin.json`: `name: "kompas"`, `displayName`, `description`, `version`
|
||||
(семвер, поднимается релизным коммитом), `author`, `homepage`, `repository`, `license`, `keywords`.
|
||||
|
||||
## 5. Источник истины навыков
|
||||
|
||||
Навыки хранятся **только** в `plugin/skills/`. `tools/sync-agent-assets.ps1` создаёт на них junction'ы
|
||||
из `.claude/skills/<name>` и `.agents/skills/<name>` (на Windows junction создаётся без прав
|
||||
администратора); если junction создать не удалось — копирует и печатает предупреждение. Обе целевые
|
||||
папки добавляются в `.gitignore`, прежние копии удаляются из индекса.
|
||||
|
||||
Смысл: сегодняшний дрейф между `.claude` и `.agents` устраняется структурно. Для локальной работы в
|
||||
этом репозитории плагин **не устанавливается** — иначе навыки задвоятся (плагинная копия + junction).
|
||||
|
||||
## 6. Лаунчер и версионирование сервера
|
||||
|
||||
`plugin/server.lock.json` — пин ровно одной версии:
|
||||
|
||||
```json
|
||||
{ "version": "1.0.0",
|
||||
"url": "https://git.shahovalov.ru/mikhail/kompas3d-mcp/releases/download/v1.0.0/kompas-mcp-1.0.0-win-x64.zip",
|
||||
"sha256": "…" }
|
||||
```
|
||||
|
||||
`plugin/.mcp.json`:
|
||||
|
||||
```json
|
||||
{ "mcpServers": { "kompas": {
|
||||
"command": "powershell",
|
||||
"args": ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File",
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/launch-kompas-mcp.ps1"] } } }
|
||||
```
|
||||
|
||||
Алгоритм `launch-kompas-mcp.ps1`:
|
||||
|
||||
1. Задан `KOMPAS_MCP_EXE` → использовать его (цикл разработки: локальная сборка вместо релиза).
|
||||
2. Иначе целевой путь `%LOCALAPPDATA%\kompas-mcp\<version>\kompas-mcp.exe`; существует → запуск.
|
||||
3. Отсутствует → скачать ассет во временный каталог, посчитать SHA256; **несовпадение — отказ с
|
||||
ненулевым кодом, скачанный файл не запускается**; распаковать во временный каталог и атомарно
|
||||
переименовать в целевой (устойчиво к параллельному старту двух сессий).
|
||||
4. `& $exe @args`; stdio наследуется дочерним процессом; код возврата пробрасывается.
|
||||
|
||||
**Инвариант:** скрипт не пишет в stdout ни байта (stdout — канал JSON-RPC). Всё — в stderr;
|
||||
`Write-Host` запрещён.
|
||||
|
||||
Публикуется **self-contained win-x64**: другу не нужен установленный .NET 8 Runtime, требуется только
|
||||
КОМПАС. Цена — ~70 МБ на ассет. Старые версии остаются в кеше рядом — откат сводится к правке
|
||||
`server.lock.json`.
|
||||
|
||||
## 7. Команда `/kompas:doctor`
|
||||
|
||||
Командный промт (`plugin/commands/doctor.md`), проводящий агента по проверкам с конкретным действием
|
||||
на каждый отказ:
|
||||
|
||||
1. `server.lock.json` — какая версия ожидается;
|
||||
2. наличие `%LOCALAPPDATA%\kompas-mcp\<version>\kompas-mcp.exe` (и `KOMPAS_MCP_EXE`, если задан);
|
||||
3. запущен ли процесс КОМПАС;
|
||||
4. отвечает ли инструмент `kompas_status`;
|
||||
5. итоговый отчёт.
|
||||
|
||||
## 8. CI (Gitea Actions в `kompas3d-mcp`)
|
||||
|
||||
**`ci.yml`** — push/PR в `main`: `dotnet build -c Release` + `dotnet test --filter Category=Unit`.
|
||||
|
||||
**Интеграционные тесты в CI не выполняются никогда** — им нужен запущенный КОМПАС с GUI и лицензией.
|
||||
Это граница, а не задача на будущее; фиксируется в README и в workflow комментарием.
|
||||
|
||||
**`release.yml`** — на тег `v*`:
|
||||
|
||||
1. `dotnet publish -c Release -r win-x64 --self-contained` → zip → sha256;
|
||||
2. создание релиза и загрузка ассета через Gitea API (`curl` + `secrets.GITEA_TOKEN`);
|
||||
3. бот-коммит в `main` с пометкой `[skip ci]`: обновить `plugin/server.lock.json`
|
||||
(version/url/sha256) и `version` в `plugin/.claude-plugin/plugin.json`.
|
||||
|
||||
Требования к раннеру (готовится в отдельной сессии «LXC для Gitea runner»): .NET 8 SDK, доступ к
|
||||
nuget.org, `curl` и `git`, токен Gitea с правами на релизы и запись в репозиторий. Если раннер
|
||||
Linux — сборка с `-p:EnableWindowsTargeting=true` (ожидается, что проект соберётся: WinForms/WPF не
|
||||
используются; **подлежит проверке первым же прогоном**, при неудаче — Windows-раннер).
|
||||
|
||||
## 9. Каталог и установка
|
||||
|
||||
В `home-repo-cc/.claude-plugin/marketplace.json` добавляется одна запись, один раз:
|
||||
|
||||
```json
|
||||
{ "name": "kompas",
|
||||
"source": { "source": "git-subdir",
|
||||
"url": "https://git.shahovalov.ru/mikhail/kompas3d-mcp.git",
|
||||
"path": "plugin", "ref": "main" },
|
||||
"description": "КОМПАС-3D через MCP: построение деталей, сборки, чертежи, STEP",
|
||||
"category": "cad" }
|
||||
```
|
||||
|
||||
`ref: main`, а не тег: версия для Claude Code берётся из `plugin.json.version`, поднятого релизным
|
||||
коммитом, поэтому обновления доезжают через `/plugin marketplace update` сами и каталог руками больше
|
||||
не правится. Каталог приватный, плагин тянется из публичного репозитория — знакомому нужен доступ
|
||||
только к каталогу.
|
||||
|
||||
Путь пользователя: доступ в Gitea → `/plugin marketplace add https://git.shahovalov.ru/mikhail/home-repo-cc.git`
|
||||
→ `/plugin install kompas@home-repo-cc` → `/kompas:doctor`.
|
||||
|
||||
Предпосылки в `plugin/README.md`: Windows x64; установленный и **запущенный** КОМПАС-3D (проверено на
|
||||
v24 Home); работа только на одной машине с КОМПАС (сервер — COM-клиент, не автономный CAD-движок).
|
||||
|
||||
## 10. Задел под Codex и opencode
|
||||
|
||||
Ни Codex, ни opencode не знают ни `${CLAUDE_PLUGIN_ROOT}`, ни маркетплейсов: для них модель —
|
||||
клон репозитория и абсолютный путь. Задел выражается не декларацией, а тем, что контент не копируется:
|
||||
|
||||
- `adapters/codex/config.snippet.toml` — `[mcp_servers.kompas]` через тот же лаунчер + README:
|
||||
куда вставлять (`~/.codex/config.toml`), навыки берутся из `.agents/skills` (создаёт sync-скрипт);
|
||||
- `adapters/opencode/opencode.json` — фрагмент local-MCP + README;
|
||||
- лаунчер параметризуется только `server.lock.json`, навыки лежат в одном месте — новый харнесс стоит
|
||||
README и сниппета, а не форка контента.
|
||||
|
||||
Граница явная: это сниппеты и инструкция, а не дистрибутивы. Полноценные плагины Codex/opencode —
|
||||
отдельная веха, когда у них стабилизируется формат пакета.
|
||||
|
||||
## 11. Риски и открытые вопросы
|
||||
|
||||
- **Приватный каталог** требует у знакомого аккаунта в Gitea и настроенного git-credential-helper;
|
||||
что Claude Code корректно клонирует приватный marketplace по https — проверить на живом человеке.
|
||||
- **Скачивание исполняемого файла** закрыто sha256-пином в репозитории; при несовпадении — отказ.
|
||||
- **Лицензионный статус interop-DLL АСКОН** при публичности плагина и self-contained-сборки —
|
||||
открытый вопрос, требует отдельного решения до выхода за круг знакомых.
|
||||
- **Рекурсия CI**: бот-коммит релиза помечается `[skip ci]`; проверить, что раннер это уважает.
|
||||
- **Сборка `net8.0-windows` на Linux-раннере** — ожидаемо работает с `EnableWindowsTargeting`,
|
||||
но не проверена.
|
||||
- **Расход диска**: каждая версия сервера ~70 МБ в `%LOCALAPPDATA%`; очистка старых версий — вручную.
|
||||
|
||||
## 12. Критерии приёмки
|
||||
|
||||
1. `tools/sync-agent-assets.ps1` отрабатывает на чистом клоне: навыки видны и в Claude Code, и в
|
||||
`.agents/skills`, при этом файлы физически существуют в одном месте.
|
||||
2. Тег `v*` даёт релиз в Gitea с ассетом и обновлённые `server.lock.json` / `plugin.json` в `main`.
|
||||
3. На машине без предустановленного сервера: `/plugin install kompas@home-repo-cc` → первый запуск
|
||||
скачивает бинарь, `/kompas:doctor` зелёный.
|
||||
4. Порча sha256 в `server.lock.json` приводит к отказу запуска с внятным сообщением в stderr.
|
||||
5. Ручная проверка канала: лаунчер получает `initialize` на stdin и отдаёт корректный JSON-RPC-ответ,
|
||||
в stdout нет посторонних строк.
|
||||
6. По playbook'у навыка `kompas:kompas-3d` строится деталь на свежей установке.
|
||||
Reference in New Issue
Block a user