# dkc-ramcube — MCP-сервер: каталог ДКС + проект RamCube

Локальный MCP-сервер (stdio) для проектирования НКУ на оборудовании ДКС.

**Скачать без доступа к GitBucket:** https://ailabscrume.ru/downloads/dkc-ramcube.zip
(архив пересобирается автоматически при каждом пуше в `main`.)

Связывает две вещи, которые до этого приходилось сводить руками:

1. **каталог ДКС** — база `DKC_data.mdf` из установки RAMcube (30 096 позиций,
   параметры, цены, габариты, 3D-геометрия);
2. **проект RamCube** — XML-файл проекта: чтение состава и габарита, замена
   аппаратов, параметры проекта.

Разбор PDF-схемы (перечень аппаратов с листа) в эту версию **не входит** — перечень
готовится отдельно, сервер работает с каталогом и XML (см. «Известные ограничения»).

Сервер ничего не делает «за программу»: компоновку, панели и выгрузку документов
считает сам RamCube. Задача сервера — подготовить и проверить вход (схему) и
прочитать результат (габарит, панели).

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

| Инструмент | Что делает |
|---|---|
| `dkc_search` | поиск аппаратов по артикулу и номинальному току; возвращает deviceId, In, Icu, число полюсов, исполнение, габарит, семейство |
| `dkc_device` | полные параметры позиции по `deviceId` (это же значение стоит в XML как `elementDevice`) |
| `ramcube_project_read` | сводка проекта: параметры, аппараты схемы с кодами и позициями, панели, длина ряда (всего / полезные / служебные) |
| `ramcube_apparatus_replace` | замена аппаратов: правит `elementDevice`, 3D-модель и **оба** набора свойств, затем сам перечитывает файл и отдаёт проверку |
| `ramcube_set_project` | параметры проекта: имя, IP, секционирование (3b/4b), подвод кабелей (сверху/снизу), Iном, Iкз, наличие АВР |

### Почему замена аппарата — не «поменять один атрибут»

В XML проекта RamCube свойства аппарата лежат **в двух местах**:

- эталон элемента — `propertyValueInstance` = атрибут `elementInstance` самого
  `<element>` (порядка 25 значений);
- набор каждого размещённого экземпляра — `propertyValueInstance` =
  `elementInstanceInstance` (порядка 67 значений).

Если поправить только `elementDevice`, программа при загрузке выдаёт
«Ошибки в проекте: … не соответствует … [device:…]» и в спецификации остаётся
старый код. Инструмент правит оба набора и возвращает `verified_instances` —
фактические значения после записи.

## Требования

- Windows (нужны LocalDB и установленный RAMcube с базой каталога);
- Python 3.12 (в `.venv`);
- доступ к базе каталога: копия `DKC_data.mdf`, подключённая к LocalDB
  (см. «Подготовка базы»).

## Установка

```powershell
git clone <repo> dkc-ramcube
cd dkc-ramcube
uv venv --python 3.12 .venv
uv pip install --python .venv\Scripts\python.exe -r requirements.txt
```

`requirements.txt`:

```
mcp<2
pyodbc==5.1.0
```

Версии принципиальны:

- `mcp<2` — в mcp 2.x `FastMCP` переименован в `MCPServer`, код сервера написан под 1.x;
- `pyodbc==5.1.0` — в 5.5.0 не загружается legacy-драйвер `{SQL Server}`
  (ошибка «Не найден SQLSRV32.dll»).

## Подготовка базы каталога

1. Взять `RamcubeV3\DKC_data.mdf` и `DKC_data_log.ldf` из установки RAMcube
   (`C:\Program Files (x86)\DKC\RAMcube V4.4.0`). Оригинал не трогать — работать
   с копией.
2. Подключить копию к LocalDB, например как `DKC_cat_ro_v44`:

   ```powershell
   SqlLocalDB.exe start MSSQLLocalDB
   sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE DATABASE DKC_cat_ro_v44 ON (FILENAME='C:\ramcube_db\DKC_cat_ro.mdf'),(FILENAME='C:\ramcube_db\DKC_cat_ro_log.ldf') FOR ATTACH"
   ```

