--- name: kompas-3d description: > Методика работы с КОМПАС-3D через MCP-сервер плагина: построение и модификация деталей, импорт/экспорт STEP, работа со сборками, осмотр геометрии снимками и запросами. Используй ВСЕГДА, когда задача — что-то СДЕЛАТЬ в КОМПАС через MCP-инструменты (создать/править деталь, импортировать STEP, разобрать сборку, померить, отрендерить, экспортировать). Здесь — playbook'и и эвристики, проверенные на практике. Триггеры: «построй деталь в КОМПАС», «импортируй STEP», «что в этой сборке», «нарасти/измени деталь», «экспортируй STEP», «сделай снимок модели». --- # kompas-3d — методика управления КОМПАС-3D через MCP MCP-сервер даёт **общие** операции КОМПАС (эскизы, формообразующие, осмотр, обмен), этот навык — **методику**: в каком порядке их применять, как выбирать геометрию, чем проверять результат и какие подводные камни обходить. Коротко: **MCP = чем делать, навык = как делать.** Подробности вызова — варианты операций, обязательные поля, типы примитивов эскиза и их параметры — живут в описаниях самих инструментов: контракт сервера подробен, читай его, а не восстанавливай по памяти. ## Когда применять Любая задача «сделать что-то В КОМПАС» через MCP: создать/править деталь, эскизы и операции, импорт/экспорт обменных форматов, разбор сборки, измерения, снимки. ## Два правила прежде всего **1. «Зрение» — структурное, не по картинке.** «Увидеть» деталь = **`describe_model`** — паспорт одним запросом и ЕДИНСТВЕННЫЙ инструмент осмотра: разделы `box | mass | bodies | topology | tree | variables | errors | components` (`sections` сужает и ответ, и объём чтения модели). Углубляться — `list_faces(index=N)` / `list_edges` (отбор `type` + координатное окно — им адресуют то, что не выбрать по одному: весь нижний контур под фаску) / `measure`. **`model_snapshot` бери только** для визуально-пространственных вопросов, на которые паспорт не отвечает (общая форма, ориентация, правдоподобность, «куда смотрит грань»): снимок дорог по контексту и менее точен, чем числа. **1а. Осмотр НЕ перестраивает документ.** Если модель правили снаружи (человек в GUI, соседний агент) или операция запросила перестроение, `describe_model` покажет числа ДО правки — и ответ будет выглядеть безупречным: размеры новые, положения старые, сопряжения валидны. Такой ответ сам скажет «Документ ТРЕБУЕТ ПЕРЕСТРОЕНИЯ» (`needsRebuild: true`); увидел — `rebuild` и повтори осмотр, выводов по непересчитанной модели не делай. **2. Ответ мутирующей операции — это ТРИ проверки, читай все.** Любая операция может «пройти» (`Create()==true`), оставив деталь в ошибке, поэтому каждая мутирующая операция сама дописывает к ответу итог проверки построения и сводку состояния «Тел: N, объём V мм³»: - **«⚠ N операц. в ошибке»** (напр. `et3dError54`) — деталь невалидна: не продолжай и не экспортируй, исправь или переделай другим методом. «Построение чистое» = порядок. Строки с «ℹ» — не отказы: «требуется перестроение» лечится `rebuild`, а «не определено положение (N)» означает, что компоненту не хватает сопряжений или фиксации. Бросать из-за них исправную сборку не нужно; в обеих названы имя и индекс компонента. - **«Тел: 2»** там, где ждёшь одно тело, — деталь распалась: касание объединением не считается (см. «Надписи»). Смотри на число ТЕЛ, а не граней: объединение сливает компланарные грани, и счётчик граней законно остаётся прежним. - **Объём сверяй с прикидкой** «площадь контура × высота». Так ловятся молча не применившаяся тонкая стенка (прирост как у сплошного сечения), вычитание мимо цели и операция «не туда» — габарит и снимок этого не покажут. Отдельный `describe_model(sections=errors,bodies,mass)` после каждого шага не нужен. Он возвращается, когда авто-проверку выключили (`set_auto_validate(false)` на тяжёлой модели, где проверка каждого шага тормозит): тогда `describe_model(sections=errors,bodies,mass)` вручную перед выдачей: одного `errors` мало — распад детали на два тела показывает только раздел `bodies`. ## Справочник сервера: `help` Подробности инструментов — маршруты, порядок вызовов, ловушки — лежат в самом сервере и достаются по требованию, а не занимают контекст заранее: - `help()` — оглавление тем (дёшево, одна строка на тему); - `help(topic="…")` — статья целиком; - `help(query="…")` — поиск словами с цитатами; - `help(tool="extrude")` — что известно про конкретный инструмент. **Зови его, когда инструмент повёл себя не так, как ты ожидал, и когда тема названа в тексте ошибки.** Ссылки вида `help(topic="…")` по этому файлу — не украшение: там лежит то, что здесь намеренно не повторяется. Справочник описывает ЭТОТ сервер; справка по COM API КОМПАС — отдельная история и в работе через MCP не нужна. ## Инструменты: индекс групп Актуальный перечень с описаниями параметров отдаёт сам MCP-сервер — здесь только карта: - *Система/документы:* `kompas_connect` (shared|private|attach), `kompas_set_visible`, `kompas_status`, `set_auto_validate`, `set_operation_log`; `document_create|open|save|close`, `document_active` (тип, путь, есть ли несохранённые изменения, «только чтение», материал детали), `document_list` (все открытые документы — им проверяют, что имя файла занято другим документом и что несохранённого не осталось), `set_part_info`, `set_part_material`. - *Эскиз:* `sketch_create` (основание: `plane`+`offset` | `faceIndex` | точка; геометрия — списком `entities` **или** файлом `entitiesFile`), `sketch_add`, `sketch_close`; `measure_text` — замер надписи без построения; `fragment_create` — тот же список примитивов, но в самостоятельный файл-фрагмент (*.frw); `fragment_place` — положить готовый фрагмент в чертёж. - *Формообразующие:* `primitive`, `extrude`, `revolve`, `fillet_edge`, `chamfer_edge`, `shell`, `rib`, `sweep`, `loft`, `draft`, `hole`, `pattern`, `mirror`, `feature_delete`, `rebuild`. - *Прямое редактирование (в т.ч. импортированная B-rep):* `move_face`, `split_solid_by_plane`, `move_body`, `boolean_union`. - *Переменные:* `set_variable`, `list_parameters`, `link_parameter`, `delete_variable` (сами переменные показывает `describe_model(sections=variables)`). - *Обмен:* `import_model` (3D: step, iges, sat, xt, stl, c3d, jt, obj + родные форматы чужих САПР), `import_drawing` (плоский .dxf/.dwg), `export_model` (`format=auto` по расширению: `.step` — точная геометрия в другую САПР, `.stl` — сетка в слайсер). - *Исполнения:* `embodiment` (`set|add|delete|rename`; `kind=embodiment|mirror|variant`) — несколько геометрий одной модели в одном файле; список с габаритом и массой каждого — `describe_model(sections=embodiments)`. - *Сборка:* `assembly_add_component` (положение + поворот `rx/ry/rz`, `embodiment` — какое исполнение источника вставлять), `assembly_add_mate` (стороной может быть грань ИЛИ вспомогательный объект `object1/object2`: плоскости и оси СК компонента, а без `componentIndex` — самой сборки) (семь типов, `orientation`), `assembly_fix_component`, `assembly_delete`, `assembly_check_interference` (не налезли ли детали друг на друга — больше это не видно нигде), `assembly_transform_point` (`to=world|local` — точка между ЛСК компонента и СК сборки). - *2D-чертёж:* `drawing_create_standard_views` (`views[]`, `mainOrientation`, `hiddenLines`), `drawing_add_view` / `drawing_move_view` / `drawing_delete_view` / `drawing_get_view_info` (компоновка листа и паспорт вида), `drawing_add_section_view` (РАЗРЕЗ или СЕЧЕНИЕ: линия разреза на базовом виде и производный вид по ней — одним вызовом), `drawing_add_sheet`, `drawing_set_sheet_format`, `drawing_fill_title_block`, `drawing_add_linear|diametral|radial|angular_dimension` (у всех — `tolerance`/`prefix`/`suffix`/ `textOverride`; у Ø и R — ещё `objectKind`/`objectIndex`, прямой адрес окружности или дуги), `drawing_add_axis`, `drawing_add_rough|text|leader`, `drawing_set_unspecified_rough`, `drawing_set_technical_requirements`, `drawing_delete_object`, `drawing_move_object` (сдвинуть поставленное), `drawing_project_point` (точка модели → координаты вида), `drawing_export_image` (посмотреть глазами). Обратное чтение — `drawing_get_title_block` и `drawing_get_technical_requirements`: технические требования ПЕРЕЗАПИСЫВАЮТСЯ целиком, поэтому правку одного пункта начинают с чтения текущего текста. Методика — §«Чертёж». - *Осмотр:* `describe_model` (разделы `box|mass|bodies|topology|tree|variables|errors|components|mates` — габарит, МЦХ, тела, топология, дерево построения, переменные, операции в ошибке, состав сборки, сопряжения), `measure`, `model_snapshot`; адресация объектов — `list_faces` / `list_edges`. Для 2D-документов — свой: `list_drawing_objects` (что лежит в чертеже/фрагменте). Три сквозных свойства контракта: **размерный параметр принимает число ИЛИ выражение** (имя переменной/формулу — параметр сразу становится ведомым); **объект выбирается индексом** (надёжно) или точкой (запасной путь — если выбирал точкой, ответ подскажет, что выбралось); **списковые параметры** (`entities[]`, `edgeIndices[]`, `points[]`, `faceIndices[]`, `variables[]`, `links[]`) — весь пакет одним вызовом: прямоугольник с четырьмя отверстиями — ОДИН `sketch_create`, скругление восьми рёбер — ОДИН `fillet_edge`, крепёжная картина из шести отверстий — ОДИН `hole(points=[…])`, наращивание двух торцов — ОДИН `move_face(faceIndices=[…])`; каждый лишний вызов — лишний шанс сбиться. Пакет НЕ транзакционен: отказ называет позицию элемента в списке, а сделанное до него остаётся — повторяй вызов с оставшимися, а не с начала. Если инструмента под задачу нет — собирай результат из имеющихся общих операций. ## Два пути формообразования — выбирай по форме, а не по привычке «Эскиз → выдавливание» — не единственный способ. `primitive` строит тело сразу по размерам, и это короче и надёжнее там, где форма призматическая: | Форма | Чем строить | |---|---| | Плита, брусок, бобышка, штифт, цилиндрическая стойка | `primitive(kind=block\|cylinder)` — один вызов вместо «эскиз + выдавливание» | | Прямоугольный карман, паз, срез угла | `primitive(..., result=subtract)` — вычитание тела вместо `extrude(mode=cut)` по эскизу | | Скруглённые углы призмы | `primitive` + `fillet_edge` по рёбрам (скругление после, а не дуги в эскизе) | | Текст, кривые, произвольный контур, переменное сечение | ТОЛЬКО эскиз: `sketch_create(entities=[…])` + `extrude`/`revolve`/`loft`/`sweep` | | Тонкая стенка, ободок по контуру | эскиз + `extrude(thinThickness, thinSide)` | Их **сочетают в одной детали**: корпусные объёмы — примитивами, сложные контуры — эскизами. - **Ось цилиндра и конуса задаётся параметром, а не системой координат детали:** `primitive(kind="cylinder", axis="X"|"Y"|"Z")`. Точка `x,y,z` остаётся центром основания в мировых координатах, высота растёт вдоль выбранной оси. Не перепроектируй деталь ради того, чтобы её ось совпала с Z (у `block` и `sphere` параметра нет: у блока ось задают размеры `length/width/height`, у сферы оси нет). - **Тонкую стенку по сложному контуру строй ДО того, как появится тело, которое она пересечёт.** `extrude(thinThickness=…)` по многоконтурному эскизу (надпись — десяток замкнутых контуров с «дырками») отказывает, если стенка пересекает уже построенное тело; простой прямоугольный контур проходит и с пересечением. Ошибка сервера называет причину, но порядок планируй заранее: на шильдике «плашка → буквы → кайма» падает, а «буквы → кайма → плашка `primitive(union)` → карман `primitive(subtract)`» проходит — примитивам пересечение безразлично. - **Скругления делай, пока рёбер мало** — сразу после примитивов их видно в `list_edges` наперечёт. Если рёбер уже сотни, бери их ПО ТОЧКАМ: `fillet_edge(radius, points=[…])` по углам известных координат — одна операция на все; точки без ребра ошибка перечислит разом. - **Скругление не построится там, где ребро «съедено» соседним элементом** (угол плашки под каймой букв). Это нормальный ответ геометрии, а не ошибка вызова: проверь снимком, виден ли угол снаружи. - **`result=new` даёт ОТДЕЛЬНОЕ тело**, `subtract` мимо цели сервер ловит сам — и то и другое видно по сводке «Тел/объём» в ответе; при распаде зови `boolean_union`. ## Базовый цикл (эскиз → операция → осмотр) Опорный сценарий построения, проверен end-to-end: 1. `kompas_connect` (+ `kompas_set_visible true`). **Работаешь не один — бери свой экземпляр:** `kompas_connect(instance="private")` (см. «Когда КОМПАС общий»). 2. `document_create(type="part", name="…")` — наименование даём сразу, здесь оно ничего не стоит. 3. **Запиши замысел переменными** до первого эскиза (см. «Параметризация») и связывай каждый размер, взятый из паспорта, при построении — иначе переменная останется числом в списке. 4. `sketch_create(plane="XOY", entities=[…])` — весь контур одним вызовом. 5. `extrude` / `revolve` → прочитай итог проверки и сводку прямо в ответе (правило 2). 6. Осмотр — структурно: `describe_model` (нужен кусок — `sections="box,mass"`). 7. Итерация «на грани»: `list_faces` → `sketch_create(faceIndex=N, entities=[…])` → операция. 8. **Задай материал, если смотришь на массу** — `set_part_material`: у нового документа стоит сталь 7.86, и МЦХ печатной детали завышена вшестеро; плотности ходовых материалов перечислены в описании инструмента. 9. **Проверь, что деталь названа** (шаг 2 или `set_part_info`) — безликая «Деталь» уедет в штамп чертежа и спецификацию; имя файла при сохранении этого не заменяет. **Называй каждую операцию** — `name` есть у всех: «Контур плашки», «Рельеф букв OldMan», «Карман под площадку». Дерево из «Эскиз:1, Элемент выдавливания:3» нечитаемо ни человеку, ни тебе самому через сотню вызовов. ## Параметризация: сначала переменные, потом геометрия **В новом документе первым делом опиши будущую модель переменными — до первого эскиза.** Пока деталь пуста, компоновка стоит одного вызова на размер; после десятка операций та же мысль стоит пересборки. Набор переменных — это план построения числами и паспорт, по которому человек поймёт модель, не разбирая дерево. - **Заводи переменной то, что было РЕШЕНИЕМ**: габариты из ТЗ, толщины, зазоры, отступы, кегли, радиусы. Выводимое задавай формулой (`plate_L = badge_L - 2*edge_gap`) — правка ведущего размера пересчитает зависимые сама. Позиции, подобранные замером, оставляй числами: связь — обещание, что правка переменной даст осмысленный результат, а на позиционных числах она чаще ломает деталь. - **Размер передавай выражением прямо в операцию** (`extrude(depth="badge_T")`) — параметр сразу становится ведомым, внутреннее имя параметра («Расстояние 1») знать не нужно. Переменная должна существовать ДО операции — потому паспорт и заводят первым. Задним числом и для параметров, которых нет среди аргументов инструмента (углы уклона, второе направление), — `link_parameter`. - **Промахи сервер ловит сам:** ссылка на несуществующее имя — отказ с перечнем виновных (и в выражениях операций, и в `set_variable`; регистр значим), функции в формулах — предупреждение (тригонометрия в радианах, разделитель аргументов «;», непонятая запись = молчаливый 0). Твоя часть — **сверить вычисленные значения из ответа со своей прикидкой**. - **`note` обязателен** и пишется по-русски, со смыслом и единицей; `(ТЗ)` метит числа, зафиксированные пользователем. **Что замерил — верни в переменную** (фактический кегль, прирост каймы), иначе паспорт разойдётся с моделью и станет дезинформацией. Переосмысливать можно всё, кроме помеченного `(ТЗ)`. - **После связывания правка паспорта перестраивает деталь** (проверено: `set_variable(badge_T=4)` → габарит по Z 3.00 → 4.00, объём 5154.5 → 5861.5 мм³). Это и есть параметрическая модель, а не комментарий к ней. **До связывания — не перестраивает**, и `set_variable` говорит об этом прямо: «⚠ НИЧЕГО НЕ ВЕДЁТ». Такой ответ — не успех: число поменялось, деталь нет. - **Сверка и уборка в конце:** `describe_model(sections=variables)` помечает «⚠ ничего не ведёт» — это либо забытая связь, либо мусор; разбери оба. `delete_variable(unused=true)` — только ПОСЛЕ `link_parameter` на всё, что должно вести геометрию: вычистка не отличает мусор от несвязанного размера из ТЗ. ## Надписи, логотипы и рельеф Надпись — примитив `type=text` в эскизе; все поля (шрифт, кегль, `widthFactor`, выравнивание `align`/`vAlign`) описаны в схеме `entities`. Она сразу переводится в кривые, поэтому выдавливается как обычный контур: гравировка — `extrude(mode="cut")`, выпуклые буквы — `mode="boss"`. - **Ответ даёт габарит ГЛИФОВ и ширину ячейки — позиционируй по глифам.** Ячейка шире на 1–2 % у наборных шрифтов (Zilla Slab, Bevan) и на 7–9 % у скриптовых (Lobster, Pacifico). - **Кегль калибруй `measure_text`** — он ничего не строит. Пробу, которую всё же пришлось построить, убирает `feature_delete`; отдельный черновой документ для этого не нужен. - **`height` — высота ПРОПИСНОЙ, а не габарит строки** (Zilla Slab, height=10: «HH» → 9.97 мм, «Hy» → 13.24 мм, выносной уходит на −3.27) — закладывай выносные отдельно. Прочие тонкости полей (`widthFactor`, `align`, `vAlign`) — `help(topic="sketch-text")`. - **Подложка под надпись — тем же эскизом тонкой стенкой:** один хендл эскиза можно передать в несколько операций — сплошное выдавливание на высоту подложки + `extrude(thinThickness, thinSide="outward")` дают силуэт с равномерной каймой. Стенку проверяй по объёму из сводки: не применившаяся толщина молча даёт сплошное сечение при том же габарите. - **Надпись и плашка обязаны ПЕРЕКРЫВАТЬСЯ** — по размерам чертежа блоки обычно только касаются, а касание объединением не считается. Приём: кайму/полосу плашки сделать выше самой плашки на 1–1.5 мм с той стороны, где стоит надпись. Распад видно по «Тел: 2» в ответе операции — не тяни проверку до конца построения. - **Рельеф = разница глубин от одной плоскости** (основание 2 мм + буквы 3 мм = выступ 1 мм); не строй буквы «на грани основания» — из одного эскиза на базовой плоскости получается и то и другое, и рельеф не зависит от порядка операций. - **Шрифт должен быть установлен в системе** — неизвестное имя КОМПАС молча подменяет; сервер предупреждает об этом в ответе `sketch_create`/`measure_text` — не игнорируй. **Логотип, которого нет в шрифте, приходит готовым вектором (SVG).** Переводи его в примитивы эскиза сам — `line` и `arc3points`, а не ломаной: контур из сотен звеньев даёт деталь в сотни граней, и фаска по такому низу не строится. Кубические Безье режь пополам, пока дуга по трём точкам не ляжет в допуск. Четыре вещи, каждая из которых стоила захода: - **Ось Y в SVG смотрит вниз** — без инверсии контур встаёт вверх ногами, и это видно только на снимке. - **Дуги задавай тремя точками** (`arc3points`): концы заданы явно, соседние примитивы стыкуются точно. Перед постройкой проверь цепочку — конец примитива против начала следующего, разрыв 0. - **Чисти мелочь под масштаб детали — параметром `minSegment`.** SVG рисуют в своём габарите (сотня условных единиц), и его скругления после масштабирования превращаются в дуги по 0.02–0.5 мм; замыкающий `z` часто даёт ещё и сегмент нулевой длины. `chamfer_edge` по такому набору отвечает «катет больше длины N из M рёбер» — и это правда. Передай `sketch_create(minSegment=катет)` (тот же параметр есть у `sketch_update` и `fragment_create`), и та же фаска пройдёт с первой попытки; отчёт о выброшенном читай, а не пролистывай — `help(topic="contour-cleanup")`. **Порядок для фаски по контуру логотипа — только такой, и он неочевиден:** 1. **чистка** порогом ≈ будущего катета (`minSegment`); 2. **замер ЧИЩЕНОГО силуэта** — `sketch_measure_thickness(entitiesFile, minSegment=тот же порог)`; 3. **катет по узкому месту** чищеного силуэта: `c ≤ (узкое_место − 2·w)/2`, где `w` — ширина нити. Менять шаги местами нельзя: **чистка СУЖАЕТ узкое место**. Она заменяет скругление острым углом — в выпуклом углу это добавляет материал (габарит подрастает), а в вогнутом срезает его, и именно вогнутые углы образуют перемычки между штрихами. Замер обводки логотипа шириной 105 мм: узкое место 1.98 → 1.82 мм, порог распада лицевой грани 0.99 → 0.91. Катет, подобранный по нечищеному контуру, после чистки перестаёт проходить свой же критерий. - **Ширину штриха и узкое место меряй инструментом, а не глазом** — `sketch_measure_thickness` ничего не строит и документа не требует, поэтому зовётся ДО эскиза (`help(topic="silhouette-thickness")`). От этих чисел зависит, останется ли что-то от рисунка после фаски и напечатается ли он вообще; шаг растра в ответе — точность округления катета. Контур, который переживёт конкретную деталь (логотип, шаблон, профиль), клади во фрагмент — `fragment_create(path, entities)` тем же списком примитивов. Активный документ он не подменяет, поэтому фрагмент можно снять посреди построения детали; габарит в ответе снят с самого документа — сверяй его с задуманным. **Точная подгонка и отделка — в [reference/text-and-relief.md](reference/text-and-relief.md); прочитай его, как только доходишь до точной компоновки надписи или отделки рельефа:** подбор кегля под заданную ширину за одну пробу, ступени `widthFactor`/`height`, приросты каймы на острых терминалах (t/sin(θ/2)) и её роль в стыковке блоков, разрядка пробелами, кайма вокруг прямоугольной плашки, карманы `primitive(subtract)` рядом с буквами, скругления и фаски рельефа на сотнях рёбер. ## Внешний контур: не диктуй координаты, если фигуру нельзя описать формулой Три маршрута, и выбор между ними механический — не по вкусу, а по происхождению геометрии. | Откуда фигура | Чем строить | |---|---| | **Вычисляется**: пластины, рёбра, сетка отверстий | `sketch_create(entities[])` — прямо в вызове, размеры вяжи переменными | | **Срисована**: логотип, шаблон, кулачок, профиль | внешний вектор → JSON → `sketch_create(entitiesFile=…)` | | **Пришла в CAD-формате**: файл от смежника | `import_drawing` (.dxf/.dwg) → фрагмент → `fragment_place` | **Обводка занимает сотни примитивов, и переписывать их в тело вызова незачем.** У `sketch_create`, `sketch_add` и `fragment_create` есть `entitiesFile` — путь к JSON того же формата, что `entities`; сервер читает файл сам. Замер на эмблеме Volvo: SVG в 1.5 КБ даёт 96 примитивов (50 отрезков + 46 дуг) и 9.5 КБ JSON; через `entitiesFile` это один вызов на одну строку аргументов, а эскиз строится за один заход. Оба параметра можно задать вместе — сначала `entities`, следом файл: так к готовому контуру дописывают рамку или ось, не трогая файл. Что проверить **до** постройки, а не после: габарит в ответе (`fragment_create` печатает фактический — сверь с задуманным) и вложенные контуры. Правил заливки у эскиза КОМПАС нет: любой вложенный контур он режет как отверстие, даже там, где вектор заливал материал. Конвертер такие места называет заранее — на них смотри до выдавливания, иначе дыры обнаружатся на снимке. ## Фрагмент — переиспользуемый чертёж, а не сечение Эскиз живёт внутри дерева построения и вне его не существует; фрагмент (*.frw) — самостоятельный файл, который переживает деталь. `fragment_create` его пишет, `fragment_place` кладёт в активный чертёж или другой фрагмент, а `mode` решает, чем он там станет — и это разные объекты, а не оттенки одного: - **`reference`** — вставка-ссылка: содержимым владеет файл, правка файла меняет все документы, куда он вставлен. Ради этого фрагменты и заводят: одна заготовка на десять чертежей. - **`copy`** — копия внутри документа, живёт своей жизнью; файл потом можно удалить. - **`local`** — вставка, переиспользуемая только внутри этого документа. - **`explode`** — россыпь обычных примитивов: правится по одному, но связи с файлом уже нет. `angle` (градусы), `scale` и `mirror` задают размещение; зеркалить можно только вставку — у россыпи отражать нечего. **Зеркало отражает относительно вертикали через точку вставки**, поэтому контур уходит в другую сторону от неё: вставка в x=220 после `mirror` занимает 160…220, а не 220…280. Проверять результат — `list_drawing_objects`: он показывает состав по типам, габарит и все вставки с их файлами. Вставка, чей файл потерялся, рисуется пустым местом — в списке она помечена недействительной, и это единственный способ отличить её от удавшейся, не глядя на экран. ## Сборка: собрать своё Плейбук: **создать → вставить → ЗАФИКСИРОВАТЬ базовую → сопрячь → rebuild → проверить.** Разбор чужой сборки — следующий раздел, здесь про сборку с нуля. 1. **Детали сначала сохрани в файлы.** Компонент вставляется ссылкой на `.m3d`/`.a3d`, поэтому несохранённую деталь вставить нельзя. 2. **`document_create assembly` → `assembly_add_component(filePath, x, y, z, rx, ry, rz)`.** Углы — в градусах, вокруг СОБСТВЕННЫХ осей компонента и по очереди X→Y→Z: второй угол считается уже от повёрнутого положения. Пока задан один угол, разницы с мировыми осями нет. 3. **Зафиксируй базовую деталь СРАЗУ: `assembly_fix_component(componentIndex=0, fixedState=true)`.** КОМПАС не закрепляет никого сам, включая первый компонент, и решатель двигает того, кого сочтёт нужным — в том числе основание, вокруг которого ты собираешь всё остальное. Это самая частая причина «сопряжение верное, а сборка расползлась». 4. **Сопрягай:** `assembly_add_mate(mateType, …)` — семь типов, адресация гранью и смысл `orientation` в `help(topic="assembly-mates")`. Что решаешь ты, а не справочник: - **Грань адресуй индексом, а не координатами:** `list_faces(component=N)` → пара `faceIndex`+`componentIndex`. Точки на бумаге считать не нужно, и сервер сам проверит, что грань принадлежит этому компоненту. - **Сторону зазора у `distance` задаёт ВЫБОР ПАРЫ ГРАНЕЙ, и от стартового положения она не зависит.** «Closest» — не «ближайшее»: при сонаправленных нормалях объект 1 садится со стороны −n относительно объекта 2 (замерено двойным прогоном). Практическое правило: бери пару граней, которые смотрят ДРУГ НА ДРУГА. Вышло зеркально — меняй грань, а не `orientation`. - **Первое сопряжение вешай на зафиксированную деталь.** Пока в цепочке нет ни одного закреплённого звена, решатель волен двигать любое; связка «каждый новый компонент — к уже стоящему на месте» разваливается вдвое реже, чем связка «все ко всем». 5. **`rebuild`,** если авто-валидация написала «ℹ Требуется перестроение». Это НЕ ошибка построения: так помечает себя свежий компонент или только что наложенная связь. Бросать работу здесь не надо — правило «не продолжай при ⚠» касается строки со знаком ⚠, а не этой. **Исключение из правила «⚠ = стоп».** После КАЖДОГО сопряжения авто-валидация пишет «⚠ N операц. в ошибке: „Сопряжения“ (код 0: ошибки нет)». Это то же «требуется перестроение», только под знаком ⚠: код 0 и имя операции «Сопряжения» означают, что ломаться нечему. Делай `rebuild` и иди дальше. Настоящая беда со связью видна не здесь, а в `describe_model(sections=mates)` — по пометке `valid:false`. 6. **Проверь:** - `describe_model(sections=components)` — origin, поворот ЧИСЛАМИ (`rx/ry/rz` в градусах, та же семантика, что у вставки) и «зафиксирован/свободен» у каждого: этим и видно, КОГО и НА СКОЛЬКО подвинул решатель; - `describe_model(sections=mates)` — что с чем связано, с каким значением и не выродилось ли. Это ключевой детектор: `assembly_add_mate` может ответить успехом, а связь окажется вырожденной; - `measure(kind1=face, index1=…, componentIndex1=…, kind2=face, index2=…, componentIndex2=…)` — зазор между деталями напрямую, без арифметики по габаритам; - `assembly_check_interference(componentIndex1, componentIndex2)` — **не налезли ли детали друг на друга.** Проверяй все пары, которые должны идти впритирку. **Неудачную связь не нужно пересобирать с нуля:** `assembly_delete(target="mate"|"component", index)` снимает сопряжение или компонент вместе с опирающимися на него связями. Индексы после удаления сдвигаются — иди от больших к меньшим и перечитывай `describe_model(sections=mates)`. **Пересечение деталей не видно НИГДЕ, кроме `assembly_check_interference`.** Сборка складывается из готовых тел, и КОМПАС их не вычитает: две детали могут занимать общий объём, а сопряжения при этом останутся `valid`, раздел `errors` — пустым, объём экспорта — простой суммой компонентов. `measure` тоже не спасает: нулевой зазор одинаково означает и касание, и взаимопроникновение. Проверяй все пары, которые должны идти впритирку. **«Тела: 0» в сборке означает не «пусто», а «спрошено не то»:** тела принадлежат компонентам (`describe_model(component=N, …)`), а `box` и `mass` без `component` честно дают габарит и МЦХ сборки целиком. Про разные системы координат внутри паспорта компонента — `help(topic="model-inspection")`; про локальные координаты граней и `pointOnFace` — `help(topic="face-addressing")`. ## Чертёж: оформить деталь по ГОСТ Чертёж строится не так, как деталь: **авто-валидации здесь нет**. Правило трёх проверок из §«Базовый цикл» в 2D не работает — операция не отчитывается «построилось верно», потому что верность тут не про геометрию, а про место на листе. Проверять приходится самому, и способ ровно один: посмотреть. **Порядок, который окупается:** 1. **Деталь строится в чертёжной ориентации.** Набор видов задаётся ОТ модели: `mainOrientation` выбирает, какую ориентацию модели показывает главный вид, но саму ориентацию модели он не вращает. Если самая информативная проекция детали — не одна из шести стандартных, чертежа по ГОСТ не выйдет; планируешь чертёж — строй эскизы так, чтобы главный вид попадал на плоскость с наибольшей информацией. 2. **`drawing_set_sheet_format`** (формат до видов — иначе виды придётся двигать), при необходимости `drawing_add_sheet` для второго листа. 3. **`drawing_create_standard_views(views=[…], mainOrientation=…, hiddenLines=…)`** — бери ровно те проекции, которые нужны: лишний вид — лишнее место и лишний повод ошибиться видом. **Главный вид входит в набор сам**: перечисленные коды — это проекции ОТНОСИТЕЛЬНО него, поэтому `views=["top"]` даёт ДВА вида (главный и сверху). Ответ возвращает НОМЕРА видов, и дальше всё адресуется ими. 4. **Координаты — замером, а не формулой.** `drawing_get_view_info(viewNumber)` отдаёт паспорт вида одним вызовом: положение на листе, масштаб, габарит и — главное — локальную СК: куда попадает начало координат модели и куда смотрят её оси +X/+Y/+Z в координатах вида (нулевой орт = ось проекции, вдоль неё вид смотрит). Этого хватает, чтобы пересчитывать точки модели в вид арифметикой; отдельные точки переводит `drawing_project_point(x, y, z, viewNumber)`. Выводить оси из головы не надо и вредно: у КОМПАС «спереди» показывает плоскость XY детали, а «сверху» — X и **минус Z**, и **знаки инверсии зависят от `mainOrientation`** — формула, выведенная на одном чертеже, на соседнем врёт. 5. **Разрез — до размеров, а не после.** Внутреннюю геометрию (зенковка, ступенчатое отверстие, паз, глубокая расточка, полость) показывай разрезом, а не невидимыми линиями: по штриховой линии нельзя ни поставить нормальный размер, ни разобрать форму. `drawing_add_section_view` — см. §«Разрез» ниже. Размеры внутренней геометрии ставятся УЖЕ НА РАЗРЕЗЕ, поэтому строить его надо раньше простановки, иначе размеры придётся переносить. 6. **Размеры**, `drawing_add_axis` (осевые и центровые), шероховатость, выноски, техтребования, штамп. **Осевые сначала посмотри, потом добивай**: ассоциативные виды приходят со СВОИМИ центровыми и осевыми, которые КОМПАС ставит сам, и `drawing_add_axis` вслепую даёт дубли поверх существующих. Сначала `list_drawing_objects(kind="axis"|"centreMarker", viewNumber=…)`. 7. **`drawing_export_image`** — посмотреть глазами. Пока картинки не было, чертёж не сдан. ### Разрез `drawing_add_section_view` делает всё сразу: проводит линию разреза на базовом виде и строит по ней производный вид со штриховкой. Механика, ступенчатый разрез и встроенная проверка честности — `help(topic="drawing-sections")`; здесь только решения, которые принимаешь ты: - **Разрез или `hiddenLines`.** Разрез — когда внутреннее нужно ИЗМЕРИТЬ или показать форму: зенковка и цековка, ступенчатое или резьбовое отверстие, паз, канавка, глубокая расточка, тонкая стенка полой детали. Невидимые линии — только намёк на то, что уже показано где-то ещё; размер к штриховой линии не привязывают. - **Веди линию с запасом за габарит** (плита 60 мм → от −40 до +40): линия по самому краю режет не всю деталь. Координаты — в ЛСК БАЗОВОГО вида, её даёт `drawing_get_view_info`. - **Строй разрез, когда модель готова**: после правки детали перестраивается только ПЕРВЫЙ разрез базового вида. Модель всё же изменилась — снеси разрезы и построй заново. - Сам разрез дальше — обычный вид: размеры и обозначения ставятся на него по его номеру. **Промах простановки лечится, а не остаётся навсегда.** Отката (undo) у чертежа нет, но `list_drawing_objects` показывает обозначения с индексами, `drawing_delete_object` убирает одно, а `drawing_move_object` его СДВИГАЕТ — слипшиеся тексты соседних размеров лечат именно сдвигом, а не заменой размера на выноску. Так же правится и компоновка: `drawing_move_view` переставляет вид со всеми обозначениями, `drawing_add_view` доносит недостающую проекцию, `drawing_delete_view` убирает лишнюю. Пересоздавать документ ради компоновки не нужно. Подробности адресации и порядок удаления — `help(topic="drawing-fixing")`. **Три вещи, на которых чертёж молча выходит неверным** — держи их в голове, детали в справочнике: - `viewNumber=0` — это НЕ главный вид, а координаты ЛИСТА; знак, поставленный «на главном виде» с нулём, уезжает за границы формата (`help(topic="drawing-views")`); - ассоциативны только диаметральный и радиальный размеры; линейный и угловой меряют координаты, и «60» останется, когда деталь станет 70 — после правки модели перепроверяй их сам (`help(topic="drawing-dimensions")`); - допуск, не легший в размер, виден только по пустому read-back в ответе — техтребования его не заменят (`help(topic="drawing-dimension-text")`). Ещё две ловушки, о которых узнаёшь только столкнувшись: штамп частично ведёт МОДЕЛЬ, а не чертёж (`help(topic="drawing-title-block")`), и у цилиндрической грани нет «координат оси» — её восстанавливают и проверяют сходимостью площадей (`help(topic="cylinder-axis")`). **Чего нет.** Выносного элемента (увеличенный фрагмент), МЕСТНОГО разреза внутри вида, местного вида и вида с разрывом. Ассоциативного ЛИНЕЙНОГО размера нет и не будет: в API у него нет привязки к геометрии ни под каким именем (проверено QI, поздним связыванием и размером с обрывом). Экспорта в PDF/DXF тоже нет — наружу уходит растр (`drawing_export_image`) и STEP. ## Работа с импортом / сборками Конвейер «импорт → разбор → извлечение детали → осмотр → модификация → экспорт»: 1. **`import_model`** — `type` задаёт документ: `assembly` (по умолчанию) или `part`. Формат берётся из расширения; `.prt` и `.asm` носят несколько САПР сразу — там задавай `format` явно. Нужна отдельная деталь файлом — включай `createComponentFiles`: без него импорт не пишет на диск ничего, кроме открытого документа. Плоский чертёж (.dxf/.dwg) читает не он, а `import_drawing`. 2. **Разбор:** `describe_model(sections=components)` (у каждого компонента — origin, поворот, фиксация) и `describe_model(sections=mates)`, если сборка пришла со связями; грани компонента — `list_faces(component=N)`. Извлечённую деталь открывай самостоятельным документом. Гашение видимости компонента на снимок **не влияет** — изоляция так не делается. 3. **Осмотр — структурно** (`describe_model`: какая ось «высота», МЦХ, топология). Снимок `model_snapshot(view=…)` — ракурс выбирай по плоскости детали (плоскую смотри сверху или спереди, не в изометрии); один и тот же `view` даёт воспроизводимый кадр «до/после». **Пары ракурсов противоположны по оси:** `front` смотрит из +Z, `rear` — из −Z, так же `top`/`bottom` и `left`/`right`. Следствие, которое нужно чаще всего: деталь, лежащая на столе гранью Z=0 (эскиз на XOY, выдавливание вперёд), видна столу как **`rear`**, а `front` покажет зеркальную картинку. Читаемость надписи или логотипа доказывают снимком с нужной стороны, а не рассуждением. 4. **Модификация «тупой» B-rep** (итог — в ответе каждой операции): простой случай — `move_face`; вставка N мм в призматическую ножку — `split_solid_by_plane` → `move_body` → `move_face` (мост) → `boolean_union` (шаги пронумерованы в описаниях самих инструментов; цепочка проверена end-to-end: проставка 39.45 → 41.45 мм, построение чистое). 5. **Перед выдачей:** последняя операция «Построение чистое» → `export_model` (STEP для обмена, STL для печати). ## Исполнения: одна модель — несколько геометрий Типоразмеры (профиль на 100, 200, 500 мм), правое и левое зеркало, версии с отверстием и без часто живут **в одном файле** исполнениями. Тогда всё, что ты меришь и экспортируешь, относится к **текущему** исполнению — не к «детали вообще». - **Признак замечаешь не ты, а ответ.** У модели с несколькими исполнениями `describe_model` сам пишет, сколько их и какое сейчас текущее. Увидел эту строку — прежде чем считать массу или резать чертёж, посмотри `describe_model(sections=embodiments)`: там габарит и масса **каждого**, и это чтение ничего не переключает. - **Переключение равно смене документа.** `embodiment(action="set", target="L200")` обнуляет сессию построения: хендлы `sk_…`/`op_…` после него мертвы. Сохраняй документ до переключения. - **Индекс живёт до первой правки дерева**: после `delete` индексы смещаются. Адресуй обозначением («L500»), а индексом — только сразу после того, как увидел список. - **Строишь новое исполнение** — `embodiment(action="add", number="02")`; оно сразу становится текущим, строй в нём немедленно. `depended=false` нужен, когда правки НЕ должны наследоваться от родителя, — иначе изменение уедет и в него. - **В сборку исполнение выбирается явно**: `assembly_add_component(embodiment="L500")`. Без параметра встанет **базовое** исполнение, а не то, что сохранено в файле текущим. Обозначение нужно ПОЛНОЕ («ПРОБА.001-01», а не «-01»); сервер откажет, если КОМПАС подсунет базовое. - **«Удлинить эти профили с 500 до 600» — это смена исполнения экземпляра, а не новая вставка**: `embodiment(action="set", target="L600", component=N)` и затем `rebuild`. Сопряжения при этом **сохраняются** — пересоздание вставки, наоборот, порвало бы их все. Какие исполнения есть у конкретного экземпляра, показывает `describe_model(sections="embodiments", component=N)`. - **Выгнать всю линейку на печать** — `export_model(embodiment="all")`: каждое исполнение в свой файл с суффиксом обозначения. - **После смены исполнения в собранном узле проверь сопряжения** (`sections="mates"`): если у нового исполнения нет объекта, на который опиралась связь, она рвётся — «ССЫЛКА ПОТЕРЯНА», `valid: false`, компонент недоопределён. Что было потеряно, хранит имя сопряжения; `assembly_delete` сотрёт и его. Подробности и границы — `help(topic="embodiments")`. ## Эвристики и подводные камни - **Правила 1 и 2 действуют всегда:** осмотр структурный; «⚠ N операц. в ошибке» — в STEP/печать не брать. - **Направление операции** (`extrude(forward)`, знак `distance` у `move_face`): на выбранной грани зависит от ориентации её нормали — реши ДО построения, прочитав нормаль в `list_faces(index=N)` (или по снимку), а после сверь сводку объёма в ответе. - **Эскизы и операции адресуются ХЕНДЛАМИ из ответов** — `sk_7c1e5aa3f1_1_2`, `op_7c1e5aa3f1_1_5`. Не сочиняй их и не передавай числа: числовая адресация не поддерживается, а сервер объяснит формат отказом. Хендл живёт только в текущей сессии построения: смена активного документа (create/open/close) и перезапуск сервера делают прежние хендлы **мёртвыми**, и они отказывают с указанием причины — не молча, как раньше делали числовые id. Потерял хендл — читай `describe_model(sections=tree)` и строй заново; сохраняйся перед долгими паузами. Хендл — это НЕ индекс: `faceIndex`/`edgeIndices` из `list_faces`/`list_edges` и параметр `feature` у `link_parameter`/`list_parameters` (имя или индекс узла дерева) остаются числовыми. `primitive` и `hole` тоже возвращают хендл (у `hole` — по одному на КАЖДОЕ отверстие серии), так что примитив и отверстие можно удалить `feature_delete` и размножить `pattern`/`mirror`. Если ответ вместо хендла говорит «выдать не удалось» — операция построена, но адресовать её нечем: переставить её потом можно только пересборкой. - **Единицы — мм** (геометрия) и **кг** (масса). Локальные координаты эскиза ≠ мировые координаты модели. - **Одинаковая ошибка у ВСЕХ инструментов — это транспорт, а не КОМПАС.** «Unable to connect…», таймаут или пустой ответ на `kompas_connect`, `kompas_status` и `describe_model` одновременно означают, что до MCP-сервера не дошёл ни один байт: перебирать инструменты и «пробовать ещё раз» бесполезно. Один-два подтверждающих вызова — и сдавай задачу как заблокированную, назвав, что именно не отвечает. Отдельный признак того же — сообщение без имени инструмента и без слова «КОМПАС»: наши ошибки всегда называют операцию и причину. ## Когда КОМПАС общий По умолчанию (`instance="shared"`) сервер работает в том же экземпляре КОМПАС, что человек и другие агенты, а **активный документ там один на всех**. Два симптома, которые легко принять за свою ошибку: операция ушла в чужую деталь (кто-то создал документ — активность переехала), либо твой документ исчез, потому что сосед вызвал `document_close(all=true)` — тот закрывает ВСЁ и без сохранения. - **Строишь параллельно с кем-то — `instance="private"`** при первом `kompas_connect` (потом режим не сменить). Свой экземпляр: активный документ только твой, окно скрыто (`kompas_set_visible true` покажет). - **`shared` оставляй**, когда работа идёт на глазах у человека и ты единственный агент. - **Один файл в двух экземплярах не открыть** — второй получит его только на чтение: работу делите по файлам, а не по вкладкам. ## Открытые вопросы / границы - **Параметрика работает через параметры ОПЕРАЦИЙ, а не размеры эскиза** — сдвинуть контур переменной нельзя, только пересобрать эскиз. Планируй членение так, чтобы изменяемое задавалось параметром операции (глубина, радиус, габарит примитива), а не координатами в эскизе. - **2D покрыт вместе с разрезом и сечением.** Есть виды (с выбором набора, ориентации главного и невидимых линий), разрез/сечение, листы, штамп, размеры с допусками, осевые, обозначения, техтребования, удаление и сдвиг объекта, вывод в растр — методика в §«Чертёж». Нет выносного элемента, местного разреза внутри вида, местного вида и вида с разрывом. - **Разрез не переживает правку модели, если он не первый на своём базовом виде.** Замерено: обновляется только ПЕРВЫЙ, остальные молча остаются со старой геометрией, и ни одно перестроение этого не чинит. Порядок один: сначала модель, потом разрезы. - **Вставку фрагмента правят только целиком** (заново `fragment_place`). Экспорт наружу — растр и STEP; DXF/DWG и PDF не пишутся. - **SVG сервер не читает** — и не будет: разбор путей, деление кривых Безье на дуги и разбор вложенности контуров живут во внешнем конвертере, а серверу достаётся готовый список примитивов. ## Связанное - Проверка окружения (КОМПАС установлен, сервер запускается, подключение живое): команда **`/kompas:doctor`**. - Установка, требования и настройка сервера: README плагина. - Правила проектирования под FDM/FFF-печать: навык **`kompas-fdm-design`**.