Skip to main content
Glama
README.md
# v8unpack-mcp

MCP-сервер (stdio) для полного цикла работы с бинарными файлами 1С
(`.cf` / `.cfe` / `.epf` / `.erf`) **без импорта в проект EDT**:

```
unpack → чтение/правка → repack → cleanup
```

Единственная точка распаковки — `unpack`. Все остальные инструменты принимают
`dir_path` — каталог, созданный `unpack`, и не выполняют неявной распаковки.

---

## Возможности

| Инструмент | Сигнатура | Что делает |
|---|---|---|
| `unpack` | `(file_path)` | полная распаковка в отдельный временный каталог (без лимита размера), возвращает путь |
| `unpack_async` | `(file_path)` | асинхронная распаковка: сразу `{job_id, status:"running"}`, результат — через `job_status` (не срывается таймаутом клиента на крупных файлах) |
| `repack_async` | `(dir_path, output_path)` | асинхронная сборка: сразу `{job_id, status:"running"}`, результат — через `job_status` |
| `job_status` | `(job_id)` | статус фонового задания `unpack_async`/`repack_async`: `status`/`progress`/`result`/`error` |
| `list_objects` | `(dir_path)` | список объектов внутри контейнера `{вид_объекта: [имена]}` (только имена) |
| `get_metadata` | `(dir_path, object_path="", detail=false)` | метаданные: вид, счётчики по типам, объект (uuid, синоним, формы, макеты, модули) |
| `read_module` | `(dir_path, object_path="", module_name="")` | исходник BSL-модуля объекта (защищённый помечает `encrypted`) |
| `read_bytecode` | `(dir_path, object_path="")` | разбор байт-кода закрытого модуля (методы, константы, опкоды) |
| `search_code` | `(dir_path, pattern, ...)` | поиск подстроки/regex по коду, формам, макетам (слои `layers`) |
| `set_help` | `(dir_path, object_path="", help_html="", overwrite=false)` | записать справку объекта в raw-слой (сборку делает `repack`) |
| `diff` | `(dir_a, dir_b, full=true)` | сравнение двух распакованных каталогов пообъектно + дифф |
| `repack` | `(dir_path, output_path)` | сборка файла из распакованного каталога |
| `cleanup` | `(dir_path=null, all=false)` | удалить каталог unpack (или все по префиксу) |

Поиск бинарников `.cf/.cfe/.epf/.erf` на диске — стандартными файловыми
инструментами клиента (glob/list).

### Рабочий цикл

1. `unpack(file_path)` → `{status, dir, file, kind}`. Каталог `dir` содержит:
   - **организованное дерево** (`Тип/Имя` + `.json` / `.obj.bsl` / формы / макеты) —
     чтение и правка кода, форм, макетов, реквизитов;
   - **raw-слой** `.v8unpack_raw/` (brace-файлы: `text`/`image`/help) — для
     `read_bytecode`/`set_help`.
2. Чтение — `list_objects` / `get_metadata` / `read_module` / `read_bytecode` / `search_code`;
   правка — файлами в `dir` (или `set_help`).
3. `repack(dir_path, output_path)` → `{status, output, bytes}`.
4. `cleanup(dir_path)` (или `cleanup(all=true)`).

Ошибки (нет файла/каталога, неверный тип) — исключениями. Каталог после `repack`
не удаляется автоматически — можно переиспользовать для нескольких сборок.

### Асинхронный режим для крупных файлов

`unpack`/`repack` ждут завершения работы синхронно — на больших `.cf` (сотни МБ–ГБ)
это может превысить таймаут MCP-клиента, и агент «сорвёт» запрос, хотя сервер продолжит
работать. Для таких случаев используйте асинхронные варианты — каждый вызов возвращается
мгновенно и не зависит от таймаута клиента:

1. `unpack_async(file_path)` → `{job_id, status:"running"}`;
2. повторять `job_status(job_id)`, пока `status != "done"` (промежуточные вызовы
   возвращают `progress` — число обработанных объектов);
3. при `status="done"` взять результат из поля `result` (тот же dict, что у `unpack`);
   при `status="error"` — сообщение в поле `error`.

Аналогично `repack_async(dir_path, output_path)` + `job_status`. Синхронные
`unpack`/`repack` сохранены для малых файлов и обратной совместимости.

