Зафиксирован фундамент проекта MCP-сервера КОМПАС-3D: - docs/: ARCHITECTURE.md, IMPLEMENTATION_PLAN.md, presentation.html - tools/kdoc.py: навигатор по справке SDK - libs/kompas-interop/: вендорские interop-сборки КОМПАС из SDK - src/Kompas.Mcp.ConnectSpike: net8.0-windows консоль, доказывает работу COM-интеропа и attach/launch подключения к КОМПАС (IApplication, версия 24.0) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
21 KiB
Архитектура MCP-сервера КОМПАС-3D (предлагаемый вариант)
Статус: черновик / предлагаемый вариант, открыт к правкам. Назначение: зафиксировать выбор стека и целевую архитектуру решения до начала реализации. Сопутствующий контекст по COM API КОМПАС — в
../CLAUDE.md. Имена интерфейсов и перечислений сверены со справкой SDK черезtools/kdoc.py.
1. Назначение и контекст
Строим MCP-сервер, который даёт LLM управлять CAD-системой КОМПАС-3D (АСКОН): создавать/открывать документы, строить 2D-геометрию, 3D-детали и сборки, читать/писать параметры, запускать команды.
Жёсткие рамки, заданные природой API:
- Только Windows, только x64 — КОМПАС автоматизируется через COM Automation API; разрядность сервера должна совпадать с разрядностью установленного КОМПАС.
- КОМПАС должен быть установлен и запускаем на той же машине. Сервер — это COM-клиент, а не самостоятельный геометрический движок. Без работающего экземпляра КОМПАС инструменты бесполезны.
- Целевая среда — КОМПАС-3D v24 Home (LT-редакция); часть возможностей полной редакции может быть недоступна.
Две сосуществующие версии API (подробнее — CLAUDE.md):
| Точка входа | Namespace (C#) | Когда | |
|---|---|---|---|
| API5 (legacy) | KompasObject |
Kompas6API5 |
bootstrap-подключение, построение 3D через ksPart |
| API7 (современный) | IApplication |
KompasAPI7 |
всё новое: документы, параметры, операции |
2. Выбранный стек
| Решение | Выбор | Обоснование |
|---|---|---|
| Язык / платформа | .NET 8 (LTS), C#, win-x64 |
COM-интероп первого класса; SDK поставляет именно C#-примеры и .tlb |
| MCP SDK | ModelContextProtocol (официальный C# SDK) |
хостинг через Microsoft.Extensions.Hosting, DI, готовый stdio-транспорт |
| Транспорт | stdio | локальный клиент (Claude Desktop / IDE) запускает сервер дочерним процессом на машине с КОМПАС — проще и безопаснее всего |
| COM-интероп | COM-references на .tlb из SDK\lib |
строгая типизация интерфейсов API7 (IApplication, IPart7, …) на этапе компиляции |
| Логи | Microsoft.Extensions.Logging → stderr |
stdout занят протоколом MCP — туда писать нельзя |
| Сериализация | System.Text.Json |
штатно в .NET, без зависимостей |
Подключаемые типобиблиотеки (C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK\lib):
kAPI5.tlb, kAPI7.tlb, ksConstants.tlb, ksConstants3D.tlb, kAPI2D5COM.tlb, kAPI3D5COM.tlb.
Namespaces: Kompas6API5, KompasAPI7, Kompas6Constants, Kompas6Constants3D, KAPITypes.
Почему C#, а не Python
Python (comtypes/pywin32) технически способен управлять COM, но КОМПАС-API активно использует
конструкции, болезненные для динамического интеропа: out/ref-параметры (например,
ExecuteKompasCommand(commandID, post, &retval)), SAFEARRAY/динамические массивы
(ksDynamicArray, ksLtVariant), мосты API5↔API7 (ksGetApplication7, TransferInterface) и
обязательный STA + насос сообщений. В C# всё это покрыто строго типизированным interop, что
снижает риск и стоимость поддержки.
3. Модель процесса и потоков (ключевой раздел)
COM-объекты КОМПАС живут в STA (Single-Threaded Apartment), экземпляр приложения — единственный и однопоточный. Отсюда — центральное архитектурное ограничение:
- Сервер держит один выделенный STA-поток, который владеет всеми без исключения
COM-вызовами. Асинхронные обработчики MCP-инструментов (поток-пул) маршалят работу в этот
поток через очередь/диспетчер (например,
BlockingCollection<Func<…>>или собственныйSynchronizationContext). Это автоматически сериализует доступ к КОМПАС. - STA-поток крутит насос сообщений Windows и периодически вызывает
IApplication.PumpWaitingMessages()/ при необходимостиEnableTaskAccess(false)на время пакетных операций — чтобы диалоги и колбэки КОМПАС не приводили к взаимоблокировке.
MCP client ──stdio──> Host (поток-пул, async)
│ ставит задачу в очередь
▼
┌─────────────────────────┐
│ STA-поток (COM owner) │ ← насос сообщений + PumpWaitingMessages
│ KompasObject / IApplication
└─────────────────────────┘
│ COM
▼
КОМПАС-3D.exe
Подключение к КОМПАС
- Разрешить ProgID. На целевой машине (v24 Home) проверено: зарегистрированы
KOMPAS.Application.7иKOMPAS.Application.5, аKOMPASLT.*отсутствует — то есть Home-редакция использует обычные ProgID, а не LT. Порядок попыток:KOMPAS.Application.7(прямой API7) →KOMPAS.Application.5(+ksGetApplication7()) →KOMPASLT.Application.5(запасной, для других инсталляций). Выбранный ProgID фиксировать в логе. - Attach к запущенному экземпляру:
Marshal.GetActiveObject(progId). Если не запущен — launch:Activator.CreateInstance(Type.GetTypeFromProgID(progId)). - Если зашли через API5 — получить современное приложение:
IApplication appl = (IApplication)kompas.ksGetApplication7();(черезKOMPAS.Application.7IApplicationуже на руках). appl.Visible = true;— показать окно КОМПАС; дальше работать через интерфейсы API7.
Жизненный цикл COM
- Корневые RCW (
KompasObject,IApplication) держим на всё время жизни сервера. - Временные объекты освобождаем (
Marshal.ReleaseComObject) в обратном порядке создания. appl.Quit()вызываем только если экземпляр запустили мы сами (флаг «launched-by-us»); к чужому запущенному КОМПАС не применяем.
4. Слои решения
В v1 — логические слои (папки/проекты одного solution KompasMcp.sln):
| Слой | Ответственность |
|---|---|
| Kompas.Mcp.Host | Точка входа. Сборка MCP-сервера (stdio), DI, логи в stderr, старт и владение STA-потоком, graceful shutdown. |
| Kompas.Mcp.Tools | Определения MCP-инструментов по категориям (System / Documents / Sketch / Features / Query). Тонкий слой: валидация аргументов → постановка задачи на STA-поток → форматирование результата/ошибки в MCP-ответ. |
Kompas.Mcp.Core (KompasSession) |
COM-слой. Менеджер соединения, менеджер документов, построитель эскизов, построитель операций, помощники выборки граней/плоскостей. Безопасные типизированные методы, null-проверки, трансляция ошибок. Здесь живут все паттерны работы с API5/API7. |
| Kompas.Mcp.Interop | Interop-сборки из .tlb + маппинг «дружелюбная строка ↔ перечисление» (DocumentTypeEnum, Obj3dType, ksEndTypeEnum, ksDirectionTypeEnum). |
Принцип: только Core и Interop знают про COM. Tools оперируют доменными
DTO и вызывают Core; Host не содержит бизнес-логики.
5. Карта инструментов v1
Сгруппированы вокруг центрального цикла «эскиз ↔ операция». Имена — snake_case.
System
kompas_connect— attach/launch, возвращает версию и редакцию (GetSystemVersion,ApplicationName).kompas_set_visible— показать/скрыть окно (IApplication.Visible).kompas_status— состояние соединения, активный документ.
Documents (IApplication.Documents → IDocuments)
document_create— типpart | assembly | drawing | fragment(DocumentTypeEnum: Part=4, Assembly=5, Drawing=1, Fragment=2).document_open/document_save/document_close/document_active.
Sketch (2D-геометрия внутри 3D-эскиза)
sketch_create— на базовой плоскости (o3d_planeXOY/XOZ/YOZ) или на выбранной грани.sketch_add_line/sketch_add_circle/sketch_add_arc/sketch_add_rectangle.sketch_close— завершить редактирование.- Жизненный цикл:
NewEntity(o3d_sketch)→SetPlane(plane|face)→BeginEdit()→ksLineSeg/ksCircle/ … →EndEdit().
Features (3D-операции)
extrude_boss/extrude_cut— sketch, depth, direction, endType.revolve_boss/revolve_cut— угол.rebuild— перестроить деталь.
Selection / Query
select_face_by_point— выбрать грань точкой (для следующего эскиза).list_bodies,list_faces_planes— перечислить тела/грани и плоскости.get_part_info— МЦХ/габариты (IMassInertiaParam7).
Vision — визуальная обратная связь («зрение агента»)
model_snapshot— отрендерить активный 3D-документ в PNG и вернуть как image-контент MCP, чтобы мультимодальный агент увидел промежуточный результат и контролировал построение пошагово.set_view— задать ориентацию вида (iso/front/top/right/ …), zoom-to-fit и режим отображения (ShadedWireframe) перед снимком — иначе снимок берётся со случайного текущего ракурса.
Механизм.
ksDocument3D.RasterFormatParam()→IRasterFormatParamрендерит документ в растр; свойствоresultArrayBytesвозвращает изображение как массив байт в память (без временного файла). Альтернатива — экспортные функцииksSaveAsToRasterFormat[W]. Полученные байты сервер упаковывает в image-контент MCP-ответа (C# SDKModelContextProtocolэто поддерживает). Параметры: формат (PNG/JPEG/BMP/TIFF), разрешение, цвет/greyScale. Снимки делать после значимых операций (не после каждой линии) — каждый кадр расходует токены изображения в контексте агента. На v24 Home качество/доступность рендера проверить на прототипе.
Escape hatch (опционально)
run_kompas_command—IApplication.ExecuteKompasCommand(commandID, post)для команд, ещё не обёрнутых в типизированные инструменты. Доступность проверять черезIsKompasCommandEnable.
Замечание об API5 vs API7 для 3D-операций
API7 создаёт операции через IPart7 → (QueryInterface) IModelContainer → IExtrusions.Add()
→ IExtrusion. Примеры SDK при этом активно используют API5-путь (ksPart.NewEntity(o3d_…) →
ksBossExtrusionDefinition.SetSideParam/SetSketch → Create()), который хорошо документирован.
Стратегия v1: предпочитать API7 там, где он покрывает операцию; падать на API5 ksPart-путь
там, где он проще/надёжнее (мост — kompas.TransferInterface). Выбор фиксировать в Core.
6. Центральный сценарий: цикл «эскиз → операция → эскиз»
Основной пользовательский поток v1 — итеративное параметрическое моделирование.
document_create(part)
│
▼
sketch_create(plane = XOY) ──► sketch_add_circle(...) ──► sketch_close
│
▼
extrude_boss(sketch, depth=…, dir=dtNormal, end=etBlind) → цилиндр
│
▼
set_view(iso, fit) → model_snapshot 👁 агент СМОТРИТ на результат и решает следующий шаг
│
▼
select_face_by_point(x,y,z) ← выбираем верхнюю грань
│
▼
sketch_create(face = выбранная) ──► sketch_add_circle(...) ──► sketch_close
│
▼
extrude_cut(sketch, depth=…) → отверстие
│
▼
model_snapshot 👁 проверка результата
│
└──────────► повторять: смотрим → новая грань → новый эскиз → новая операция
Соответствие API (на STA-потоке, через Core):
Document3D()/IKompasDocument3D→IPart7(вершинная деталь,pTop_Part).part.NewEntity(o3d_sketch)→GetDefinition()→SetPlane(базовая_плоскость | грань)→Create();BeginEdit()→ рисование примитивов (ksLineSeg,ksCircle,ksArcByPoint, …) →EndEdit().part.NewEntity(o3d_bossExtrusion)→ksBossExtrusionDefinition→SetSideParam(direction, ksEndTypeEnum, depth, …)→SetSketch(эскиз)→Create(). Для выреза —o3d_cutExtrusion; для вращения —o3d_bossRotated/o3d_cutRotated.- Выбор грани для следующего эскиза:
part.EntityCollection(o3d_face)→SelectByPoint(x, y, z)→ элемент коллекции как плоскость эскиза. - Снимок результата:
set_view(ориентация + fit) →ksDocument3D.RasterFormatParam()→IRasterFormatParam.resultArrayBytes→ image-контент MCP. Агент анализирует кадр и выбирает следующий шаг.
Используемые перечисления: ksDirectionTypeEnum (dtNormal/dtReverse/dtBoth/dtMiddlePlane),
ksEndTypeEnum (etBlind/etThroughAll/etUpTo…), Obj3dType (o3d_sketch, o3d_bossExtrusion,
o3d_cutExtrusion, o3d_face, o3d_planeXOY, …).
7. Обработка ошибок и безопасность
- Трансляция ошибок COM в структурированные MCP-ошибки: проверять HRESULT каждого вызова и
опрашивать
kompas.ksGetLastError()/IApplication.KompasError; возвращать клиенту код + текст. - Null-чек после каждого приведения COM-интерфейса (любой каст может вернуть
null). .Init()на param-структурах перед использованием (GetParamStruct(...)→.Init()).- Гарантированный
EndEditдля эскизов черезtry/finally— незакрытый эскиз ломает документ. - Подтверждение деструктивных операций: закрытие без сохранения, перезапись файла,
Quit— только по явному флагу в аргументах инструмента. - Модель состояния: инструменты по умолчанию работают с «активным документом»; опционально — явный хэндл/идентификатор документа.
8. Сборка и запуск
dotnet build -c Release -r win-x64 # сборка
# → kompas-mcp.exe (self-contained, win-x64)
Регистрация stdio-сервера у клиента (пример для конфигурации Claude Desktop):
{
"mcpServers": {
"kompas3d": { "command": "C:\\path\\to\\kompas-mcp.exe", "args": [] }
}
}
Ручная проверка (smoke): запустить КОМПАС (или дать серверу запустить его) → через инструменты
построить простую деталь (выдавить окружность в цилиндр, затем extrude_cut — отверстие) →
убедиться визуально в окне КОМПАС → сохранить .m3d.
9. Стратегия тестирования
- Интеграционные тесты (требуют установленного КОМПАС): xUnit, категория
Integration, гейтятся (не идут в обычном CI без КОМПАС). Покрывают связку Core↔COM и центральный цикл. - Unit-тесты чистой логики без COM: маппинг строк↔перечислений, валидация аргументов, форматирование результатов/ошибок.
- Smoke MCP: проверка протокола через MCP Inspector или тестовый клиент (list tools, вызов
kompas_connect/document_create).
10. Дорожная карта (после v1)
- Операции:
fillet/chamfer/shell/rib/loft/sweep; массивы (ILinearPattern,ICircularPattern). - Параметры и свойства:
IVariable7/IVariableTable,IPropertyMng/IPropertyKeeper. - Полноценное 2D-черчение: виды, линии/дуги/окружности, размеры (
ILinearDimension, …), штриховки, тексты. - Спецификации (
ISpecification), сборки и сопряжения (IAssemblyDocument). - Конвертеры/экспорт (STEP и др.) через
IApplication.Converter. - Транспорт HTTP/SSE — как опция для удалённых клиентов.
11. Открытые вопросы
- Один проект vs solution из 4 проектов в v1 (склоняемся к одному solution, слои — папками, выделять проекты по мере роста).
- Embed Interop Types vs генерируемые interop-сборки (
tlbimp) — проверить на реальных.tlbv24, выбрать по совместимости типов и размеру. - Стратегия именования инструментов — подтвердить
snake_caseс группами-префиксами (document_*,sketch_*, …).