3. Проверить: `SELECT COUNT(*) FROM tblDevices` → 30 096.

## Подключение к Hermes

```powershell
hermes -p ai-si config set mcp_servers.dkc-ramcube.command "C:/path/to/dkc-ramcube/.venv/Scripts/python.exe"
hermes -p ai-si config set mcp_servers.dkc-ramcube.args '["C:/path/to/dkc-ramcube/server.py"]'
hermes -p ai-si config set mcp_servers.dkc-ramcube.enabled true
hermes -p ai-si mcp test dkc-ramcube
```

Инструменты появляются в новой сессии Hermes.

## Переменные окружения

| Переменная | Назначение | По умолчанию |
|---|---|---|
| `DKC_CONN` | готовая строка подключения; перебивает LocalDB | — |
| `DKC_DB` | имя базы каталога | `DKC_cat_ro_v44` |
| `DKC_LOCALDB` | путь к `SqlLocalDB.exe` | автопоиск старшей версии |
| `DKC_LOCALDB_INSTANCE` | имя инстанса | `MSSQLLocalDB` |

## Примеры

Поиск аппарата на 4000 А:

```json
{"query": "NW40", "in_min": 3000}
```

→ `ACB NW40`, `device_id: 11919`, `in_a: 4000`, `icu_ka: "100"`, `W - выкатной`,
габарит 441×441×421, семейство `NW32-NW40`.

Замена вводных в проекте:

```json
{"xml_in": "vrsh1.xml", "xml_out": "vrsh1_new.xml",
 "replacements": [{"element_id": "-174426", "new_device_id": 11919}]}
```

Вместо `element_id` можно указать `element_device` — тогда заменятся все элементы
с этим `deviceId`.

Чтение габарита после компоновки:

```json
{"xml_path": "vrsh1_new.xml"}
```

→ `length_mm: {total: 7054, useful: 4217, service: 2837}`, то есть полезные панели
отдельно от шинных опусков и кабельных отсеков, которые RamCube добавляет сам.

## Модель данных (что читается из базы)

- `tblDevices` — позиции каталога (`deviceId`, `Code`);
- `tblDeviceValues` + `tblDeviceParameters` — параметры позиции: `2` In,
  `3` In расцепителя, `8` Icu, `9` Код, `10` полюса, `11` производитель,
  `12` тип по каталогу, `43` исполнение;
- `tblDrawingUnits` — габариты (`unitBoundMinX…MaxZ`) и монтажные поля.

Замечание: `deviceValueContent` имеет тип `sql_variant`, который pyodbc не читает
(ODBC type −150) — в запросах обязателен `CAST(... AS nvarchar(400))`.

## Известные ограничения

- **Новый щит «с нуля» не генерируется.** В базе пусты `tblElements`,
  `tblElementComponents`, `tblElementConnectors`: компоненты и монтажные точки
  создаёт само приложение при вставке аппарата из «Репозитория». Эталонный блок
  берётся из проекта, куда аппарат вставлен штатно.
- **Замена надёжна внутри семейства**, где совпадают компоненты и модель
  (пример: NW08…NW40 — одна линейка моделей, габарит в базе у всех 441×441×421).
  Смена на чужое семейство даёт «Отсутствуют монтажные точки».
- **Компоновка и выгрузка документов — в GUI RamCube**, сервер их не запускает.
- **PDF-разбор схемы** в этой версии не входит: перечень аппаратов готовится
  отдельно, сервер работает с каталогом и XML.

## Структура репозитория

```
server.py        — MCP-сервер (stdlib + pyodbc + mcp)
test_client.py   — проверка: список инструментов и вызовы на копии проекта
requirements.txt — фиксированные версии зависимостей
README.md        — это описание
```

## Проверка после установки

```powershell
.venv\Scripts\python.exe test_client.py
```

Ожидаемо: 5 инструментов, `dkc_search` отдаёт позиции, `ramcube_apparatus_replace`
возвращает `verified_instances` с новым кодом и номиналом.