### Схема `repack`

`repack` собирает через `v8unpack.build(use_raw=True)`:

- организованное дерево **не правилось** → raw-слой восстанавливается побайтно
  (сохраняются help, байт-код, шифрованные модули);
- организованное дерево **правилось** → пересборка из организованного дерева.

Ограничение (all-or-nothing): в одной сессии либо правки организованного слоя
(код/формы), либо raw-слоя (help/байт-код) — не оба сразу. Пообъектное слияние —
отдельная задача.

### Что ищется в `search_code`

- `.bsl` — исходники модулей;
- `.json` — заголовки объектов, реквизиты и дерево элементов форм;
- `.txt` / `.html` — текстовые и HTML-макеты;
- `.bin` (СКД) — схема компоновки данных: бинарный префикс + XML с текстом запроса.

Параметр `layers` ограничивает области поиска: `modules` (`.bsl`), `forms` (`.json`),
`templates_text` (`.txt`), `templates_html` (`.html`), `dcc` (`.bin`-СКД). Пусто = все.
Каждое совпадение содержит поле `layer`.

Не ищется (бинарное): `.mxl` (табличный документ), картинки, роли (`.c1brace`),
зашифрованные модули. Парсер MXL — отдельная research-задача (см. `.ai/`).

### Сравнение (`diff`)

`diff(dir_a, dir_b, full=true)` сравнивает два распакованных каталога пообъектно:

- перечисляет каталоги объектов (`Тип/Имя` для cf/cfe, корень для epf/erf);
- собирает файлы каждого объекта (без служебного `.id.json`);
- статусы: `changed` / `added` / `removed` / `unchanged`;
- для изменённых строится `unified diff`, обрезанный лимитами
  (MAX_DIFF_LINES=400, MAX_DIFF_FILES=20);
- `full=false` — только факт изменения, без построения диффа.

---

## Архитектура

