Skip to content

MCP Server ​

The extension ships a standalone MCP server (dist/mcpServer.js) that exposes its mesh and simulation-setup engine to any MCP client (Claude Code, Claude Desktop, …) — no VS Code needed. Anything the sidebar and palette can do to a mesh by path is reachable here; UI-only surfaces (preview layout, Inspect, What's New) are not.

Build it once with npm run compile, then register it, e.g. with Claude Code:

bash
claude mcp add kratos-mdpa -- node /abs/path/to/VSCode-MDPA-Preview/dist/mcpServer.js

or in a generic client config:

json
{ "mcpServers": { "kratos-mdpa": { "command": "node", "args": ["/abs/path/to/dist/mcpServer.js"] } } }
ToolWhat it does
mesh_infoParse any supported mesh (.mdpa, VTK family, .stl/.obj/.ply, and the extended meshio++ formats) and summarize nodes, blocks, SubModelParts, fields, diagnostics. Named groups from formats that carry them (gmsh physical groups, Abaqus sets, Exodus blocks/node sets/side sets) appear as SubModelParts. inputFormat forces a reader no extension defaults to (ansys, freefem, ansysinp). timeStep selects a step of a multi-step mesh (Exodus, MED since meshio++ 9.9.0, GiD postprocess, CGNS/Tecplot since 11.3.0, XDMF, VTKHDF, ParaView .pvd, OpenFOAM time directories); the response then includes timeStep/timeValues (Exodus, GiD, MED, CGNS, Tecplot, XDMF and OpenFOAM list theirs). metadataOnly skips parsing and reports the file header (counts, block shapes, data-array names, regions, bbox) for the formats whose reader stays header-only (.xdmf/.xmf, .msh, .med, .cgns, .dat/.tec, the GiD .post.* set) — anything else is refused rather than served at header price. An OpenFOAM case is opened through its .foam marker, like any other path. piece reads one piece of a .pvtu/.pvtp and dropGhosts (default true for those two) drops cells duplicated at partition seams; region reads one region of a multi-region OpenFOAM case instead of merging them all. summary is the universal counterpart: it reports the file shape for every supported format, including .mdpa and the natively-parsed VTK/STL/OBJ/PLY, and never refuses for ineligibility — it reports cost instead (header a bounded read, scan a whole-file stream that builds nothing, buffered/read the meshio++ paths that hold or parse the file), with bytesRead saying what it actually took and unknown naming what the format cannot report so a blank is not read as a zero. A mesh with one-node (sphere/particle) elements also reports a spheres section — how many, whether they carry a RADIUS, and a suggested radius if not. An .mdpa that declares Begin Properties also reports a properties section with the parsed values, one that declares Begin Constraints a constraints section (per block: name, variables, row count and id range, plus undefinedIds — constraint ids a SubModelPart lists that no block defines), and a mesh with line cells a beams section (how many carry a CROSS_AREA, and how many of those are Elements rather than boundary conditions). A mesh whose source carries a NURBS side channel (.cad.json, a .step/.igs file, an MFEM NURBS .mesh) also reports a nurbs section — the format and its patch/face counts — which is the gate mesh_derive's igaRefine/igaSample run behind (present only while the model is unedited)
mesh_qualityGeometric quality metrics (edge ratio, angles, gradation) with Kratos thresholds and worst-element ids, plus a watertight section: how many boundary edges (holes), non-manifold edges, inconsistently wound face pairs and zero-area faces — the counts rather than a bare flag, since three boundary edges is a pinhole and three thousand is a surface that was never closed
mesh_sizeNodal size (NODAL_H, a port of Kratos FindNodalHProcess) + element size (mean edge length), with box-whisker statistics and the IQR-outlier smallest/largest element ids
mesh_field_integrateCell-measure-weighted total and mean of the cell fields — a density field's total mass, a flux field's total power, an occupied volume — for the whole mesh and per named region, which here means one row per entity block and one per SubModelPart. Regions overlap rather than partition, so their totals need not sum to the domain total
mesh_curvatureDiscrete mean / Gaussian / principal curvature statistics of a surface mesh, the Gauss–Bonnet check (angle-defect sum vs 2πχ), boundary / isolated / degenerate node counts and orientation warnings — read-only; mesh_transform's curvature op writes the fields
mesh_graphThe connectivity graph of a mesh (meshio++ 18.1.0): kind node (nodes joined by a cell edge), clique (nodes sharing a cell — the FEM sparsity pattern) or cell (cells sharing a facet). Returns vertex and edge counts, the degree range and the bandwidth of the current numbering; with outputPath writes a METIS (.graph) or Scotch (.grf) file for a partitioner. Read-only.
mesh_intersectionsWhere a surface mesh intersects itself, or with otherPath where two surfaces interpenetrate or touch (exact triangle–triangle tests, meshio++ 18.0.0): clean, pair / coplanar / segment counts and the entity ids of the facets involved (capped by idLimit) — read-only; mesh_derive kind findIntersections writes the intersection curve as a line mesh
mesh_fit_primitivesNames the boundaries of a surface mesh by shape: segments it into patches (unless SEGMENT_PATCH exists) and reports per patch the plane / sphere / cylinder / cone / torus it matches, its radius and axis, and the fit residual; outputPath writes the integer FIT_PRIMITIVE field.
mesh_ale_qualityMesh validity over a moving-mesh (ALE/FSI) series: per frame, every Element on its deformed coordinates (default MESH_DISPLACEMENT) against the same element at the first frame — signed measure ratio, shape ratio, inverted count and ids, and the worst frame. .csv output.
mesh_recover_fluxPer-area traction / heat flux recovered on a SubModelPart's faces from nodal reactions (consistent boundary-mass projection, CG); its integral equals the reaction sum. Derived field <VAR>_RECOVERED; outputPath writes it.
mesh_compareCompare two meshes and their fields by entity id: a verdict (identical / equal within tolerance / different), moved nodes with the worst id, entities only in one mesh or with changed connectivity or type per kind, block-name and SubModelPart-membership differences, and per-field max / mean / RMS / relative error with coverage gaps counted (never compared as 0). With variable it also compares one field — by id, or by spatial point sampling of the other mesh's nodal field — and with outputPath writes the difference mesh (<name>_DIFF, _ABS, _REL). A field read from an OpenFOAM case carries its dimensions vector: mesh_info reports dimensions and unit per field, and the series, probe and table CSV headers gain [unit] only for such fields. When both fields state their dimensions and they differ the comparison is refused (naming convertFieldUnits); if one side is unknown it proceeds and says so
mesh_deriveWrite a new mesh derived from the opened one (nothing is written back to the input): a slice through a plane, the isosurface of a nodal field, a threshold region where a field lies in an absolute or normalized window, a decimated copy of a triangle surface, or a regular sampling of it — grid (a lattice from nothing, no input mesh needed), voxelize (occupancy) and sdfVolume (signed distance, dense or octree), sized by cellSize or resolution with a memory estimate and a 20-million-cell refusal before anything runs; a complete lattice can be written as .vti (survivors keep their ids and cell-field values). Slices and isosurfaces carry the interpolated fields and tag every cell with the cell it was cut from (SOURCE_ENTITY_ID / SOURCE_ENTITY_KIND); a threshold region keeps original ids, groups, fields, Properties and the conditions still on it, or returns its boundary surface. Normalized windows need an explicit fixed reference range — rescaling per frame is opt-in kind: "streamlines" traces STEADY streamlines of a Nodal vector field variable (RK4 in arc length through a pure-JS locator, no meshio++) from seedPoints, seedLine, seedPlane or seedPart (exactly one), forward/backward/both, bounded by maxSteps/maxLength/maxSeeds (more seeds are refused, not truncated), in the frame timeStep selects, and writes line cells with STREAM_SPEED/VELOCITY/ARCLENGTH and per-segment STREAM_LINE/SEED/DIRECTION/TERMINATION; every line ends for a stated reason and the reply lists the seeds that gave no line; a long trace reports per-seed progress as log lines. kinds igaRefine/igaSample (meshio++ 17.2.0) run the IGA kernel on the NURBS side channel the input CARRIES — a .cad.json, a .step/.igs file or an MFEM NURBS .mesh, unedited (any applied edit drops the channel): refine h/p-refines the patches (subdivisions per knot span/direction, elevate, B-rep edges/trim), sample tessellates them into Lagrange cells (sampleSubdivisions, trimSamples); both run on the lean build, keep the source untouched, and results do not carry the channel (write .cad.json/.mesh and reopen to refine again).
mesh_periodicMatch periodic SubModelPart nodes under an affine transform: every node of the slave part is mapped into the master part's frame and paired with its nearest match within atol (default 1e-8). The transform is exactly one of matrix (a finite row-major 4×4 affine), translate (three finite values) or rotate (a nonzero axis, an angle in degrees, an optional center). The reply reports original node ids with each pair's residual and the worst residual overall, plus the unmatched ids when the run was allowed to be partial — requireComplete (default true) refuses instead of returning a partial set. outputPath writes the pairs as CSV. This is a measurement, not a constraint authoring: it never writes into the mesh or the case. Same core as Advanced ▸ Mesh analysis and region tools ▸ Match periodic nodes
mesh_probeSample a nodal field along a polyline — distance-versus-value rows with a gap (null) wherever the path leaves the mesh or crosses a region the field was never written, never a fabricated 0 — optionally across every step of a time series, with CSV output
plot_table_readRead CSV/TSV independently of a mesh, with delimiter/header corrections, explicit numeric-column mapping, supplied units, missing/nonfinite gaps and SHA-256 revision; paginated JSON (default 100, max 10,000 rows)
plot_runsDiscover existing execution receipts and latest-run sidecars from explicit paths/directories (directory plus immediate child run directories; bounded). Terminal isolated results can be verified; legacy/shared outputs and live/uncertain runs remain unresolved. No active-case lookup or second run manager.
plot_run_bindPin a recorded terminal isolated result by verifying run/study/request IDs, source-mesh revision, selected rank/timeline/SubModelPart files and recursive index companions against the existing receipt's SHA-256 artifacts. OpenFOAM, Elmer and MFEM directory-backed sources additionally require a frozen complete inventoryRevision; removed/changed inputs, added directory trees and linked dependencies refuse ownership. Returns the recipe source's run binding; an available contradictory latest-run sidecar refuses it even when result bytes match. Collection checks it before/after extraction; live snapshots never substitute for bound disk values.
plot_time_cursorResolve physical time in its verified owning run: supplied units/mapping, exact or tolerance-bound nearest. Equal-distance ties and unmatched times return matched:false; changed ownership fails. Returns a frame index, never inferred cross-mesh entity correspondence or preview redirection.
plot_run_targetResolve an explicit frameIndex in a pinned source/rank timeline, optionally checking an entityKind + entityId or submodelpart in that exact frame. Returns the owning preview/frame paths and label after before/after verification. Shared with the UI's provider handoff; never opens a preview, uses the active case, or equates matching IDs across meshes.
plot_datasetEvaluate a version-1 scientific plot recipe through the shared cancellable host worker: table/inline/mesh/history/probe/region extraction, including regional reductions/reactions and boundary pressure/flux integrals, statistics, ordered numerical transforms, reference alignment and explicit masked gridding. A probe uses its explicit captured timeStep; followTimeline is UI intent, never an active-preview lookup. JSON samples are bounded (default 100, max 10,000 per series); optional CSV and .kratosplot.json provenance retain all derived/original values and regional conventions/coverage. See Scientific plots and FEM postprocessing.
plot_presetBuild a named plot recipe and optionally evaluate it — the headless twin of the Plots quick panel's Preset selector. sectionComparison (a field's boundary or entity mean over time for two or more SubModelParts), volumeTotal (a scalar Elemental field times element length/area/volume, per region or whole mesh), tensorComponents (one curve per component index, named by index only), tensorInvariants (von Mises, hydrostatic, principal values, … from a layout you must supply — full3x3, full2x2 or explicit {xx,yy,zz?,xy,yz?,xz?} indices — never inferred), heatFluxBalance (flux of a supplied nodal heat-flux vector through boundary sections, positive out of the domain) and tableRelationship (one supplied table column against another). An explicit pressureDensity (kg/m³) converts a kinematic-pressure field to Pa for the mean operations, never inferred. With evaluate (or a threshold) the recipe runs through the same worker as plot_dataset; threshold applies a user-supplied limit and direction (equality passes, gaps counted apart); differences reports from − to at exactly matching x. Without evaluate it returns only the validated recipe for plot_dataset. See Plot Presets.
mesh_flow_balanceSigned boundary flow balance: the flux ∫u·n dA through each named SubModelPart of Conditions (positive = out of the domain, so an inlet reads negative), the area-weighted mean of a nodal pressure on each, net flux, imbalance = net / max(inflow, outflow) (null with a reason when there is no flow) and an optional pressureDrop between two sections in the field's own units. orientation outward (default) flips each facet away from the Element it belongs to and excludes facets it cannot orient or that are internal; winding trusts the file. A corner with no value is a gap, reported as uncovered area, never 0; higher-order facets integrate as their linear skeleton and say so; 2D meshes give flux per unit depth; mass flux needs an explicit density. pressureDensity additionally reports means/drop in Pa for a kinematic-pressure field only. allSteps repeats over the whole series; outputPath writes a .csv
mesh_splitSplit one mesh into several files that keep the source's ids, kinds, Properties, SubModelParts and fields: partition writes N per-part meshes with optional ghost layers (every cell owned by exactly one part, ghosts flagged, weights by an elemental field, interface nodes and imbalance in the manifest — method: space-filling curve by default, kahip to minimize the edge cut, auto for KaHIP when available), or component / type / field split into connected bodies, element types or field values
mesh_transformApply a sequence of mesh operations (scale/translate/rotate, merge nodes, remove orphans, linear→quadratic, delete/rename SubModelPart, reorganize the SubModelPart tree (create / move / merge / add / remove entities), write mesh-size fields, set/scale the sphere-element RADIUS, MMG remesh & level-set split, smooth, reorder, partition, refine, simplexify, linear→linear-only (quadratic→linear), crop, field calculator + nodal/elemental averaging, field gradient/divergence/curl, field Hessian, Zienkiewicz-Zhu error estimate, signed distance to an imported surface, mass-preserving field transfer from another mesh, merge another mesh file) inline or from a saved Edit-sidebar recipe — returns an export report (what each kind of data did: retained / transformed / omitted / unverified); provenance (auto / sidecar / none) and verify (re-read and grade the report)
mesh_convertConvert between formats — ours (.mdpa, .vtk, .vtu, .vtp, .stl, .obj, .ply) plus ~40 written by meshio++ (.msh, .inp, .bdf, .unv, .mesh, .meshb (Medit binary, meshio++ 17.3.0), .vol, .su2, .xdmf, .off, .poly (Triangle), the HDF5 containers .cgns/.h5m/.hmf/.med, the solver result files .fil/.op2/.t19/.xplt/.rst (the last three gained writers in meshio++ 17.3.0), Kratos CAD JSON .cad.json (quads and lines), plus the field-only .dex/.ip/.mff and write-only .svg/.tikz figures, …); plus .e/.exo/.ex2 (Exodus, lossy — see the format table). inputFormat/outputFormat override the extension defaults; timeStep selects a step of a multi-step input (Exodus, MED, GiD postprocess, CGNS/Tecplot, XDMF, OpenFOAM time directories). piece, dropGhosts and region select the input as for mesh_info. Writing .xdmf also emits a companion <stem>.h5 — returns an export report (what each kind of data did: retained / transformed / omitted / unverified); provenance (auto / sidecar / none) and verify (re-read and grade the report). frd and radioss_th are additionally accepted as explicit outputFormat keys (meshio++ 16.41.0 gave both writers), but no export extension routes to either yet, so they are reachable only by key — mesh_capabilities reports them as unrouted with the reason. meshio++ 17.2.0 adds reads for .step/.stp/.igs/.iges (the full artifact's OpenCASCADE readers — the solid's triangulation) and .glb/.gltf (lean build), and makes .step a real export: a closed triangle skin is FITTED with fitCad into a B-rep that also lands beside the file as <stem>.cad.json (fitCad: false, a failed fit or a quad/open skin writes the faceted solid instead); pass fitCad options (tolerance, types, freeform, … — unknown keys are refused by the kernel) or false; the fit measures the solid against the skin it came from (faceDeviation, on unless the object says faceDeviation: false) and the report states the measured deviation and whether the solid is closed.
mesh_extract_submodelpartSlice one SubModelPart (+ subtree) into a standalone file — returns an export report (what each kind of data did: retained / transformed / omitted / unverified); provenance (auto / sidecar / none) and verify (re-read and grade the report)
mesh_extract_skinExtract the boundary skin of a mesh's volume cells (+ any pre-existing surface cells) as a standalone surface mesh — a native boundary-face walk, so SubModelParts survive (narrowed to node membership) — returns an export report (what each kind of data did: retained / transformed / omitted / unverified); provenance (auto / sidecar / none) and verify (re-read and grade the report)
mesh_field_seriesOne entity's value for one variable across every step of a time series — the headless mirror of the viewer's Plot over time, and the only tool that reads a value across steps. Steps are discovered from a single path exactly as the preview does (a sibling <prefix>_<rank>_<step> series (VTK, STL/OBJ/PLY and meshio formats without an in-file timeline), an in-file series such as Exodus/GiD/XDMF/OpenFOAM, or a lone file), and source reports which was found. A gap is null, never 0, with missingField and missingId counted apart; topologyChangedAt warns that the mesh changed size mid-series. Writes a .csv when outputPath is given
mesh_export_tableTabulate every node/element/condition/geometry as rows of plain values — id, coordinates or block+connectivity, optional SubModelPart membership, and every field defined there. The only tool that reports field values (mesh_info reports field metadata; mesh_find_entity answers for one id). With outputPath it writes the whole table as .csv/.xlsx; without one it returns limit rows from offset as JSON (default 100, max 10 000). submodelpart restricts rows to one part and its subtree
mesh_pack_seriesPacks a solver run's per-step mesh files into one time-series container. path is the vtk_output directory or any one step file; steps are found the same way the preview finds them (<prefix>_<rank>_<step>), and the step label becomes the time, so the axis carries the Kratos step numbers rather than 0..N-1. Not mesh_convert with outputFormat: xdmf — that writes ONE mesh, this writes every step. target picks the container, and the choice is semantic rather than cosmetic. "xdmf" (the default) writes one .xdmf plus its sibling .h5 — a single file, which is why the .h5 is part of the output rather than an extra — and refuses a series whose mesh changes between steps, since an XDMF time series carries one grid for all of them. "pvd" writes a .pvd index plus a <stem>/ directory of one file per step, each with its own mesh: the container for a remeshed, adaptive or moving-mesh run. It needs no mesh-format kernel, reuses a step's bytes when they are already VTK XML (so a Kratos run's .vtu steps are copied, not re-encoded), and accepts a source that already carries its own steps (Exodus, GiD, MED, CGNS, a packed XDMF or .pvd) — which "xdmf" refuses for lack of anything to combine. It will not overwrite an existing <stem>.pvd or <stem>/. Both containers stream one step at a time, and the result re-opens in the preview as a timeline, with topologyChangedAt on a .pvd whose steps differ in size
mesh_resampleExport a resampled timeline as .pvd (plus one .vtu per new step) or a single .vtu, so a run saved at inconvenient times becomes the times you asked for. Give explicit times or a range (start/stop/step); sourceTimes and useStepLabels keep the source's own time values, which is what keeps Kratos step numbers on the axis instead of 0…N−1. method is linear (default), previous or nearest: linear blending needs matching topology and metadata across the source steps and is refused for a mesh that changes shape. Integer fields are never blended, and an unknown field must be named in continuousFields (or fall back to nearest). extrapolate: "error" (default) refuses a target time outside the source range; clamp reuses the nearest end. Source files are never modified, and each new frame returns its own export report (sidecar adds one collection roll-up)
mesh_find_entityLocate a node/element/condition/geometry by id (coordinates, connectivity, owning SubModelParts)
mesh_capabilitiesmeshio++ capability inventory: the installed WASM build's readers/writers, per-reader options-awareness, backend and cgnslib — next to the extension's routing (read candidates, write targets, in-file vs filename timelines, header-only metadata set, unrouted keys with reasons) and a fidelity section (the carry/adopt adapter's carrier keys, SubModelPart region prefix, and which model slots it retains). Takes no arguments and an exportFidelity section (what each writer was measured to keep)
problemtype_list / problemtype_describeEnumerate built-in + workspace problemtypes (with their family, domains and collections); get the full form/condition/material/collection spec plus a default case skeleton
case_runStart a Kratos solve (generating the case files first unless told not to). Optional threads is applied and read back through Kratos ParallelUtilities before analysis construction; owned execution receipts include resource counts and revisioned configured outputs. The solver is always spawned detached, with its output appended to <stem>.kratosrun.log, so it outlives the MCP server — which cannot own a run, since its stdout is the protocol channel. waitSeconds (default 10, 0 = don't wait) blocks for the exit; expiry is not an error but a handoff, returning running with the pid and log path, since the only applicable timeout belongs to the client and the server cannot observe it. Refuses to start over a run that may still be active unless forced. python / installPath / extraEnv are arguments, defaulting to a pip-installed Kratos. Before starting, it asks python whether every Kratos application the case needs (recorded in kkss-preparation-v1.json) can be imported and refuses naming the missing ones; when that probe cannot answer, the run starts and the generated driver's own check (exit code 3) stands behind it. With requestId + ownerId + runDirectory it snapshots the mesh and case state into that fresh directory and writes a durable .kkss-execution.json receipt (the retry key: the same identity never dispatches twice). With isolate: true it plans <case folder>/runs/<stem>-<requestId> itself instead of taking runDirectory, using the same layout as the sidebar's kratos.run.isolate; studyId / clonedFrom label the run in kkss-preparation-v1.json without ever touching an earlier run's files.
case_compareCompare two saved isolated runs by the evidence each owns — its execution receipt and its kkss-preparation-v1.json — never by matching file names, so two cases sharing a source folder cannot be confused. Each side is a run directory or its .kkss-execution.json. Reports both identities (requestId, ownerId, jobId, state), whether they name the same source-mesh revision, problemtype, settings and CAD export revision, every differing setting as a dotted path with both values, per-role artifact counts, artifacts only one side has, outputs whose frozen revision differs, and paired outputs whose bytes neither side pinned (unverified, not silently "unchanged"). comparable: false with problems when a side is not a terminal isolated run, has no receipt, or both sides name the same directory; it never hashes today's bytes to upgrade a legacy receipt.
case_run_quantityOne monitor evaluated once per isolated run: a row per run with the case settings that differ between runs as columns and the monitor's final value — a parameter sweep as a table. .csv output.
case_stopStop the latest run by the pid in its sidecar. First writes the cooperative stop file (<stem>.kratosstop) that a case generated by this extension watches between solution steps, so the solver finalizes and closes its last result file on every platform, Windows included; if it does not answer within the grace period (or the script predates the file) it escalates SIGINT → SIGTERM → SIGKILL (Windows: immediate terminate — signals are not real there). Reports which rung worked (outcome / stopRung) — SIGINT is what lets python close its last result file rather than truncate it. Records the stop before signalling so it reads cancelled, not failed. A run that already ended is never signalled, since pids get reused
wind_tunnel_planPlan a virtual wind tunnel around a body surface without meshing anything: the body as measured (size, frontal area, whether it is closed), the tunnel extents and blockage, the flat-plate boundary layer (Reynolds number, friction velocity, first-cell height for a target y+, layers), the cell sizes, an estimate of tetrahedra, memory and time, the ordered steps, warnings and errors (a plan with errors cannot run). Read-only.
wind_tunnel_generateBuild the tunnel: a graded background lattice, distance-driven refinement with a wake box, a level-set carve of the body, the named parts (Fluid, Body, Inlet, Outlet, Floor, Ceiling, SideLow/SideHigh or Symmetry), a stretched-tetrahedron wall layer (remesh mode wall), hard mesh checks and a measured wall fit — or, in embedded mode, the unfitted lattice with the signed DISTANCE. Writes <stem>.mdpa, the placed <stem>_body.stl, <stem>.kratosvwt.json (parameters, report) and the prepared Fluid (or Embedded Fluid) case <stem>.kratoscase.json; with generateCase also the solver files. Refuses to overwrite unless overwrite; reports progress and stops between steps on cancellation.
case_export_resultsConvert a case's solver output (vtk_output/) to other meshio++ formats: .xdmf/.pvd pack the series into one file, every other format gets one file per step in converted/. formats defaults to the case's saved output.exportFormats; an unwritable format is skipped with its reason.
case_convergenceThe solver convergence history of a case, read from the kkss-convergence-v2.jsonl the generated MainKratos.py writes: per-step residual norm, convergence ratio, nonlinear iteration count and the solver's own converged flag, with CSV output. Progress, completion, per-step convergence and the verdict are reported apart; the verdict is conservative — converged needs a completed run, a run with no end record is incomplete, a solve-hook exception is solver-error (an unknown outcome, never proof of divergence), and a residual the solver did not publish is null, never 0. case_status carries a compact copy
case_optimizationThe progress of a Structural Optimization case, read from the per-iteration summary the OptimizationApplication's ascii output process writes (the file optimization_parameters.json names, summary.csv by default): the formulation, the objective's current value and change since the first iteration, each constraint's value and standardized value (satisfied when ≤ 0, unknown when the column is absent), and a verdict — finished, stopped (a cooperative stop finalizes the run), running, incomplete (no end-of-file marker: killed or crashed) or no-data. Columns are classified by the case's own response names. Bounded rows (limit, default 200) or every row as .csv. case_status carries a compact copy
case_optimization_cadThe optimized geometry of a Structural Optimization case as STEP: the latest finished design-field frame through the .step pipeline (shape writes the frame mesh; topology contours densityField at threshold, default 0.5, averaging an Elemental field to the nodes). fitCad as in mesh_convert, outputPath defaulting to <case>_optimized.step, excludeNewest dropping a possibly half-written newest frame. Refusals name the cause (no case, no design fields, no frames, unknown field, uncrossed threshold, no skinnable surface)
case_romThe results of a reduced-order model case: modes from rom_data/RomParameters.json, the singular-value decay, the HROM element and condition ids (Kratos entity ids), the sampled parameters from RomSamples.json, the per-analysis progress the generated driver records and its end summary. A stopped run is reported as a partial database. Lists bounded by limit. case_status carries a compact copy
case_monitorsSaved post-run monitors of a case, stored in <stem>.kratosmonitors.json: a point value of a field at one entity or a regional quantity (min, max, mean, sum, boundary mean or integral, pressure force or moment, flux, reaction moment) over a SubModelPart. Actions list, set, remove and evaluate; evaluation reads the case's current saved result frames with the plotting library's extraction, supports stride thinning and a unit label, returns bounded rows or a full .csv, and reports a missing field, entity or frame as a null gap, never 0. A point source interpolates a Nodal field at fixed coordinates. Not a live solver monitor; it makes no run-ownership claim unless a run binding from plot_run_bind is passed with resultPath, which is then verified.
case_statusThe latest Kratos run for a mesh: status, exit code, command, pid and a result summary discovered from generated output-process settings. Reports configured VTK, XDMF/HDF5 and GiD result entrypoints/companions plus missing or unsupported outputs; legacy cases without settings keep the vtk_output/ fallback. Reads the <stem>.kratosrun.json sidecar and reconciles it against the OS rather than repeating it, so a stale record whose process is gone reads orphaned and one whose pid is alive reads detached, never running
case_validate / case_write_statePreflight a case setup against mesh + problemtype as structured findings (severity error/warning/info, a stable code, a target naming the SubModelPart / condition / law / Properties id); write <stem>.kratoscase.json (picked up by the sidebar). The check is a dry run of generation, so ok: true means the case generates — including unusable material values, bad fluid time-stepping values and coupled-domain interface problems. It adds computing parts with no material, empty / wrong-kind / unused SubModelParts, dangling or unused Properties ids, mesh fields a problemtype expects (field-missing / field-shape warnings, advisory — Embedded Fluid reading its nodal DISTANCE field is the first) and mesh-wide quality concerns (quality: false skips those). With checkInstall: true (and optional python / installPath / extraEnv) it also reports install.missingApplications, the Kratos applications the case needs that the given Python cannot import; applications lists what the case needs either way. For coupled problemtypes the interface sides must pair one-to-one, carry boundary cells of the right dimension and overlap. A CAD-Preview handoff beside the mesh (<mesh>.handoff.json) is consumed too: unresolved CAD Parts the case assigns to, unassigned boundary surfaces, overlapping Part groups, a non-unit export scale factor, and a manifest that no longer matches the mesh after a remesh. case_generate records that export's identity (handoff: {source, sourceRevision, replay}, names and hashes only) in kkss-preparation-v1.json.
case_estimate_timestepRead-only convective time-step guidance dt = safety × Courant × h / |U| for a mesh: the length basis used (a thin smallest element switches to its shortest edge and says so; a mesh with no measurable elements falls back to bounding-box volume/diagonal per node and says so), flow-through time and, with endTime/outputInterval, step count, output frames and a rough storage range. Guidance, not a stability guarantee; zero velocity or no usable bounds is reported as unavailable. Apply a chosen step with case_write_state
case_material_assignFill one SubModelPart's material from a catalog preset or from explicit values, and write the case file. A preset is applied as a snapshot — the resolved numbers plus the row's source, version and reference conditions are copied into the case, so editing the library afterwards never rewrites it. A preset quoting kinematic viscosity and density fills DYNAMIC_VISCOSITY as μ = ρ·ν, exactly once per application; the reply reports the conversions and derivations it performed. One material per SubModelPart, so an existing assignment is replaced
material_preset_list / material_preset_importThe material catalog: the rows shipped with the extension plus every workspace library file under <workspace>/.kratos/materials/*.json, each with the laws it fits, its values and units, its reference conditions and its source. law filters to what a constitutive law can be filled from, outputPath writes the selection as an importable JSON file, and material_preset_import validates a file and installs it into the library — refusing a row with no source, a non-numeric value, or a name that would overwrite a different file
case_generateWrite ProjectParameters.json, the materials JSON and MainKratos.py next to the mesh — same output as the sidebar's Generate button, including solver mesh-name adaptation (a non-.mdpa mesh is always converted to <stem>_case.mdpa first)
problem_pack / problem_unpackBundle the whole problem (mesh + edit recipe + case state + generated case files) into one zip, or extract such an archive — the same format as the File menu's Save problem… / Load problem…

MMG operations run in-process and block the server while they run; progress is streamed as MCP log messages.

Export reports and provenance ​

Single-mesh write tools, including mesh_compare with outputPath, return report and accept provenance (auto / sidecar / none) and verify (re-read and grade). mesh_split persists per-file reports in its manifest/reply; mesh_batch_transform persists each entry's report, preserving it on resume. mesh_pack_series and mesh_resample return compact per-step reports with named category ids, warnings and provenance; sidecar writes one collection roll-up. Structured VTI and temporal XDMF paths explicitly disclose unverified fidelity rather than borrowing another writer's claims. problem_pack embeds a source/recipe/version/hash record inside the ZIP without rewriting pristine mesh bytes (provenance: "none" opts out).

mesh_capabilities.exportFidelity version 2 publishes references and per-reference writer rows (hex/quad, tetra/triangle, tetra-only, triangle-only). Claims use the narrowest covering fixture; Conditional scalar/vector fields are now measured. Unknown shapes and failed round trips stay unverified. Native MDPA/VTK XML/OBJ/PLY support provenance comments, legacy VTK has a bounded title, and STL has no safe slot. Export Report & Provenance explains the shared UI/MCP report and format limits.

Released under the GNU AGPL-3.0-or-later License.