Files
kompas3d-mcp/CLAUDE.md
T
mikhail d8edb18f06 docs: текстовые обозначения чертежа — README, ARCHITECTURE, OPEN_QUESTIONS, presentation, CLAUDE.md
81 инструментов, 267 тестов. 2D-чертёж: добавлены шероховатость, свободный текст,
технические требования (инкремент 6).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 21:22:35 +03:00

43 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project goal

Build an MCP (Model Context Protocol) server that lets an LLM drive the CAD system КОМПАС-3D (ASCON). The server exposes КОМПАС operations (create/open documents, build 2D geometry, 3D parts and assemblies, read/write parameters, run macros) as MCP tools.

Authoritative references:

  • SDK knowledge base in this repo: docs/Kompas3D_SDK/ — clean Markdown, one article per COM interface, with YAML tags; search it with Grep/Read (see below). Committed to the repo (canonical), distilled from the КОМПАС SDK help. Prefer this over the web. For non-trivial lookups, dispatch the kompas-sdk-research subagent (Sonnet) to save context.
  • Online SDK docs: https://help.ascon.ru/KOMPAS_SDK/22/ru-RU/index.html
  • Local SDK install: C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK

Navigating the SDK docs (docs/Kompas3D_SDK/)

docs/Kompas3D_SDK/ is a structured MD knowledge base distilled from the 26 000-page Help&Manual WebHelp export. One article per COM interface/topic, split into interfaces/, enums/, structures/, guides/ (+ resources/ images), each with YAML frontmatter (type, api, domain, tags, sources); methods/properties are ## headings inside the interface article. Search it directly — do not browse the raw HTML:

  • Grep over docs/Kompas3D_SDK/ for an interface/method/property name or Russian keyword (method names are ## SetSideParam - … headings, so the name lands you in the right article).
  • Read the matching *.md — the interface article holds all its members, Синтаксис Automation:/Синтаксис COM: blocks (in code fences), parameters, notes.
  • docs/Kompas3D_SDK/index.md — table of contents by category. Filter by frontmatter tags, e.g. Grep "type: enum" or Grep "domain: \[.*3d".

The base is committed to the repo (canonical) — no regeneration step. It covers the COM API7/API5 reference this project uses (interfaces named iapplication_*, idocuments_*, …). The cross-platform Qt/C++ KsAPI flavour (ksapi_*, non-COM binding) is intentionally excluded from the base — ignore unless explicitly working with KsAPI.

Current state

v1 + v2 + STEP/assembly + direct B-rep edit + structural model inspection implemented and working (full sketch→feature→inspect→STEP round-trip + move_face + describe_model validated end-to-end). Stack: .NET 8 (net8.0-windows, x64), C#, MCP via the official ModelContextProtocol SDK over stdio. 81 MCP tools, 267 tests green (163 unit + 104 integration). v2 added: sketch-on-face (by point and by index), revolve (boss/cut + sketch axis), fillet/chamfer (edge-by-point and by index), and Query tools get_part_info (МЦХ), get_bounding_box, list_faces, list_edges. After v2: import_step, export_step (ConversionService, ConversionTools), list_components (assembly traversal via TopPart → IParts7). move_face (FaceEditService, EditTools) — direct B-rep face editing. After move_face: structural model inspectiondescribe_model, list_features, list_bodies, list_variables, describe_face, describe_edge, measure (ModelInspectionService, InspectionTools). describe_model is the preferred first call over model_snapshot (no token cost for image context; gives feature tree, bodies, variables, topology summary, МЦХ). Package A «richer sketches»: 7 new sketch primitives — sketch_add_arc, sketch_add_arc_3points, sketch_add_ellipse, sketch_add_polyline, sketch_add_polygon, sketch_add_spline, sketch_add_point. PartModeler refactored into partial classes: PartModeler.cs (core), PartModeler.Sketch.cs (2D primitives), PartModeler.Features.cs (extrude/revolve/fillet/chamfer). Static SketchGeometry class in Core/Modeling. Package B «forming ops» complete: shell (оболочка, o3d_shellOperation=43) + rib (ребро жёсткости, o3d_ribOperation=44) + sweep (кинематическая операция, o3d_baseEvolution=45) + loft (по сечениям, o3d_baseLoft=30). Auxiliary geometry (start of package E): sketch_create_on_offset_plane (смещённая плоскость, o3d_planeOffset=14) — unlocked loft. Additional Edit tools: split_solid_by_plane, move_body, boolean_union. Package C «patterns & mirror» complete: linear_pattern (линейный массив, o3d_meshCopy=35) + circular_pattern (круговой массив, o3d_circularCopy=36) + mirror_operation (зеркальная копия операций, o3d_mirrorOperation=48) + mirror_body (зеркало тела, o3d_mirrorAllOperation=49). hole (HoleService, FeatureTools) — цилиндрическое отверстие (сквозное или глухое) через API7 (IModelContainer/IHole3D/IHoleDisposal); первая формообразующая операция на API7 (прецедент ранее только у move_face). hole_counterbore — отверстие с цековкой (ksHTCounterbore, ISpotfacingHoleParameters). hole_countersink — отверстие с зенковкой (ksHTCountersinking, ICountersinkHoleParameters). hole_conic — коническое отверстие (ksHTConic, IConicHoleParameters: ConicType=ksCNAngle, ConicAngle); завершает набор типов отверстий. HoleCore рефакторен: принимает ksHoleTypeEnum holeType + Action<IHole3D> configure (настройка HoleParameters после установки HoleType, т.к. параметрический подынтерфейс недоступен до фиксации типа). Базовый hole = ksHTBase + configure=null. draft (уклон, o3d_incline=42) — наклон граней на угол относительно нейтральной координатной плоскости; реализован через API5 ksInclineDefinition (операция называется Incline в API5, не Draft). Package D «parametrics» started: create_variable, set_variable, delete_variable (VariableService, VariableTools) — CRUD переменных модели через API5. list_variables исправлен (читает ksPart.GetFeature().VariableCollection, а не ksPart.VariableCollection()). Ограничение: переменная управляет геометрией только в параметрической модели (где размеры эскиза связаны с именем переменной); наши эскизы строятся литеральными координатами → set_variable хранит/вычисляет значение, но геометрию не меняет. Связь эскизных размеров с переменными (API2D) — не реализована. Assembly class: assembly_add_component (AssemblyService, AssemblyTools, namespace Kompas.Mcp.Core.Assemblies) — вставка компонента (.m3d/.a3d) из файла в активную сборку с заданием положения origin (мм, мировая СК сборки); возвращает индекс и имя вставленного компонента. assembly_add_mate — наложить сопряжение между гранями двух компонентов активной сборки, выбранными по мировым точкам; mateType: coincidence (грани заподлицо) | distance (зазор value мм, value>0); решатель позиционирует компоненты; возвращает статус (valid). Подтверждено вживую: coincidence (ширина сборки 120→40 мм), distance(30) (→70 мм). 2D-чертёж (веха, инкремент 3): drawing_create_standard_views (DrawingService, DrawingTools, namespace Kompas.Mcp.Core.Drawings) — создать стандартные ассоциативные виды (спереди/сверху/слева) сохранённой 3D-модели (.m3d/.a3d) на активном чертеже; возвращает число созданных видов (3) и их номера (ViewNumbers). drawing_fill_title_block — заполнить графы основной надписи (штампа) активного чертежа: designation (обозначение, графа 2), name (наименование изделия, графа 1), material (материал, графа 3); передаются только нужные поля (null/пусто пропускается, нужно хотя бы одно); возвращает число заполненных граф. drawing_add_linear_dimension — поставить линейный размер на виде активного чертежа: точки (x1,y1)-(x2,y2) в локальной СК вида (мм), положение размерной линии (x3,y3), orientation (horizontal|vertical|parallel), viewNumber (0=первый вид); значение измеряется автоматически; возвращает значение и номер вида. drawing_add_diametral_dimension — поставить диаметральный размер (Ø) окружности: центр (xc,yc), radius, angle (направление выноски, градусы), viewNumber; значение = 2·radius, измеряется автоматически; возвращает диаметр и номер вида. 2D-чертёж (инкремент 5, базовое семейство размеров завершено): drawing_add_radial_dimension — радиальный размер (R) окружности/дуги на виде: центр (xc,yc), radius, angle (направление выноски, °), viewNumber; значение измеряется автоматически и = РАДИУСУ (не диаметру — вопреки справке SDK); возвращает радиус и номер вида. drawing_add_angular_dimension — угловой размер между лучами (xc,yc)→(x1,y1) и (xc,yc)→(x2,y2) на виде: (x3,y3) — положение размерной дуги (задаёт её радиус), angleType (min|max|more) выбирает измеряемый угол, viewNumber; значение (градусы) измеряется автоматически; возвращает угол (°) и номер вида. 2D-чертёж (инкремент 6, текстовые обозначения): drawing_add_rough — знак шероховатости на виде: x,y (положение, ЛСК вида, мм), value (текст параметра, напр. "Ra 1.6"; пусто = без значения), signType (delete|without|none), angle (наклон оси, °), viewNumber; возвращает значение (read-back) и номер вида. drawing_add_text — свободная текстовая надпись на виде стилем по умолчанию: x,y (точка привязки), text (\n — многострочно), angle, viewNumber; возвращает текст (read-back) и номер вида. drawing_set_technical_requirements — технические требования чертежа (единый блок над штампом, уровень документа): text (строки через \n); перезаписывает прежние; возвращает число строк. See README.md and docs/ARCHITECTURE.md; design decisions/caveats in docs/OPEN_QUESTIONS.md.

Principle: MCP = translating SDK capabilities into general tools (not task-specific). On top of MCP — skill .claude/skills/kompas-3d/ with a methodology (playbooks, heuristics, validated in usecases/). Layout: usecases/ (in .gitignore) is the proving ground; proven techniques are promoted to the skill.

Delegation subagents (.claude/agents/, dispatched via the Agent tool to keep heavy work off Opus's context — system prompt lives in the agent definition, so pass only the variable part as the prompt):

  • kompas-sdk-research (model: Haiku, read-only — Glob/Grep/Read): finds an interface/method/enum/constant signature in the docs/Kompas3D_SDK/ MD knowledge base and returns a compressed summary. Dispatch it for any non-trivial SDK lookup instead of grepping the help yourself; a wrong answer is cheap — Opus re-verifies against libs/kompas-interop/*.dll by reflection.
  • docs-maintainer (model: Sonnet, Read/Edit/Write/Glob/Grep): syncs README.md/CLAUDE.md/docs/ARCHITECTURE.md/docs/OPEN_QUESTIONS.md/docs/presentation.html with code changes from a change summary you provide. Dispatch it for doc updates instead of editing docs by hand. (Both were skills before — converted to native subagents; the model split reflects task type: bounded retrieval → Haiku, judgement-heavy editing → Sonnet.)

Layout: src/Kompas.Mcp.Core (COM layer), src/Kompas.Mcp.Host (MCP stdio server + tools), tests/Kompas.Mcp.Tests (unit + integration), libs/kompas-interop/*.dll (vendored КОМПАС interop assemblies from SDK Samples/Common, referenced via Directory.Build.propsKompasInteropDir).

dotnet build -c Release                          # build
dotnet test  --filter "Category=Unit"            # unit tests (no COM)
dotnet test  --filter "Category=Integration"     # integration (requires running КОМПАС)
dotnet run --project src/Kompas.Mcp.Host         # start the MCP server (stdio)

Key implementation facts (don't relearn):

  • All COM calls run on one dedicated STA thread (KompasDispatcher.InvokeAsync); КОМПАС is single-instance STA. Services never touch COM off that thread.
  • Connection goes through API5 (KOMPAS.Application.5KompasObject) then ksGetApplication7()IApplication; the API5 root is needed for ksPart 3D-building and ksDocument3D snapshots.
  • 3D is built via API5 ksPart (NewEntity(o3d_sketch/o3d_bossExtrusion/o3d_bossRotated/o3d_fillet/o3d_chamfer/o3d_shellOperation=43/o3d_ribOperation=44/o3d_baseEvolution=45/...), ksBossExtrusionDefinition/ksCutExtrusionDefinition/ksBossRotatedDefinition/ksFilletDefinition/ksChamferDefinition/ksShellDefinition/ksRibDefinition/ksBaseEvolutionDefinition); cut-through holes use dtBoth + etThroughAll. API7 is used for app/documents.
  • Face/edge selection: ksPart.EntityCollection(o3d_face|o3d_edge)SelectByPoint(x,y,z) (world mm) filters to objects through the point, then GetByIndex(0); or by stable index from list_faces/list_edges. ksFaceDefinition.IsPlanar/IsCylinder/... + GetArea(ST_MIX_MM) classify faces. ksEdgeDefinition.IsLineSeg/IsCircle/IsArc/... + GetLength() classify/measure edges. Sketch axis = line with system style 3 (осевая). Fillet/chamfer by edge index via fillet_edge_index/chamfer_edge_index (more reliable than by-point).
  • МЦХ / mass props: use API5 ksPart.CalcMassInertiaProperties(ST_MIX_MM|ST_MIX_KG)ksMassInertiaParam (v/m/F/xc/yc/zc), computed on demand. Do NOT use API7 IMassInertiaParam7.Calculate() — its Actual flag sticks after the first calc and won't refresh on API5 geometry changes (stale volume). Bounding box: ksPart.GetGabarit(full:false, ...).
  • Snapshot: ksDocument3D.SaveAsToRasterFormat(file, ksRasterFormatParam) renders to a temp file (the in-memory resultArrayBytes stays empty when a filename is given); read bytes back. Return to MCP via ImageContentBlock.FromBytes(bytes, mime)not Data = bytes (Data holds base64 bytes). Use model_snapshot only for visually-spatial questions; prefer describe_model first.
  • Logs go to stderr (stdout is the MCP channel). Integration tests reuse one КОМПАС via KompasFixture; artifacts land in gitignored .scratch/. All integration test classes inherit IntegrationTestBase (IAsyncLifetime) which calls DocumentService.CloseAllAsync after each test to prevent tab accumulation in КОМПАС.
  • Structural model inspection (ModelInspectionService, InspectionTools): describe_model — one-call structural "passport" (bounding box + МЦХ + bodies + topology summary + feature tree + variables); preferred over snapshot. list_features — feature tree with params (depth/radius/legs). list_bodies — list solid/surface bodies with face count. list_variables — model variables (name/expression/value, external/info flags); reads via ksPart.GetFeature().VariableCollection (all variables, including user-created) with fallback to ksPart.VariableCollection() (external-only — bug was fixed). describe_face — drill-down by index (type, area, normal, radius, edge count). describe_edge — drill-down by index (type, length, adjacent faces, vertices). measure — distance/angle between two objects (face|edge|vertex by index, unit ST_MIX_MM).
  • Variable management (package D start, VariableService, VariableTools): create_variable(name, value, note?, external?) — creates a model variable; set_variable(name, expression) — sets expression (constant "30" or formula "width*2+5"); delete_variable(name) — deletes (fails if dependents exist). Key API facts (don't relearn): variable creation MUST use ksPart.GetFeature().VariableCollection (property on root ksFeature) — NOT ksPart.VariableCollection() (returns external-only). Expression is the leading field; value is derived. Changes applied via ksPart.RebuildModel() (return checked); after rebuild the RCW variable is stale → re-read via fresh collection (ReadValueFresh). Dependent variables recalculate automatically. Deletion fails if dependents exist (RemoveVariable returns FALSE). Geometry limitation: variables control geometry only in a parametric model where sketch dimensions are linked to variable names; our sketches are built with literal coordinates → set_variable stores/computes the value but does NOT change geometry. Linking sketch dimensions to variables (parametric sketches via API2D) is not yet implemented.
  • Feature tree API (don't relearn): read via API5 ksPart.GetFeature()(ksFeature).SubFeatureCollection(true,false)ksFeatureCollection. Cast (ksFeature)part does NOT work (RCW QI returns null) — must use GetFeature(). ksFeature.type returns only coarse o3d_entity and does NOT distinguish operations; precise type and params come from ksFeature.GetObject()ksEntity.GetDefinition() and matching definition type (ksBossExtrusionDefinition.GetSideParam, ksFilletDefinition.radius, ksChamferDefinition.GetChamferParam, …). Node name ("Элемент выдавливания:1", "Скругление:1") is localized by КОМПАС itself.
  • STEP import/export, list_components, move_face, split_solid_by_plane, move_body, boolean_union, full inspection layer, richer sketch primitives (package A), shell, rib, sweep, loft (package B complete), sketch_create_on_offset_plane (package E start), linear_pattern, circular_pattern, mirror_operation, mirror_body (package C complete), hole, hole_counterbore, hole_countersink, hole_conic (all API7 via HoleService; hole_conic uses ksHTConic/IConicHoleParameters), draft (API5 ksInclineDefinition), create_variable/set_variable/delete_variable (package D start), assembly_add_component, assembly_add_mate (both API7, AssemblyService; mate types coincidence/distance verified), drawing_create_standard_views (API7, DrawingService, namespace Kompas.Mcp.Core.Drawings), drawing_fill_title_block (API7, DrawingService; заполнение основной надписи/штампа через IStamp), drawing_add_linear_dimension (API7, DrawingService; линейный размер на виде через ISymbols2DContainer/LineDimensions.Add/ILineDimension; координаты в локальной СК вида), drawing_add_diametral_dimension (API7, DrawingService; диаметральный размер через ISymbols2DContainer.DiametralDimensions.Add/IDiametralDimension; Xc/Yc/Radius в локальной СК вида, Angle в радианах, NominalValue=2·Radius), drawing_add_radial_dimension (API7, DrawingService; радиальный размер R через ISymbols2DContainer.RadialDimensions.Add/IRadialDimension; Xc/Yc/Radius+Angle (рад), DimensionType=true; NominalValue=Radius, НЕ диаметр — вопреки справке SDK, подтверждено спайком), drawing_add_angular_dimension (API7, DrawingService; угловой размер через ISymbols2DContainer.AngleDimensions.Add(ksDrADimension=10)/IAngleDimension; вершина Xc/Yc + точки сторон X1/Y1,X2/Y2 + положение дуги X3/Y3 (локальная СК вида); измеряемый угол выбирает DimensionType=ksAngleDimTypeEnum через enum AngleDimensionType{Min,Max,More}+AngleDimensionTypes.Parse/ToKompas; на лучах 0°/45° → min=45°/max=135°(супплемент)/more=315°(рефлексный); NominalValue в градусах; (x3,y3) лишь позиционирует дугу, угол НЕ выбирает), drawing_add_rough (API7, DrawingService; знак шероховатости через ISymbols2DContainer.Roughs.Add()/IRough (BranchX0/Y0,Angle) + (IRoughParams)rough QI: SignType=ksRoughSignEnum через enum RoughSignType{NoProcessing,DeleteMaterial,WithoutDeleteMaterial}+RoughSignTypes.Parse/ToKompas, значение Ra/Rz — RoughParamText.Str; возвращает значение read-back), drawing_add_text (API7, DrawingService; свободная надпись через (IDrawingContainer)view.DrawingTexts.Add()/IDrawingText (X/Y/Angle) + (IText)dt.Str=текст; текст в IDrawingContainer, НЕ в ISymbols2DContainer, и НЕ в IView.ObjectCount — счёт по DrawingTexts.Count; Height НЕ задаём — это высота блока, не шрифт), drawing_set_technical_requirements (API7, DrawingService; тех. требования уровня ДОКУМЕНТА через (IDrawingDocument)doc.TechnicalDemand/ITechnicalDemand: td.Text.Str=текст → td.Update(); IsCreated False→True при первом задании; перезаписывает; многострочно \n) are done. DrawingAnnotationResult{Value(read-back),ViewNumber} — общий результат rough/text. Базовое семейство размеров 2D-чертежа завершено (линейный, диаметральный, радиальный, угловой); текстовые обозначения (шероховатость, надпись, тех. требования) завершены. Not yet done: parametric sketches — investigated, unavailable via COM API (ksCDimWithVariable cannot be constructed from external automation; see docs/superpowers/specs/2026-05-27-parametric-sketch-findings.md); 2D-чертёж: ассоциативная привязка размеров/шероховатости к геометрии (BaseObject/BaseObject1/2), рамка/формат листа, выноски (Leaders), обозначения баз (Bases), допуски формы (Tolerances) — далее; additional mate types (parallel/perpendicular/concentric/angle/tangency); package E continuation (axis, angle plane). Known caveat: boss/cut direction on a selected face depends on face-normal orientation (forward may need flipping — agent picks via snapshot or describe_face normal). See docs/OPEN_QUESTIONS.md → «Ревью v2».
  • "STEP import without history" detected structurally: bodyCount > 0 && no formative features && features.Count <= bodyCount+1 (only origin + body). STEP with edits (move_face: "Смещённая плоскость", "Разрезать", "Переместить грани", "Булева операция") — that already has history.
  • Topology/measure API: ksFaceDefinition.EdgeCollection / GetCylinderParam / GetSurface().GetNormal + normalOrientation; ksEdgeDefinition.GetAdjacentFace(bool) / GetVertex(bool)ksVertexDefinition.GetPoint; bodies via ksPart.BodyCollection()ksBody (IsSolid / FaceCollection); all variables via ksPart.GetFeature().VariableCollectionksVariable (external-only: ksPart.VariableCollection() — do NOT use for reading all variables); measurements via ksPart.GetMeasurer()ksMeasurer (SetObject1/2, unit=ST_MIX_MM, Calc, distance/MinDistance/angle in degrees / IsAngleValid).
  • STEP import COM pattern (verified): IApplication.get_Converter((object)(int)ksConverterFromSTEP=-3) (pass format code, not DLL path) → IConverter.ConverterParameters(cmd) → set IAdditionConvertParameters.Format=ksConverterFromSTEPIKompasDocument3D1.ConvertFromAdditionFormat(path, prm). Export: ConvertToAdditionFormat with format codes for AP203/AP214/AP242. Param co-classes (AdditionConvertParameters etc.) are NOT CoCreatable — only via converter factories. Assembly traversal: IKompasDocument3D.TopPart → IPart7.Parts (IParts7). Extract component: prm.NeedCreateComponentsFiles=true (writes .m3d files next to STEP) + IPart7.OpenSourceDocument.
  • Direct B-rep face editing (move_face) (verified on top_spacer, 39.45→41.45 mm height): API7 face object retrieved via IPart7.FindObjectsByPoint(x,y,z,true) → cast to KompasAPI7.IFace; containers acquired at runtime via COM-QI: (ISurfaceContainer)part, (IModelContainer)part; FaceMover (SetFaces + Offset + Direction + Update) moves the face. distance>0 = outward (add material), <0 = inward. Works on both parametric and imported B-rep geometry. Full split-reposition workflow (SplitSolids/BodyRepositions) is driveable but not yet exposed as tools.
  • Shell operation (shell, package B): ksShellDefinition via ksPart.NewEntity(o3d_shellOperation=43); thickness (mm) + thinType (bool: true=inward/false=outward; mapping: thinType = !outward) + FaceArray() (open faces, ≥1, by index from list_faces). Helper SelectFaceByIndex in PartModeler.cs (analogous to SelectEdgeByIndex, with range check). Validation: thickness>0, dedup via Distinct, range check before mutation. Transient RCWs in ShellAsync/SelectFaceByIndex are intentionally not released (consistent with Fillet/Chamfer pattern).
  • Rib operation (rib, package B): ksRibDefinition via ksPart.NewEntity(o3d_ribOperation=44). Params: sketchId, thickness (mm), side (left|right|up|down → 0/1/2/3 via SketchGeometry.RibSide()), symmetric (bool), angle (°). SetSketch(sketch) → set index=0, angle, side; SetThinParam(dtBoth, t/2, t/2) when symmetric=true, else SetThinParam(dtNormal, t, 0). Empirical: the rib contour must float in the gap (not touch the body at endpoints) — КОМПАС extends the web to the body automatically.
  • Sweep operation (sweep, package B): ksBaseEvolutionDefinition via ksPart.NewEntity(o3d_baseEvolution=45). Params: profileSketchId (closed profile sketch), pathSketchId (open/closed path sketch on a different plane, typically perpendicular). SetSketch(profile)PathPartArray().Add(path)sketchShiftType=0SetThinParam(false)Create(). Validation: profileSketchId != pathSketchId. Profile and path must be on different (usually perpendicular) planes.
  • Offset plane (sketch_create_on_offset_plane, package E start): OpenSketchOnOffsetPlaneAsync in PartModeler.Sketch.cs. ksPart.NewEntity(o3d_planeOffset=14)ksPlaneOffsetDefinition (SetPlane(basePlane) + offset mm + direction) → Create() → sketch on that plane. Used to place sketches at arbitrary heights — enables loft with parallel sections. entity.Create() result is checked (reliability fix applied to all CreateSketchOn* paths).
  • Loft operation (loft, package B): ksBaseLoftDefinition via ksPart.NewEntity(o3d_baseLoft=30). Params: sketchIds[] (≥2 closed profile sketches on different parallel planes). Sketchs().Add(each sketch)SetLoftParam(closed=false, false, true)SetThinParam(false)Create(). Requires parallel section sketches at different heights — use sketch_create_on_offset_plane for the non-base sections.
  • Patterns & mirror (package C): linear_patternksMeshCopyDefinition via ksPart.NewEntity(o3d_meshCopy=35); SetAxis1(axis) + SetCopyParamAlongAxis(true,0,count,step,false) + count2=1 (disables 2nd direction → 1D linear); features added via OperationArray() (no Get). circular_patternksCircularCopyDefinition via NewEntity(o3d_circularCopy=36); SetAxis(axis); properties set directly: count1=1 (radial off), count2=count (ring), step2=angle° between neighbours, factor2=false, inverce=reverse; GetOperationArray().Add(feature). mirror_operationksMirrorCopyDefinition via NewEntity(o3d_mirrorOperation=48); SetPlane(basePlane) + GetOperationArray().Add(feature). mirror_bodyksMirrorCopyAllDefinition via NewEntity(o3d_mirrorAllOperation=49); SetPlane(basePlane); ChooseBodies() does NOT cast to ksChooseBodies (returns null) and is not needed — o3d_mirrorAllOperation mirrors all bodies keeping the original (volume doubles). Source features retrieved by id from _features registry via new private RequireFeature helper (analogous to RequireSketch). New src/Kompas.Mcp.Core/Modeling/CoordinateAxis.cs — enum CoordinateAxis {X,Y,Z} + CoordinateAxes.ToObj3dType/Parse (→ o3d_axisOX/OY/OZ = 71/72/73), analogous to BasePlane.cs. SketchGeometry.RequireMin(int value, int min, string paramName) — validator for count>=2. Empirical: count includes the original instance (count=3 → 3 bodies); count2=1 disables 2nd direction for linear; step2 is angle° between neighbours for circular.
  • Hole operations (hole, hole_counterbore, hole_countersink, hole_conic): all implemented via API7 (not API5 — ksHoleDefinition absent in interop). Service src/Kompas.Mcp.Core/Modeling/HoleService.cs. HoleCore helper is parameterised with ksHoleTypeEnum holeType + Action<IHole3D> configure callback (configure sets HoleParameters after HoleType is assigned, because the type-specific sub-interface — e.g. ISpotfacingHoleParameters — is not accessible until the type is fixed). Base hole = ksHTBase + configure=null. hole_counterbore: ksHTCounterbore + configure sets (ISpotfacingHoleParameters)hole.HoleParameters (SpotfacingDiameter, SpotfacingDepth); validates spotDiameter>diameter and depth>spotDepth for blind. hole_countersink: ksHTCountersinking + configure sets (ICountersinkHoleParameters)hole.HoleParameters (CountersinkType=ksCTDiameterAngle, CountersinkDiameter, CountersinkAngle); validates sinkDiameter>diameter, 0<sinkAngle<180. hole_conic: ksHTConic + configure sets (IConicHoleParameters)hole.HoleParameters (ConicType=ksCNAngle, ConicAngle); validates 0<conicAngle<180. All four share common placement logic (IHoleDisposal+Points3D, direction selection by volume delta, orphan rollback). None enters the _features API5 registry → no id returned.
  • Draft operation (draft): implemented via API5 ksInclineDefinition (operation name in API5 is "Incline", not "Draft" — do NOT search for "Draft" in API5 docs). ksPart.NewEntity(o3d_incline=42)GetDefinition() as ksInclineDefinitionFaceArray() (add faces by index via SelectFaceByIndex, range-checked before mutation) → SetPlane(basePlane)angle (degrees) → directionCreate() → register in _features. Empirical: direction=false=expanding (outward, adds material), direction=true=tapering (inward) — opposite to the SDK docs → mapping in code: def.direction = !outward. Neutral plane set via SetPlane(base coordinate plane). Angle validation: RequireDraftAngle(0<angle<90, double.IsFinite). Returns feature id (registered in _features → patterns/mirror from package C apply). Note: o3d_DraftFromEdges=644 / IDraftFromEdges is a different "draft from edge baseline" operation — not used here.
  • Assembly class (AssemblyService, AssemblyTools, namespace Kompas.Mcp.Core.Assemblies): assembly_add_component — workflow (API7): IParts7.AddFromFile(path, ExternalFile=true, Redraw=true)IPart7part.Placement (IPlacement3D) → SetOrigin(x,y,z)part.UpdatePlacement(true)top.RebuildModel(true). Empirical: UpdatePlacement returns FALSE for a manually-positioned component (no mates) — this is NOT an error. RequireActiveAssembly validates doc.DocumentType == ksDocumentAssembly BEFORE accessing TopPart. Rollback on failure: RollbackInsertion via IFeature7.Delete + RebuildModel. Returns AddedComponent { Index, Name }. assembly_add_mate — workflow (API7): top.MateConstraints (IMateConstraints3D) → Add(MateConstraintType)BaseObject1/2 (faces via top.FindObjectsByPoint(x,y,z,FirstLevel=false)) → ParamValue (for distance) → Update()RebuildModel(true); check mate.Valid (false → error + rollback via mate.Owner.Delete). Own enum MateType { Coincidence, Distance } in src/Kompas.Mcp.Core/Assemblies/MateType.cs + static Mates (Parse/ToConstraintType/RequiresValue) mapping to КОМПАС MateConstraintType (mc_Coincidence=0, mc_Distance=5). Validator AssemblyValidation.RequireMateValue (distance value>0). Scope: coincidence/distance verified live; parallel/perpendicular/concentric/angle/tangency — future increments. DI: AddSingleton<AssemblyService>() in Program.cs.
  • Drawing service (drawing_create_standard_views, drawing_fill_title_block, drawing_add_linear_dimension, drawing_add_diametral_dimension; DrawingService, namespace Kompas.Mcp.Core.Drawings): entry via API7 IKompasDocument2D — requires an active drawing document (DocumentType==ksDocumentDrawing). Standard views: doc2d.ViewsAndLayersManager.Views.AddStandartViews(path, "#Спереди", projTypes, x, y, scale, dx=20, dy=20) where projTypes=object[]{1,3,5} (ksPtFront/ksPtUp/ksPtLeft passed as SAFEARRAY VT_I4). Success check: created==3 strictly; content check: sum of IView.ObjectCount for newly created views (identified by IView.Number delta) must be >0, otherwise error + rollback via IView.Delete. No rebuild needed — ObjectCount>0 immediately on a new drawing. Validation: DrawingValidation.NormalizeModelPath (accepts .m3d/.a3d), RequireScale>0. Model file must be saved (document_save_as) before calling. Returns DrawingViewsResult{Created,Total,ViewNumbers}ViewNumbers contains the IView.Number values of the three created views (used to address views when placing dimensions). Confirmed live: Views.Count 1→4 (system view + 3 projections). Title block / stamp (drawing_fill_title_block): doc2d.LayoutSheets.ItemByNumber[1].Stamp (IStamp) → stamp.Text[columnId].Str = text (indexed property, IText.Str replaces content — no Clear needed, overwrite confirmed) → stamp.Update(). Own enum StampField {Designation, Name, Material} + static StampFields.ColumnId (→ 2/1/3, ksStampEnum) and Collect (gathers non-empty trimmed fields). RequireStampCell validates null + columnId>0. RequireActiveDrawing shared with views check. Write is non-transactional (all cells → single Update). New file src/Kompas.Mcp.Core/Drawings/StampField.cs; tool added to existing DrawingTools.cs. Linear dimension (drawing_add_linear_dimension): places a linear dimension on a view of the active drawing. API7 path: locate view by viewNumber index → COM-QI (ISymbols2DContainer)view (dimension goes into that specific view, NOT to the sheet) → LineDimensions.Add()ILineDimension: set X1,Y1,X2,Y2 (extension point coordinates in view-local CS, mm), X3,Y3 (dimension line position), Orientation (ksLineDimensionOrientationEnum: ksLinDParallel=0/ksLinDHorizontal=1/ksLinDVertical=2), AutoNominalValue=trueUpdate() → check Valid → read value via ((IDimensionText)dim).NominalValue. Coordinates are in view-local coordinate system (not sheet). Parallel orientation works without explicit Angle (auto from points). Rollback: dim.Delete() if Update=FALSE / Valid=false / zero NominalValue (orientation incompatible with points). Key finding: dimensions are NOT counted in IView.ObjectCount (which counts geometry in IDrawingContainer); dimensions live in ISymbols2DContainer separately — verify placement via ISymbols2DContainer.LineDimensions.Count. Own enum DimensionOrientation {Horizontal, Vertical, Parallel} + DimensionOrientations.Parse/ToKompas. Validators DrawingValidation.RequireFiniteCoords + RequireDistinctPoints. New files: DimensionOrientation.cs, DrawingDimensionResult.cs; tool in existing DrawingTools.cs. Diametral dimension (drawing_add_diametral_dimension): places a diameter dimension (Ø) for a circle on a view. API7 path: shared helper RequireSymbols2DContainer(viewNumber) (reused by both linear and diametral paths) → DiametralDimensions.Add()IDiametralDimension: Xc, Yc, Radius (all in view-local CS, mm), Angle (leader direction in radians — converted from degrees via DimensionAngles.ToRadians, with overflow check), AutoNominalValue=trueUpdate() → check Valid((IDimensionText)dim).NominalValue == diameter (2·Radius). Dimension is "free" (no BaseObject — associative binding deferred). DimensionType not set (COM default). Validator DrawingValidation.RequirePositiveRadius. Invariant: returned value > 0. New helper DimensionAngles.ToRadians in DimensionOrientation.cs; RequirePositiveRadius in DrawingValidation.cs; tool in existing DrawingTools.cs. DI: AddSingleton<DrawingService>() in Program.cs.
  • Richer sketch primitives (package A, ksDocument2D API5 wrappers): ksArcBy3Points (3-point arc), ksArcByAngle (centre/radius/start-end angles in degrees, counterClockwise flag), ksEllipse via ksEllipseParam — struct obtained via KompasObject.GetParamStruct(ko_EllipseParam=22); property names are A/B (uppercase) in the interop; ksRegularPolygon via ksRegularPolygonParam (ko_RegularPolygonParam=92) — describe = !inscribed; NURBS spline via ksNurbs(order=4) + ksNurbsPoint loop + ksEndObj; ksPoint. Param structs are released after use. PartModeler split into partial classes: PartModeler.cs (registry/helpers/NewParam/reset), PartModeler.Sketch.cs (all 2D primitives), PartModeler.Features.cs (extrude/revolve/fillet/chamfer). Static SketchGeometry class (Core/Modeling) holds enum mappings (ArcDirection, PolygonDescribe) and validators (RequirePositive, RequireVertexCount, RequirePoints). Polyline/spline point lists use record SketchPoint(X, Y) with JSON names x/y.

КОМПАС-3D API architecture (the critical context)

КОМПАС-3D is automated via a COM Automation API, Windows-only. КОМПАС-3D must be installed and running/launchable on the same machine — the MCP server is a COM client, not a standalone CAD engine. There are two coexisting API generations:

Entry point Namespace (C#) Style Use when
API5 (legacy) KompasObject Kompas6API5 procedural, flat older features, 2D primitives, bootstrapping
API7 (modern, preferred) IApplication / _Application KompasAPI7 OOP, interface-based everything new — documents, 3D, parameters

Constants live in separate libraries: Kompas6Constants, Kompas6Constants3D (C#), or ksConstants.h / ksConstants3D.h (C++).

Connection pattern (verified from Samples/CSharp.zip)

  1. Get the КОМПАС root object by COM ProgID. Verified on this machine (v24 Home): KOMPAS.Application.7 and KOMPAS.Application.5 are registered; KOMPASLT.* is absent — the Home edition uses the regular (non-LT) ProgIDs. Resolution order:
    • KOMPAS.Application.7 — direct API7 IApplication (preferred)
    • KOMPAS.Application.5 — API5 KompasObject, then ksGetApplication7()
    • KOMPASLT.Application.5 — fallback for other installations
    • New instance: Activator.CreateInstance(Type.GetTypeFromProgID(progId))
    • Attach to a running instance: Marshal.GetActiveObject(progId)
  2. If you entered via API5, obtain the modern application: IApplication appl = (IApplication)kompas.ksGetApplication7(); (via KOMPAS.Application.7 you already hold IApplication).
  3. Set appl.Visible = true to show the КОМПАС window; drive documents via API7 interfaces (IKompasDocument2D, IKompasDocument3D, …).

The SDK C# samples are mostly КОМПАС plugin libraries (DLLs loaded into КОМПАС as ActiveX, entry methods like ExternalRunCommand/ExternalMenuItem, registered via [ComRegisterFunction]). For an MCP server we want the opposite direction: a standalone external automation client that connects out-of-process via the ProgID pattern above. Read the samples for API usage, not for the plugin packaging/registration boilerplate.

SDK layout (read-only reference, not part of this repo)

Under C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK:

  • lib\*.tlb — COM type libraries to reference / generate interop from: kAPI5.tlb, kAPI7.tlb, ksConstants.tlb, ksConstants3D.tlb, kAPI2D5COM.tlb, kAPI3D5COM.tlb.
  • lib64\ — 64-bit import libs (kAPI7.lib, kAPI5.lib, …) and .a for C++/Builder.
  • Include\ — C++/Pascal headers (Ks_TLB.h, kAPI2D5COM.h, LDefin2D.pas, …).
  • KsAPI\ — the KsAPI (Qt/C++ cross-platform flavour): Include\KsAPI.h, ksConstants*.h, Lib64\ksAPI.lib, plus Help\С чего начать.pdf and a Linux/Debian 12 build guide.
  • Samples\ — zipped examples per language: CSharp.zip, C++.zip, Pascal.zip, Basic.zip. Inside CSharp.zip, the Step1Step12 and Step2_API7_2D / Step2_API7_3D projects are the progressive tutorial; Gayka, SlideWrk, EventsAuto are larger feature demos.
  • Help\KOMPAS_SDK_ru-RU.zip and KsAPI\Help\KsAPI_Help.zip — offline copy of the docs.

To inspect a sample without unpacking the whole archive: unzip -p "<path>\Samples\CSharp.zip" "Automation/Step2_API7_3D/Step2_API7_3D.cs". Note the .cs sample sources are Windows-1251 encoded (Cyrillic comments appear garbled in UTF-8 tools).

Conventions / gotchas

  • Windows-only & 64-bit: target x64 to match the installed КОМПАС; mixing bitness breaks COM activation. КОМПАС v24 Home is the installed edition — some full-edition API features may be unavailable.
  • Encoding: SDK source samples are CP1251. New project files should be UTF-8.
  • COM lifetime: release COM objects (Marshal.ReleaseComObject) / scope them; a leaked reference keeps the КОМПАС process alive.
  • API choice: prefer API7 for new tool implementations; drop to API5 only for things API7 doesn't expose.