- **Ядро распаковки** — [saby v8unpack](https://github.com/saby-integration/v8unpack)
  (Python, MIT). **Вендорено** в `src/v8unpack/` с локальными патчами
  (`keep_raw`/`use_raw`, `detect_format` для 8.3.24+, толерантность к неизвестным
  группам метаданных).
- **Своя обёртка** — `src/v8unpack_mcp`: `core.py` (логика), `textlayers.py`
  (извлечение текстовых слоёв), `server.py` (MCP-сервер).
- Распаковка — в отдельный временный каталог `%TEMP%\v8unpack_unpack_*` на каждый
  вызов `unpack`; общий кэш отсутствует (агент сам управляет жизненным циклом через
  `cleanup`).
- Для MCP отключаем multiprocessing v8unpack (серийный пул) и глушим stdout/stderr,
  чтобы не ломать stdio-протокол; `OrganizerFile.pack/unpack` пропускают `.v8unpack_raw`.

```
v8unpack-mcp/
├── src/
│   ├── v8unpack/            # вендоренное ядро saby v8unpack (MIT) + патчи
│   └── v8unpack_mcp/
│       ├── __init__.py
│       ├── __main__.py     # python -m v8unpack_mcp
│       ├── core.py         # инструменты: unpack/чтение/правка/repack/cleanup
│       ├── textlayers.py   # извлечение текстовых слоёв (поиск)
│       ├── bytecode.py     # чтение байт-кода закрытых модулей (из raw-слоя)
│       ├── decompiler.py   # декомпилятор байт-кода → BSL
│       ├── diffing.py      # сравнение распакованных каталогов
│       └── server.py       # MCP-сервер (stdio)
├── tests/
│   ├── test_core.py
│   └── test_server_e2e.py
└── pyproject.toml
```

---

## Установка и запуск

```bash
# MCP-сервер (вендоренное ядро v8unpack входит в пакет)
pip install -e .

# запуск (stdio)
python -m v8unpack_mcp
# или консольная команда
v8unpack-mcp
```

### Подключение к клиенту (MCP)

Сервер работает по **stdio**: каждый клиент сам запускает его отдельным процессом
по одной команде. Все инструменты принимают **абсолютные пути** к файлам, поэтому
рабочий каталог процесса не важен. Временные каталоги распаковки создаются в
системном `%TEMP%` с префиксом `v8unpack_unpack_`.

Рекомендуемая команда запуска — консольный скрипт `v8unpack-mcp` (создаётся при
`pip install`) либо `python -m v8unpack_mcp`. Для GUI-клиентов, которые не наследуют
ваш `PATH`, надёжнее указывать **абсолютный путь** к интерпретатору.

#### Стандартный формат MCP (`command` + `args`)

Claude Desktop, Claude Code, Cline, Continue, Roo, VS Code (`.mcp.json`) и другие
используют общий формат с полями `command` и `args`:

```json
{
  "mcpServers": {
    "v8unpack": {
      "command": "v8unpack-mcp",
      "args": []
    }
  }
}
```

Или с явным интерпретатором:

```json
{
  "mcpServers": {
    "v8unpack": {
      "command": "~/путь/к/python.exe",
      "args": ["-m", "v8unpack_mcp"]
    }
  }
}
```

Где разместить:
- **Claude Desktop** — `claude_desktop_config.json` (Настройки → Разработчик → Edit Config);
- **Claude Code** — `~/.claude.json` или проектный `.mcp.json`;
- **Cline / Continue / Roo** — проектный `.mcp.json` (шарится между участниками) или настройки пользователя;
- **VS Code** — `.vscode/mcp.json` (для сервера проекта) или пользовательские настройки.

#### Kilo Code / Kilo CLI (`kilo.json`, команда — массив)

Формат Kilo отличается: серверы задаются в `kilo.json` под ключом `"mcp"`, а команда
передаётся **одним массивом** (без разделения на `command`+`args`). Файл — проектный
`./kilo.json` / `.kilo/kilo.json` либо глобальный `~/.config/kilo/kilo.json`.

```jsonc
// kilo.json (проект)
{
  "mcp": {
    "v8unpack": {
      "type": "local",
      "command": ["v8unpack-mcp"],
      "enabled": true,
      "timeout": 15000
    }
  }
}
```

Или через `python -m`:

```jsonc
{
  "mcp": {
    "v8unpack": {
      "type": "local",
      "command": ["python", "-m", "v8unpack_mcp"],
      "enabled": true
    }
  }
}
```

Сервер включается/выключается в TUI командой `/mcps`. Унаследованный сервер можно
отключить: `{ "v8unpack": { "enabled": false } }`.

Права на инструменты сервера — по ключам `v8unpack_*` (glob, срабатывает последнее
совпадение сверху вниз):

```jsonc
{
  "permission": {
    "v8unpack_*": "allow"
  }
}
```

#### Рекомендации для нескольких клиентов

- **Установка**: один раз `pip install -e .` (для разработки) или
  `pip install dist/v8unpack_mcp-0.2.0-py3-none-any.whl` (из собранного колеса);
  зависимость `v8unpack` подтянется автоматически из `pyproject.toml`.
- **Единый интерпретатор**: используйте консольную команду `v8unpack-mcp` (попадает
  в `PATH` установки) либо один и тот же абсолютный путь к `python.exe` во всех
  конфигах — тогда любой клиент подхватит ту же установку.
- **Клиенты независимы**: каждый клиент держит свой stdio-процесс; общее состояние
  — только временные каталоги unpack на диске. Можно смело подключать один и тот же
  сервер к нескольким клиентам одновременно.
- **Пути с пробелами/кириллицей**: в JSON-конфигах пути заключайте в кавычки;
  в массиве `command` (Kilo) элементы экранируются автоматически.
- **Тихий запуск**: сервер глушит прогресс распаковки и работает только по stdio —
  интерактивный вывод в конфиги добавлять не нужно.

## Сборка

```bash
pip install build wheel          # инструменты сборки
python -m build                  # создаст dist/v8unpack_mcp-<ver>-py3-none-any.whl и .tar.gz
pip install dist/v8unpack_mcp-0.2.0-py3-none-any.whl   # установка из колеса
```

---

## Тесты

```bash
python tests/test_core.py          # юнит-смоук ядра
python tests/test_server_e2e.py    # end-to-end через stdio
```

Тесты используют файлы из `../testdata` (личные файлы, в git не входят — положите свои).

---

## Ограничения

- Большие `.cf` (сотни МБ — ГБ): `unpack` делает полный extract в отдельный каталог.
  Пообъектный индекс (чтение одного объекта без полного extract) — следующий шаг.
- Табличные макеты (`.mxl`) пока не ищутся — бинарный формат, парсер в TODO.
- Защищённые (зашифрованные) модули: исходник без пароля не восстановить, но
  `read_bytecode` разбирает компилированный байт-код, а `decompiler.py` умеет
  декомпилировать его в BSL (инструмент `decompile` — в планах).
- Правки организованного слоя и raw-слоя (help/байт-код) в одной сессии не сливаются
  (all-or-nothing `use_raw`).

## Заимствованные компоненты

Проект переиспользует открытые разработки сообщества:

| Компонент | Лицензия | Назначение | Ссылка |
|---|---|---|---|
| saby v8unpack | MIT (Copyright 2015 infactum) | ядро распаковки/сборки контейнеров 1С — **вендорено** в `src/v8unpack/` с патчами | https://github.com/saby-integration/v8unpack |
| EvilBeaver/v8asm | MIT | формат стека и таблица опкодов байт-кода 1С | https://github.com/EvilBeaver/v8asm |
| 1C-inversion | без явной лицензии (учебная, форк v8asm) | алгоритм декомпиляции байт-кода → BSL | https://github.com/ProhorP/1C-inversion |

`saby v8unpack` включён в состав пакета как `src/v8unpack/` (лицензия MIT сохранена в
`src/v8unpack/LICENSE`). `decompiler.py` — порт алгоритма 1C-inversion; `bytecode.py`
использует формат из v8asm.

⚠️ **Правовое замечание.** См. `DISCLAIMER.md` и `LICENSE`:

- Проект распространяется по лицензии MIT «как есть», без гарантий — использование
  **на свой риск**.
- Лицензия «1С:Предприятия 8» запрещает изменять код/данные продукта нештатными
  средствами, а также декомпилировать программную часть системы. Это ограничение
  защищает платформу и **типовые** конфигурации 1С; на **собственные** конфигурации,
  расширения и внешние обработки/отчёты оно не распространяется — работайте только
  со своими объектами.
- Декомпиляция закрытых (запароленных) модулей реализована в исследовательских
  целях и не должна применяться для взлома или снятия защиты чужих конфигураций
  (ст. 146 УК РФ). Используйте только для восстановления собственных модулей.

## Полезные ссылки

- saby v8unpack: https://github.com/saby-integration/v8unpack
- EvilBeaver/v8asm: https://github.com/EvilBeaver/v8asm
- 1C-inversion: https://github.com/ProhorP/1C-inversion
- Формат MXL8 (спека): https://github.com/azubar/SpreadSheet/blob/main/docs/format-mxl.md

TDQS

A3.7/5.0

Scored across 20 tools

Disambiguation5/5

Each tool targets a clearly distinct operation: unpack/repack lifecycle with async wrappers and job_status, object enumeration vs metadata, module source vs structure vs bytecode, help/template/DCS read/write variants, search, diff, and cleanup. Even read_dcs and export_dcs are differentiated by granularity (structured exploration vs full platform XML export). No two tools appear to perform the same job.

Naming Consistency4/5

Most tools follow a verb_noun snake_case pattern (list_objects, get_metadata, read_module, import_template, export_dcs), and async variants consistently use the <verb>_async suffix. Minor deviations include bare verbs like unpack, repack, diff, cleanup, the noun-style job_status, and an arbitrary read/get split among extraction tools. Overall the naming is still predictable and readable.

Tool Count4/5

At 20 tools, the server is on the upper boundary for tool count, but the 1C unpack/repack domain is complex enough to justify dedicated tools for async operations, module analysis, bytecode, help, templates, DCS, diff, and cleanup. A few closely related tools (read_dcs/export_dcs) could potentially be merged, but none feel like filler.

Completeness4/5

The toolset covers the full lifecycle: unpack (sync/async), inspection (list, metadata, modules, bytecode, search), modification (help, template, DCS imports into raw layer), repack (sync/async), diff, and cleanup. Minor gaps exist—no direct tool for writing arbitrary module code or forms—but editing the unpacked directory externally and repacking is a viable workaround.

Maintenance

ActivityMaintained
ResponsivenessNo issues