kratos-mcp-server 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kratos_mcp_server-0.1.1/.github/workflows/ci.yml +53 -0
- kratos_mcp_server-0.1.1/.github/workflows/docs.yml +45 -0
- kratos_mcp_server-0.1.1/.github/workflows/release.yml +51 -0
- kratos_mcp_server-0.1.1/.gitignore +10 -0
- kratos_mcp_server-0.1.1/CLAUDE.md +115 -0
- kratos_mcp_server-0.1.1/LICENSE +21 -0
- kratos_mcp_server-0.1.1/PKG-INFO +99 -0
- kratos_mcp_server-0.1.1/README.md +86 -0
- kratos_mcp_server-0.1.1/docs/.vitepress/config.ts +59 -0
- kratos_mcp_server-0.1.1/docs/guide/architecture.md +117 -0
- kratos_mcp_server-0.1.1/docs/guide/connecting.md +87 -0
- kratos_mcp_server-0.1.1/docs/guide/getting-started.md +75 -0
- kratos_mcp_server-0.1.1/docs/guide/installation.md +88 -0
- kratos_mcp_server-0.1.1/docs/guide/mdpa-format.md +123 -0
- kratos_mcp_server-0.1.1/docs/guide/troubleshooting.md +95 -0
- kratos_mcp_server-0.1.1/docs/index.md +56 -0
- kratos_mcp_server-0.1.1/docs/tools/environment.md +152 -0
- kratos_mcp_server-0.1.1/docs/tools/index.md +37 -0
- kratos_mcp_server-0.1.1/docs/tools/mesh.md +79 -0
- kratos_mcp_server-0.1.1/docs/tools/postprocessing.md +70 -0
- kratos_mcp_server-0.1.1/docs/tools/prompts.md +43 -0
- kratos_mcp_server-0.1.1/docs/tools/resources.md +25 -0
- kratos_mcp_server-0.1.1/docs/tools/scaffolding.md +124 -0
- kratos_mcp_server-0.1.1/docs/tools/simulation.md +71 -0
- kratos_mcp_server-0.1.1/docs/tutorials/cantilever-beam.md +123 -0
- kratos_mcp_server-0.1.1/docs/tutorials/thermal-bar.md +90 -0
- kratos_mcp_server-0.1.1/package-lock.json +2346 -0
- kratos_mcp_server-0.1.1/package.json +14 -0
- kratos_mcp_server-0.1.1/pyproject.toml +37 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/__init__.py +0 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/bridge.py +144 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/jobs.py +232 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/kratos_env.py +178 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/logparse.py +88 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/mdpa.py +435 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/runner.py +115 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/server.py +43 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/source_catalog.py +141 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/fluid_transient/Materials.json.tpl +16 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/fluid_transient/ProjectParameters.json.tpl +95 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/registry.json +211 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/structural_dynamic/Materials.json.tpl +17 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/structural_dynamic/ProjectParameters.json.tpl +75 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/structural_modal/Materials.json.tpl +17 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/structural_modal/ProjectParameters.json.tpl +55 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/structural_static/Materials.json.tpl +17 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/structural_static/ProjectParameters.json.tpl +69 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/thermal_stationary/Materials.json.tpl +14 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/thermal_stationary/ProjectParameters.json.tpl +88 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/thermal_transient/Materials.json.tpl +14 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/templates/thermal_transient/ProjectParameters.json.tpl +85 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/__init__.py +10 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/environment.py +253 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/mesh.py +130 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/postprocess.py +166 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/prompts.py +86 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/resources.py +231 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/scaffold.py +545 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/tools/simulation.py +97 -0
- kratos_mcp_server-0.1.1/src/kratos_mcp/worker.py +237 -0
- kratos_mcp_server-0.1.1/tests/conftest.py +23 -0
- kratos_mcp_server-0.1.1/tests/smoke_client.py +50 -0
- kratos_mcp_server-0.1.1/tests/test_bridge_integration.py +63 -0
- kratos_mcp_server-0.1.1/tests/test_jobs.py +92 -0
- kratos_mcp_server-0.1.1/tests/test_kratos_env.py +62 -0
- kratos_mcp_server-0.1.1/tests/test_logparse.py +45 -0
- kratos_mcp_server-0.1.1/tests/test_mdpa.py +110 -0
- kratos_mcp_server-0.1.1/tests/test_run_integration.py +121 -0
- kratos_mcp_server-0.1.1/tests/test_source_catalog.py +52 -0
- kratos_mcp_server-0.1.1/tests/test_templates.py +80 -0
- kratos_mcp_server-0.1.1/uv.lock +1326 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: Unit tests (Python ${{ matrix.python-version }})
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: astral-sh/setup-uv@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: uv sync
|
|
22
|
+
- name: Run unit tests (Kratos integration tests are skipped without a build)
|
|
23
|
+
run: uv run pytest -m "not kratos" -q
|
|
24
|
+
|
|
25
|
+
build-package:
|
|
26
|
+
name: Build Python package
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
needs: test
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- uses: astral-sh/setup-uv@v5
|
|
32
|
+
- name: Build sdist and wheel
|
|
33
|
+
run: uv build
|
|
34
|
+
- uses: actions/upload-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: python-package
|
|
37
|
+
path: dist/*
|
|
38
|
+
|
|
39
|
+
build-docs:
|
|
40
|
+
name: Build documentation
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: actions/setup-node@v4
|
|
45
|
+
with:
|
|
46
|
+
node-version: 20
|
|
47
|
+
cache: npm
|
|
48
|
+
- run: npm ci
|
|
49
|
+
- run: npm run docs:build
|
|
50
|
+
- uses: actions/upload-artifact@v4
|
|
51
|
+
with:
|
|
52
|
+
name: docs-site
|
|
53
|
+
path: docs/.vitepress/dist
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Deploy docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: 20
|
|
25
|
+
cache: npm
|
|
26
|
+
- run: npm ci
|
|
27
|
+
- name: Build with VitePress
|
|
28
|
+
run: npm run docs:build
|
|
29
|
+
env:
|
|
30
|
+
# Serve from https://<user>.github.io/<repo>/
|
|
31
|
+
DOCS_BASE: /${{ github.event.repository.name }}/
|
|
32
|
+
- uses: actions/configure-pages@v5
|
|
33
|
+
- uses: actions/upload-pages-artifact@v3
|
|
34
|
+
with:
|
|
35
|
+
path: docs/.vitepress/dist
|
|
36
|
+
|
|
37
|
+
deploy:
|
|
38
|
+
needs: build
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
environment:
|
|
41
|
+
name: github-pages
|
|
42
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
43
|
+
steps:
|
|
44
|
+
- id: deployment
|
|
45
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: astral-sh/setup-uv@v5
|
|
13
|
+
- name: Run unit tests
|
|
14
|
+
run: uv sync && uv run pytest -m "not kratos" -q
|
|
15
|
+
- name: Build sdist and wheel
|
|
16
|
+
run: uv build
|
|
17
|
+
- uses: actions/upload-artifact@v4
|
|
18
|
+
with:
|
|
19
|
+
name: dist
|
|
20
|
+
path: dist/*
|
|
21
|
+
|
|
22
|
+
github-release:
|
|
23
|
+
needs: build
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
permissions:
|
|
26
|
+
contents: write
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/download-artifact@v4
|
|
29
|
+
with:
|
|
30
|
+
name: dist
|
|
31
|
+
path: dist
|
|
32
|
+
- name: Create GitHub release with artifacts
|
|
33
|
+
uses: softprops/action-gh-release@v2
|
|
34
|
+
with:
|
|
35
|
+
files: dist/*
|
|
36
|
+
generate_release_notes: true
|
|
37
|
+
|
|
38
|
+
publish-pypi:
|
|
39
|
+
# Publishes via PyPI trusted publishing; configure the 'pypi' environment
|
|
40
|
+
# and a trusted publisher on pypi.org before the first release.
|
|
41
|
+
needs: build
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
environment: pypi
|
|
44
|
+
permissions:
|
|
45
|
+
id-token: write
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/download-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: dist
|
|
50
|
+
path: dist
|
|
51
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Kratos MCP Server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server exposing Kratos Multiphysics to AI
|
|
4
|
+
assistants: installation introspection, case scaffolding (ProjectParameters /
|
|
5
|
+
Materials / MDPA meshes), simulation execution as background jobs, and VTK
|
|
6
|
+
post-processing. Python, `mcp` SDK (FastMCP), stdio transport.
|
|
7
|
+
|
|
8
|
+
## Environment
|
|
9
|
+
|
|
10
|
+
A local compiled build is optional: `src/kratos_mcp/kratos_env.py` resolves
|
|
11
|
+
Kratos from, in order, an explicit `KRATOS_PYTHONPATH`/`KRATOS_LIBS`, a
|
|
12
|
+
`KRATOS_ROOT` build tree, or a pip-installed `KratosMultiphysics` importable
|
|
13
|
+
by the server's own interpreter.
|
|
14
|
+
|
|
15
|
+
- `KRATOS_ROOT` (default `/home/vicente/src/Kratos`) → uses
|
|
16
|
+
`$KRATOS_ROOT/bin/Release` as `PYTHONPATH` and `$KRATOS_ROOT/bin/Release/libs`
|
|
17
|
+
as `LD_LIBRARY_PATH`.
|
|
18
|
+
- Overrides: `KRATOS_PYTHONPATH`, `KRATOS_LIBS`, `KRATOS_SOURCE` (source tree
|
|
19
|
+
for macro parsing), `KRATOS_EXTRA_LIBS` (extra lib dirs; MKL under
|
|
20
|
+
`/opt/intel/oneapi/mkl/latest/lib` is auto-detected — LinearSolversApplication
|
|
21
|
+
needs `libmkl_rt.so.2`).
|
|
22
|
+
- **Pip fallback**: if no build tree resolves, `kratos_env.resolve()` probes
|
|
23
|
+
`python -c "import KratosMultiphysics"` in a subprocess. The `kratos_install`
|
|
24
|
+
tool (`tools/environment.py`) populates this by running `pip install` —
|
|
25
|
+
official wheels are `KratosMultiphysics` (core), `Kratos<AppName>` per
|
|
26
|
+
application (e.g. `KratosStructuralMechanicsApplication`), or
|
|
27
|
+
`KratosMultiphysics-all` (everything) — Linux/Windows x86_64 only, no macOS
|
|
28
|
+
wheels. `kratos_env.pip_install()`/`pypi_package_name()` do the mapping and
|
|
29
|
+
subprocess call; running pip itself is fine in the server process (it never
|
|
30
|
+
imports Kratos), unlike everything else Kratos-related.
|
|
31
|
+
- Manual incantation for ad-hoc Kratos scripts against a build tree:
|
|
32
|
+
`PYTHONPATH=$KRATOS_ROOT/bin/Release LD_LIBRARY_PATH=$KRATOS_ROOT/bin/Release/libs:/opt/intel/oneapi/mkl/latest/lib python3 ...`
|
|
33
|
+
- Server state (jobs, bridge cache) lives in `~/.kratos-mcp/`
|
|
34
|
+
(`KRATOS_MCP_HOME` overrides; tests set it to a tmp dir).
|
|
35
|
+
|
|
36
|
+
## The one hard rule
|
|
37
|
+
|
|
38
|
+
**Never import KratosMultiphysics in the server process.** It prints an ASCII
|
|
39
|
+
banner on import (corrupts the stdio JSON-RPC stream) and its C++ core can
|
|
40
|
+
abort the process. All Kratos access goes through subprocesses:
|
|
41
|
+
|
|
42
|
+
- `bridge.py` → spawns `worker.py` for short ops (introspection, validation,
|
|
43
|
+
deep mdpa read). Results travel via a `--result-file` JSON file, never
|
|
44
|
+
stdout. Cacheable ops are cached on disk keyed by build fingerprint.
|
|
45
|
+
- `jobs.py` → spawns `runner.py` detached for simulations. Job state persists
|
|
46
|
+
in `~/.kratos-mcp/jobs/<id>/` (`meta.json` + `stdout.log`) and survives
|
|
47
|
+
server restarts; orphaned jobs are re-evaluated from pid liveness + log tail.
|
|
48
|
+
|
|
49
|
+
`worker.py` and `runner.py` are the ONLY modules that import Kratos, and they
|
|
50
|
+
only run inside subprocesses with the env vars injected.
|
|
51
|
+
|
|
52
|
+
## Commands
|
|
53
|
+
|
|
54
|
+
- `uv sync` — install deps (`mcp`, `meshio`, `numpy`; dev: pytest)
|
|
55
|
+
- `uv run kratos-mcp` — run the server (stdio)
|
|
56
|
+
- `uv run pytest -m "not kratos"` — unit tests, no Kratos needed
|
|
57
|
+
- `uv run pytest -m kratos` — integration tests against the real build
|
|
58
|
+
(cantilever + thermal bar end-to-end with physics assertions)
|
|
59
|
+
- `uv run python tests/smoke_client.py` — scripted stdio MCP client smoke test
|
|
60
|
+
- `npm run docs:dev` / `npm run docs:build` — VitePress docs
|
|
61
|
+
|
|
62
|
+
## Layout
|
|
63
|
+
|
|
64
|
+
- `src/kratos_mcp/server.py` — FastMCP instance + main()
|
|
65
|
+
- `src/kratos_mcp/tools/` — one module per tool category (`environment`,
|
|
66
|
+
`scaffold`, `mesh`, `simulation`, `postprocess`, `resources`, `prompts`),
|
|
67
|
+
each exposing `register(mcp)`; `register_all` in `__init__.py`
|
|
68
|
+
- `src/kratos_mcp/mdpa.py` — pure-Python MDPA parse/write/inspect/validate +
|
|
69
|
+
structured mesh generators (line/rectangle/box with named boundary parts)
|
|
70
|
+
- `src/kratos_mcp/source_catalog.py` — parses `KRATOS_REGISTER_ELEMENT/
|
|
71
|
+
CONDITION/CONSTITUTIVE_LAW` macros from the Kratos C++ sources (there is no
|
|
72
|
+
runtime registry for these)
|
|
73
|
+
- `src/kratos_mcp/templates/` — case templates as data: `registry.json`
|
|
74
|
+
(metadata + placeholder defaults) + `<name>/ProjectParameters.json.tpl` +
|
|
75
|
+
`Materials.json.tpl`. Substitution: quoted `"{{key}}"` → JSON-typed value,
|
|
76
|
+
bare `{{key}}` → text.
|
|
77
|
+
- `src/kratos_mcp/logparse.py` — step/convergence extraction from job logs
|
|
78
|
+
|
|
79
|
+
## Kratos gotchas learned the hard way
|
|
80
|
+
|
|
81
|
+
- Load-bearing conditions must be the `*LoadCondition*` types
|
|
82
|
+
(`LineLoadCondition2D2N`, `SurfaceLoadCondition3D4N`); the generic
|
|
83
|
+
`LineCondition2D2N`/`SurfaceCondition3D4N` are geometric dummies that
|
|
84
|
+
silently contribute nothing (zero RHS, zero displacement).
|
|
85
|
+
- The convection-diffusion solver REPLACES mesh elements at import
|
|
86
|
+
(`element_replace_settings`); thermal meshes use generic `Element2D3N` +
|
|
87
|
+
`ThermalFace2D2N`. It must be a simplex mesh (triangles/tets) — its
|
|
88
|
+
`TetrahedralMeshOrientationCheck` fails on quads with "condition without
|
|
89
|
+
any corresponding element".
|
|
90
|
+
- `solver_type: stationary` still defaults to the transient EulerianConvDiff
|
|
91
|
+
element; true steady state needs `element_replace_settings: {"element_name":
|
|
92
|
+
"LaplacianElement", ...}` (our `thermal_stationary` template does this).
|
|
93
|
+
- Static analyses run exactly one step via `time_step: 1.1 > end_time: 1.0`
|
|
94
|
+
(standard Kratos test convention).
|
|
95
|
+
- `Kernel.Get*VariableNames()` return one newline-separated string, not lists.
|
|
96
|
+
- `KM.Parameters` tolerates `//` comments; plain `json.loads` on Kratos test
|
|
97
|
+
files may fail.
|
|
98
|
+
- Kratos resolves mdpa/materials paths relative to the CWD → `runner.py`
|
|
99
|
+
chdirs into the case directory.
|
|
100
|
+
|
|
101
|
+
## Conventions
|
|
102
|
+
|
|
103
|
+
- All server logging to stderr (stdout is the MCP transport).
|
|
104
|
+
- Tools return plain dicts; errors as `{"error": ...}` rather than raising
|
|
105
|
+
(bridge failures include worker stdout/stderr tails for diagnosis).
|
|
106
|
+
- Blocking work inside async tools goes through `anyio.to_thread.run_sync`.
|
|
107
|
+
- Tool inputs/outputs use absolute paths.
|
|
108
|
+
- Reference cases used for templates/tests:
|
|
109
|
+
`applications/StructuralMechanicsApplication/tests/LinearTruss2D/2D2N/` and
|
|
110
|
+
`applications/ConvectionDiffusionApplication/tests/basic_conv_diffusion_test/`
|
|
111
|
+
in the Kratos tree.
|
|
112
|
+
|
|
113
|
+
## Keep docs in sync
|
|
114
|
+
|
|
115
|
+
Every time you change code in this repo, check whether doc/, README.md, and this file need updating too — and update them if they do. Treat doc drift as part of the change, not a follow-up.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vicente Mataix Ferrándiz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kratos-mcp-server
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: MCP server for Kratos Multiphysics: scaffold, run and post-process finite element simulations
|
|
5
|
+
Author: Vicente Mataix Ferrándiz
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: mcp>=1.2
|
|
10
|
+
Requires-Dist: meshio>=5.3
|
|
11
|
+
Requires-Dist: numpy>=1.26
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Kratos MCP Server
|
|
15
|
+
|
|
16
|
+
[](https://github.com/loumalouomega/Kratos-MCP-Server/actions/workflows/ci.yml)
|
|
17
|
+
[](https://loumalouomega.github.io/Kratos-MCP-Server/)
|
|
18
|
+
[](https://github.com/loumalouomega/Kratos-MCP-Server/releases)
|
|
19
|
+
[](https://pypi.org/project/kratos-mcp-server/)
|
|
20
|
+
[](https://www.python.org/)
|
|
21
|
+
[](LICENSE)
|
|
22
|
+
|
|
23
|
+
An [MCP](https://modelcontextprotocol.io) server that lets AI assistants drive
|
|
24
|
+
[Kratos Multiphysics](https://github.com/KratosMultiphysics/Kratos) finite
|
|
25
|
+
element simulations end to end:
|
|
26
|
+
|
|
27
|
+
- **Introspect** the installation: applications, elements, conditions,
|
|
28
|
+
constitutive laws, variables, solvers and their default parameters.
|
|
29
|
+
- **Scaffold** simulation cases from templates: structural
|
|
30
|
+
(static/dynamic/modal), thermal (transient/stationary) and fluid
|
|
31
|
+
(transient incompressible) — ProjectParameters.json, Materials.json and
|
|
32
|
+
structured MDPA meshes with named boundary regions.
|
|
33
|
+
- **Run** simulations as managed background jobs (status, live logs,
|
|
34
|
+
progress, cancel) that survive server restarts.
|
|
35
|
+
- **Post-process** VTK results: summaries, point probes, convergence
|
|
36
|
+
analysis.
|
|
37
|
+
|
|
38
|
+
31 tools, 7 resources and 4 guided prompts. See the full documentation in
|
|
39
|
+
[`docs/`](docs/) (VitePress).
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
A local Kratos build is **not required** — the server can pip-install
|
|
44
|
+
Kratos itself on first use.
|
|
45
|
+
|
|
46
|
+
**Once published to PyPI**, no clone needed — `uvx` fetches and runs it:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
claude mcp add kratos -- uvx kratos-mcp-server
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**From a local checkout** (current state, before the first PyPI release):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git clone https://github.com/loumalouomega/Kratos-MCP-Server
|
|
56
|
+
cd Kratos-MCP-Server
|
|
57
|
+
uv sync
|
|
58
|
+
claude mcp add kratos -- uv --directory "$PWD" run kratos-mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then ask your assistant something like:
|
|
62
|
+
|
|
63
|
+
> Check the Kratos installation — install it if it's missing — then set up
|
|
64
|
+
> a cantilever plate 1 m × 0.2 m fixed on the left with a 1 MN/m downward
|
|
65
|
+
> load on the right edge, run it, and report the tip deflection.
|
|
66
|
+
|
|
67
|
+
The assistant calls `kratos_install` the first time and reuses it afterwards.
|
|
68
|
+
If you already have a compiled Kratos checkout, skip that and point
|
|
69
|
+
`KRATOS_ROOT` at it instead (`-e KRATOS_ROOT=/path/to/Kratos` on the `claude
|
|
70
|
+
mcp add` line) — see [Installation](docs/guide/installation.md).
|
|
71
|
+
|
|
72
|
+
## Requirements
|
|
73
|
+
|
|
74
|
+
- Python ≥ 3.10, [uv](https://docs.astral.sh/uv/)
|
|
75
|
+
- Kratos Multiphysics, either pip-installed via `kratos_install`
|
|
76
|
+
(Linux/Windows x86_64 only — no macOS wheels) or a compiled build (tested
|
|
77
|
+
with 10.4, StructuralMechanics / ConvectionDiffusion / FluidDynamics /
|
|
78
|
+
LinearSolvers applications)
|
|
79
|
+
|
|
80
|
+
## Architecture in one paragraph
|
|
81
|
+
|
|
82
|
+
Kratos is never imported in the server process — it prints a banner on import
|
|
83
|
+
(which would corrupt the stdio JSON-RPC stream) and can abort the process on
|
|
84
|
+
solver errors. Short operations run in a **worker** subprocess that returns
|
|
85
|
+
JSON through a result file; simulations run **detached** with per-job
|
|
86
|
+
directories under `~/.kratos-mcp/jobs/`. See
|
|
87
|
+
[docs/guide/architecture.md](docs/guide/architecture.md).
|
|
88
|
+
|
|
89
|
+
## Development
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv run pytest -m "not kratos" # unit tests (no Kratos needed)
|
|
93
|
+
uv run pytest -m kratos # integration tests against the real build
|
|
94
|
+
npm install && npm run docs:dev # documentation site
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Kratos MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/loumalouomega/Kratos-MCP-Server/actions/workflows/ci.yml)
|
|
4
|
+
[](https://loumalouomega.github.io/Kratos-MCP-Server/)
|
|
5
|
+
[](https://github.com/loumalouomega/Kratos-MCP-Server/releases)
|
|
6
|
+
[](https://pypi.org/project/kratos-mcp-server/)
|
|
7
|
+
[](https://www.python.org/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
An [MCP](https://modelcontextprotocol.io) server that lets AI assistants drive
|
|
11
|
+
[Kratos Multiphysics](https://github.com/KratosMultiphysics/Kratos) finite
|
|
12
|
+
element simulations end to end:
|
|
13
|
+
|
|
14
|
+
- **Introspect** the installation: applications, elements, conditions,
|
|
15
|
+
constitutive laws, variables, solvers and their default parameters.
|
|
16
|
+
- **Scaffold** simulation cases from templates: structural
|
|
17
|
+
(static/dynamic/modal), thermal (transient/stationary) and fluid
|
|
18
|
+
(transient incompressible) — ProjectParameters.json, Materials.json and
|
|
19
|
+
structured MDPA meshes with named boundary regions.
|
|
20
|
+
- **Run** simulations as managed background jobs (status, live logs,
|
|
21
|
+
progress, cancel) that survive server restarts.
|
|
22
|
+
- **Post-process** VTK results: summaries, point probes, convergence
|
|
23
|
+
analysis.
|
|
24
|
+
|
|
25
|
+
31 tools, 7 resources and 4 guided prompts. See the full documentation in
|
|
26
|
+
[`docs/`](docs/) (VitePress).
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
A local Kratos build is **not required** — the server can pip-install
|
|
31
|
+
Kratos itself on first use.
|
|
32
|
+
|
|
33
|
+
**Once published to PyPI**, no clone needed — `uvx` fetches and runs it:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude mcp add kratos -- uvx kratos-mcp-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**From a local checkout** (current state, before the first PyPI release):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/loumalouomega/Kratos-MCP-Server
|
|
43
|
+
cd Kratos-MCP-Server
|
|
44
|
+
uv sync
|
|
45
|
+
claude mcp add kratos -- uv --directory "$PWD" run kratos-mcp
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then ask your assistant something like:
|
|
49
|
+
|
|
50
|
+
> Check the Kratos installation — install it if it's missing — then set up
|
|
51
|
+
> a cantilever plate 1 m × 0.2 m fixed on the left with a 1 MN/m downward
|
|
52
|
+
> load on the right edge, run it, and report the tip deflection.
|
|
53
|
+
|
|
54
|
+
The assistant calls `kratos_install` the first time and reuses it afterwards.
|
|
55
|
+
If you already have a compiled Kratos checkout, skip that and point
|
|
56
|
+
`KRATOS_ROOT` at it instead (`-e KRATOS_ROOT=/path/to/Kratos` on the `claude
|
|
57
|
+
mcp add` line) — see [Installation](docs/guide/installation.md).
|
|
58
|
+
|
|
59
|
+
## Requirements
|
|
60
|
+
|
|
61
|
+
- Python ≥ 3.10, [uv](https://docs.astral.sh/uv/)
|
|
62
|
+
- Kratos Multiphysics, either pip-installed via `kratos_install`
|
|
63
|
+
(Linux/Windows x86_64 only — no macOS wheels) or a compiled build (tested
|
|
64
|
+
with 10.4, StructuralMechanics / ConvectionDiffusion / FluidDynamics /
|
|
65
|
+
LinearSolvers applications)
|
|
66
|
+
|
|
67
|
+
## Architecture in one paragraph
|
|
68
|
+
|
|
69
|
+
Kratos is never imported in the server process — it prints a banner on import
|
|
70
|
+
(which would corrupt the stdio JSON-RPC stream) and can abort the process on
|
|
71
|
+
solver errors. Short operations run in a **worker** subprocess that returns
|
|
72
|
+
JSON through a result file; simulations run **detached** with per-job
|
|
73
|
+
directories under `~/.kratos-mcp/jobs/`. See
|
|
74
|
+
[docs/guide/architecture.md](docs/guide/architecture.md).
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
uv run pytest -m "not kratos" # unit tests (no Kratos needed)
|
|
80
|
+
uv run pytest -m kratos # integration tests against the real build
|
|
81
|
+
npm install && npm run docs:dev # documentation site
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { defineConfig } from 'vitepress'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
title: 'Kratos MCP Server',
|
|
5
|
+
description:
|
|
6
|
+
'MCP server for Kratos Multiphysics: scaffold, run and post-process finite element simulations from AI assistants',
|
|
7
|
+
base: process.env.DOCS_BASE ?? '/',
|
|
8
|
+
themeConfig: {
|
|
9
|
+
nav: [
|
|
10
|
+
{ text: 'Guide', link: '/guide/getting-started' },
|
|
11
|
+
{ text: 'Tools', link: '/tools/' },
|
|
12
|
+
{ text: 'Tutorials', link: '/tutorials/cantilever-beam' },
|
|
13
|
+
],
|
|
14
|
+
sidebar: {
|
|
15
|
+
'/guide/': [
|
|
16
|
+
{
|
|
17
|
+
text: 'Guide',
|
|
18
|
+
items: [
|
|
19
|
+
{ text: 'Getting started', link: '/guide/getting-started' },
|
|
20
|
+
{ text: 'Installation', link: '/guide/installation' },
|
|
21
|
+
{ text: 'Connecting a client', link: '/guide/connecting' },
|
|
22
|
+
{ text: 'Architecture', link: '/guide/architecture' },
|
|
23
|
+
{ text: 'The MDPA mesh format', link: '/guide/mdpa-format' },
|
|
24
|
+
{ text: 'Troubleshooting', link: '/guide/troubleshooting' },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
'/tools/': [
|
|
29
|
+
{
|
|
30
|
+
text: 'Tool reference',
|
|
31
|
+
items: [
|
|
32
|
+
{ text: 'Overview', link: '/tools/' },
|
|
33
|
+
{ text: 'Environment & introspection', link: '/tools/environment' },
|
|
34
|
+
{ text: 'Project scaffolding', link: '/tools/scaffolding' },
|
|
35
|
+
{ text: 'Meshes (MDPA)', link: '/tools/mesh' },
|
|
36
|
+
{ text: 'Simulation & jobs', link: '/tools/simulation' },
|
|
37
|
+
{ text: 'Post-processing', link: '/tools/postprocessing' },
|
|
38
|
+
{ text: 'Resources', link: '/tools/resources' },
|
|
39
|
+
{ text: 'Prompts', link: '/tools/prompts' },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
'/tutorials/': [
|
|
44
|
+
{
|
|
45
|
+
text: 'Tutorials',
|
|
46
|
+
items: [
|
|
47
|
+
{ text: 'Cantilever beam', link: '/tutorials/cantilever-beam' },
|
|
48
|
+
{ text: 'Thermal bar', link: '/tutorials/thermal-bar' },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
socialLinks: [
|
|
54
|
+
{ icon: 'github', link: 'https://github.com/KratosMultiphysics/Kratos' },
|
|
55
|
+
],
|
|
56
|
+
search: { provider: 'local' },
|
|
57
|
+
outline: [2, 3],
|
|
58
|
+
},
|
|
59
|
+
})
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## The core constraint
|
|
4
|
+
|
|
5
|
+
Kratos cannot run inside the MCP server process, for three reasons:
|
|
6
|
+
|
|
7
|
+
1. **stdout is sacred.** MCP over stdio uses stdout for JSON-RPC framing, and
|
|
8
|
+
`import KratosMultiphysics` prints a multi-line ASCII banner to stdout.
|
|
9
|
+
One import would corrupt the protocol stream.
|
|
10
|
+
2. **Crashes.** Kratos is a C++ core; a solver bug or bad input can abort the
|
|
11
|
+
whole process (segfault). The server must survive that.
|
|
12
|
+
3. **Environment.** A build-tree Kratos needs `PYTHONPATH` and
|
|
13
|
+
`LD_LIBRARY_PATH` set *before* the interpreter starts — too late for a
|
|
14
|
+
process that is already running.
|
|
15
|
+
|
|
16
|
+
So the server process never imports Kratos. Two subprocess mechanisms cover
|
|
17
|
+
all Kratos access:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌──────────────────────────────┐
|
|
21
|
+
│ MCP client (Claude, ...) │
|
|
22
|
+
└──────────────┬───────────────┘
|
|
23
|
+
│ stdio JSON-RPC
|
|
24
|
+
┌──────────────▼───────────────┐
|
|
25
|
+
│ kratos-mcp server (FastMCP) │ never imports Kratos
|
|
26
|
+
│ tools/ · mdpa.py · jobs.py │
|
|
27
|
+
└─────┬───────────────────┬────┘
|
|
28
|
+
│ bridge.run_op() │ jobs.start()
|
|
29
|
+
│ (sync, seconds) │ (detached, minutes-hours)
|
|
30
|
+
┌─────▼─────────┐ ┌─────▼─────────┐
|
|
31
|
+
│ worker.py │ │ runner.py │ both import Kratos,
|
|
32
|
+
│ introspection│ │ AnalysisStage│ env vars injected
|
|
33
|
+
│ validation │ │ .Run() │
|
|
34
|
+
└───────────────┘ └───────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Getting Kratos itself
|
|
38
|
+
|
|
39
|
+
`kratos_env.resolve()` finds Kratos in one of three ways, in order: an
|
|
40
|
+
explicit `KRATOS_PYTHONPATH`/`KRATOS_LIBS` override, a `KRATOS_ROOT`
|
|
41
|
+
checkout with a compiled `bin/Release`, or a **pip-installed**
|
|
42
|
+
`KratosMultiphysics` importable by the server's own interpreter — probed in
|
|
43
|
+
a subprocess so a missing package fails safely instead of raising in the
|
|
44
|
+
server process. That third path is what `kratos_env.pip_install()` and the
|
|
45
|
+
`kratos_install` tool populate: they run `pip install` (never Kratos itself)
|
|
46
|
+
directly in the server process — safe, since pip does not import
|
|
47
|
+
Kratos — installing the official `KratosMultiphysics` / `Kratos<AppName>` /
|
|
48
|
+
`KratosMultiphysics-all` wheels (Linux/Windows x86_64 only). Once installed,
|
|
49
|
+
the very next `resolve()` call picks it up automatically; no restart needed.
|
|
50
|
+
A local build always takes priority when both are present.
|
|
51
|
+
|
|
52
|
+
## The bridge (short operations)
|
|
53
|
+
|
|
54
|
+
`bridge.run_op(op, args)` spawns `python -m kratos_mcp.worker` with the Kratos
|
|
55
|
+
environment injected and a JSON request file. The worker writes its result to
|
|
56
|
+
a **result file** — never stdout — so banners and solver chatter cannot
|
|
57
|
+
corrupt it; stdout/stderr are captured and attached to error messages.
|
|
58
|
+
|
|
59
|
+
Ops: `check`, `list_applications`, `list_variables`, `has_constitutive_laws`,
|
|
60
|
+
`get_solver_defaults`, `validate_parameters`, `read_mdpa_deep`.
|
|
61
|
+
|
|
62
|
+
Because each spawn costs one to a few seconds, results of build-dependent ops
|
|
63
|
+
are cached in `~/.kratos-mcp/cache/`, keyed by `(op, args, build
|
|
64
|
+
fingerprint)` — editing or rebuilding Kratos invalidates the cache
|
|
65
|
+
automatically.
|
|
66
|
+
|
|
67
|
+
## Jobs (simulations)
|
|
68
|
+
|
|
69
|
+
`jobs.start()` launches `python -m kratos_mcp.runner --case-dir ...` fully
|
|
70
|
+
detached (own session), with everything persisted under
|
|
71
|
+
`~/.kratos-mcp/jobs/<job_id>/`:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
20260712-101530-a1b2c3/
|
|
75
|
+
├── meta.json # state machine: queued → running → succeeded|failed|cancelled
|
|
76
|
+
└── stdout.log # combined solver output
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- **Status** is recomputed from the process return code, or — after a server
|
|
80
|
+
restart, when the child handle is gone — from pid liveness plus the
|
|
81
|
+
AnalysisStage end banner in the log.
|
|
82
|
+
- **Progress** (`current_step`, `current_time`) is parsed from the
|
|
83
|
+
`STEP:`/`TIME:` lines AnalysisStage prints each step.
|
|
84
|
+
- **Cancel** sends SIGTERM to the job's process group and escalates to
|
|
85
|
+
SIGKILL after a grace period.
|
|
86
|
+
|
|
87
|
+
The runner picks the analysis class from the `analysis_stage` key in
|
|
88
|
+
ProjectParameters.json (the convention used by Kratos itself and by all our
|
|
89
|
+
templates), from an explicit `analysis_type`/`analysis_class` argument, or by
|
|
90
|
+
inferring it from `solver_type`.
|
|
91
|
+
|
|
92
|
+
## Hybrid introspection
|
|
93
|
+
|
|
94
|
+
What the tools report comes from two sources:
|
|
95
|
+
|
|
96
|
+
- **Runtime** (authoritative for *your build*): version, compiled
|
|
97
|
+
applications, variables, constitutive-law existence, solver default
|
|
98
|
+
parameters — via the bridge.
|
|
99
|
+
- **Source parsing**: element/condition/constitutive-law catalogs are parsed
|
|
100
|
+
from `KRATOS_REGISTER_*` macros in the C++ sources, because Kratos has no
|
|
101
|
+
runtime listing for them. Entries are flagged `compiled: true/false` by
|
|
102
|
+
cross-referencing the compiled application list.
|
|
103
|
+
|
|
104
|
+
## Pure-Python MDPA layer
|
|
105
|
+
|
|
106
|
+
`mdpa.py` parses, writes, validates and generates `.mdpa` meshes without
|
|
107
|
+
Kratos, so mesh tools work even where no build is available and unit tests
|
|
108
|
+
run anywhere. `mdpa_validate(deep=true)` additionally round-trips the file
|
|
109
|
+
through the real `ModelPartIO` in a worker.
|
|
110
|
+
|
|
111
|
+
## Templates as data
|
|
112
|
+
|
|
113
|
+
Case templates live in `src/kratos_mcp/templates/` as JSON files with
|
|
114
|
+
`{{placeholder}}` markers plus a `registry.json` describing defaults,
|
|
115
|
+
required applications and solver modules. Substitution is typed: a quoted
|
|
116
|
+
`"{{key}}"` becomes the JSON encoding of the value (numbers stay numbers,
|
|
117
|
+
arrays stay arrays); a bare `{{key}}` inside a longer string is textual.
|