# FEA (finite element analysis)

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/TheRoboMaster123/mcp-fea  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/fea-finite-element-analysis

## Description
Real FEA on CAD parts: validated setups, stress, safety factor, natural frequencies

## Claude Desktop Quick Installation
Heuristic fallback — verify the package name and runner against the repository README before running it. Uses `npx` (confidence: low):

```json
"mcpServers": {
  "fea-finite-element-analysis": {
    "command": "npx",
    "args": ["-y","fea-finite-element-analysis"]
  }
}
```

## Documentation & README

# mcp-fea

[![ci](https://github.com/benchwire/mcp-fea/actions/workflows/ci.yml/badge.svg)](https://github.com/benchwire/mcp-fea/actions/workflows/ci.yml)
[![validation](https://img.shields.io/badge/validation-receipts-blue)](docs/validation.md)
[![license](https://img.shields.io/badge/license-Apache--2.0-green)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-2026--07--28-black)](https://modelcontextprotocol.io/specification/2026-07-28)

**Real finite element analysis from a conversation.** An AI assistant sends
a STEP file and a plain-English question ("does this arm survive a 6 g
maneuver with a 400 g motor?"); this MCP server maps the words onto
geometry, **rejects bad setups deterministically before any compute is
spent**, meshes and solves with CalculiX on Modal as an async MCP task, and
returns a verdict backed by numbers — peak von Mises stress, factor of
safety, deflection, natural frequencies — plus rendered stress plots and an
interactive 3D viewer. Every study ends with a non-skippable
reaction-balance check; every benchmark on the
[validation page](docs/validation.md) is regenerated by CI on every commit.

![mode 1 animation](demo/assets/mode1.gif)

*Measured on the live deployment (2026-07-31): cold start **3.8 s** ·
cantilever study submit→completed **9.3 s** warm / **12.9 s** with a cold
solver container · **~$0.002 per study** at Modal's posted rates.*

| Benchmark | Reference | Computed | Error |
|---|---:|---:|---:|
| Cantilever tip deflection (PL³/3EI) | 0.58055 mm | 0.58046 mm | 0.02% |
| NAFEMS LE10 σ_yy @ D | −5.38 MPa | −5.456 MPa | 1.41% |
| Plate-with-hole peak (Heywood Kt) | 62.8 MPa | 61.92 MPa | 1.40% |
| Cantilever f₁ (Euler–Bernoulli) | 816.0 Hz | 815.4 Hz | 0.08% |

Full table, mesh stats, and an explicit limitations section:
**[docs/validation.md](docs/validation.md)** — regenerated by CI, never
hand-edited.

Protocol: **MCP 2026-07-28** (stateless core) with the
`io.modelcontextprotocol/tasks` extension implemented per SEP-2663 (the
official Python SDK v2 shipped without it — this repo also contains the
[client-side extension](src/client/tasks_ext.py) that teaches the official
SDK to consume task-augmented servers) and an MCP Apps (SEP-1865) 3D
viewer. See [docs/decisions.md](docs/decisions.md) for every engineering
call and why.

## Deploy (3 commands)

```bash
uv sync
uv run modal secret create mcp-fea-token MCP_FEA_TOKEN=$(openssl rand -hex 24)
uv run modal deploy -m src.server.modal_app
```

Modal prints the endpoint URL (`https://<workspace>--mcp-fea-mcp-endpoint.modal.run`).
Connect any 2026-07-28 MCP client with `Authorization: Bearer <your token>`.
First-time Modal users: `uv run modal token new` once. Then verify the live
deployment end to end:

```bash
MCP_FEA_LIVE_URL=https://... MCP_FEA_TOKEN=... make verify-live
```

## Tools

| Tool | Sync/async | What it does |
|---|---|---|
| `inspect_geometry` | sync | STEP → face table (face_id, type, centroid, normal/axis, area, bbox) + part bbox/volume. Call first: it's how English maps to face ids. |
| `list_materials` | sync | Built-in library: Al 6061-T6, Al 7075-T6, Steel 4140, Stainless 304, Ti-6Al-4V, ABS, PLA, Nylon 12, PC (E, ν, yield, density). |
| `submit_fea_study` | **task** | Linear static: validate → mesh (C3D10, curvature-adaptive, local thin-wall refine) → CalculiX → verdict/stress/FoS + 3 stress PNGs. |
| `submit_modal_study` | **task** | Natural frequencies + mode shapes (`*FREQUENCY`), first N modes (default 6), one exaggerated-deformation PNG per mode. Requires constraints and density. |
| `get_report` | sync | Full payload for a completed task; `include_mesh_data: true` adds the surface-mesh payload the 3D viewer app fetches. |

Task lifecycle: `working` (statusMessage walks `validating → meshing →
solving → postprocessing`) → `completed | failed | cancelled`;
`tasks/cancel` kills the running container. Tasks are retained 24 h.

## Units policy

**One conversion boundary, at ingest.** Internally everything is consistent
mm–N–MPa(–tonne): lengths mm, forces N, stress/moduli MPa, density tonne/mm³
(kg/m³ × 1e-12 — done once, in `Material.density_tonne_mm3`), which makes
modal frequencies come out directly in Hz. STEP coordinates are interpreted
in the *declared* units (`mm|m|in`); gmsh's own unit conversion is disabled
so the declared unit is authoritative — and sanity-checked (a 100 mm part
declared "m" gets flagged).

## Validation codes

Every rejection returns `{code, message, suggested_fix}`.

| Code | Meaning | Stage |
|---|---|---|
| `GEOMETRY_REF_INVALID` | STEP missing/unreadable/over 25 MB, bad units field | parse |
| `GEOMETRY_KERNEL_CRASH` / `GEOMETRY_TIMEOUT` | CAD kernel crashed / hung on the file (isolated subprocess; endpoint unaffected) | inspect |
| `MATERIAL_UNKNOWN` / `MATERIAL_UNPHYSICAL` | Not in library / E ∉ [0.01, 1500] GPa, ν ∉ (0, 0.5), yield ≤ 0, density ∉ [10, 25000] kg/m³, missing density for modal | parse |
| `CONSTRAINT_INVALID` / `CONSTRAINT_CONFLICT` | Bad type; node pinned in two local frames | parse/deck |
| `LOAD_INVALID` / `LOAD_MISSING` / `MODAL_INVALID` | Bad type/units/direction; zero loads; bad n_modes | parse |
| `GEOM_NO_SOLID` / `GEOM_MULTIPLE_SOLIDS` | Not a single solid body (assemblies = v2) | pre-mesh |
| `FACE_ID_INVALID` | Face id not on this part | pre-mesh |
| `RIGID_BODY_MOTION` | Constraints leave free motion (named, e.g. "rotation about the hole axis") — SVD rank check | pre-mesh |
| `LOAD_ON_FIXED_FACE` | Load applied to a fully fixed face | pre-mesh |
| `UNITS_SUSPECT` *(warning)* | Part > 5 m or < 0.5 mm — declared units probably wrong | pre-mesh |
| `LOAD_MAGNITUDE_EXTREME` / `_NEGLIGIBLE` *(warnings)* | σ ≈ F/A > 10× yield or < 1e-6× yield | pre-mesh |
| `MESH_ELEMENT_CAP` | > 400k elements even after coarsening / local refine | mesh |
| `MESH_QUALITY_JACOBIAN` / `MESH_QUALITY_ASPECT` / `MESH_THIN_WALLS` | Quality gates; thin walls get one local auto-refine first | mesh |
| `MESH_TIMEOUT` | Meshing exceeded its wall budget (near-tangent slivers, helical threads) — the worker is killed from outside | mesh |
| `SOLVER_SINGULAR` / `SOLVER_MESH_DEGENERATE` / `SOLVER_TIMEOUT` / `SOLVER_FAILED` | Mapped ccx failures (>150k elements auto-switch to the iterative solver) | solve |
| `EQUILIBRIUM_FAIL` *(warning, untrusted result)* | ΣRF vs free-node applied loads off by > 0.5% | post |
| `LOAD_INTO_SUPPORT` *(warning)* | > 5% of the load lands on constrained nodes (loaded face touches a fixed face) and is carried directly by the support | post |
| `BEYOND_YIELD` / `LARGE_DEFLECTION` *(warnings)* | FoS < 1 (post-yield numbers flagged non-physical) / u > 5% of min dimension | post |

## Abuse limits (all env-tunable)

25 MB STEP cap · 40 MB request cap (413) · per-token rate limit
(`MCP_FEA_RATE_LIMIT`/`_WINDOW_S`, 429) · concurrent-solve cap
(`MCP_FEA_MAX_CONCURRENT`) · daily budget (`MCP_FEA_MAX_SPAWNS_PER_DAY`) ·
kill switch (`MCP_FEA_DISABLE_SPAWN=1`). CAD parsing never runs in the
endpoint process (see [SECURITY.md](SECURITY.md)).

## Local development

```bash
uv sync
curl -Ls https://micro.mamba.pm/api/micromamba/osx-arm64/latest | tar -xj bin/micromamba
./bin/micromamba create -y -p .tools/ccx-env -c conda-forge calculix=2.23
make test        # fast suite (protocol, benchmarks, validation, hardening)
make torture     # 21 real-world STEP files through the endpoint
make validation-page
uv run uvicorn --factory src.server.app:create_local_app --port 8000  # local server
```

## Repo map

`src/pipeline/` geometry, meshing, deck, solver, validation, post, render ·
`src/materials/` library · `src/server/` protocol, tools, tasks, limits,
worker host, Modal app, Apps UI · `src/client/` SDK tasks extension ·
`tests/` (incl. `torture/`) · `demo/` · `docs/` decisions, validation, upstream notes. License: Apache-2.0.

