Material-agnostic Low Cycle Fatigue (LCF) strain-life analysis: core library + MCP server.
Strong domain-specific tool set with clear naming (verb_noun pattern: analyze_*, fit_*, predict_*, count_*) and comprehensive descriptions (avg 180 chars, well above 10-char minimum). All 12 tools have input schemas with typed parameters and descriptions. Output schemas are documented in descriptions but not formally in JSON Schema. Error handling is implicit (service layer) but not surfaced in tool definitions. Security is solid (no secrets in params, file I/O gated). Main gaps: no enum constraints on string parameters (e.g., 'model' in mean_stress_equivalent_stress accepts 'none|morrow|swt|walker' but not declared as enum), no explicit output schema documentation, and missing actionable error guidance in descriptions.
Reduce one test from a CSV file (preferred for large series). ``column_map`` maps source column names to the canonical ``time``/``strain``/ ``force`` (e.g. {"Axial Strain": "strain"}). Returns the half-life summary and persists the per-cycle table under ``name``.
Analyze a directory of lab exports as one strain-life test series. One call: reads every file matching ``pattern`` (auto-detecting delimiter, header row, column names, and unit suffixes such as percent strain or kN force), reduces each test, persists each summary under its file stem, and fits the strain-life constants across the series under ``material``. Returns per-test summaries, the fit, notes, and per-file errors. Files that cannot be read are reported in ``errors`` without stopping the rest. Run ``preview_lab_file`` first if unsure how a file will be interpreted.
Reduce one strain-controlled test from a (time, strain, force) series. Converts engineering -> true stress/strain (unless already_true), detects cycles, computes per-cycle metrics, and returns the stabilized (half-life) summary. The full per-cycle table is saved to the store under ``name`` and can be recalled with ``recall_result(name, "per_cycle")``. Use this for small inline series; for large data use ``analyze_test_csv``.
Level-crossing count of a history (ASTM E1049 section 5.2). Counts positive-slope crossings at and above ``ref`` and negative-slope crossings below it. ``levels`` defaults to 32 evenly spaced levels over the signal. Saves the level table under ``name`` (quantity ``level_crossings``) and returns a summary.
String parameters lack enum constraints. 'model' in mean_stress_equivalent_stress accepts 'none|morrow|swt|walker' but is not declared as enum in schema. LLMs may hallucinate invalid values like 'morrow_modified' or 'swt_adjusted'.
Output schemas not formally documented in JSON Schema. Descriptions mention return structure (e.g., 'Returns Basquin (σ'_f, b), Coffin-Manson (ε'_f, c)...') but no explicit schema definition. LLMs cannot reliably extract fields from unstructured descriptions.
Error handling not surfaced in tool definitions. No descriptions of what errors can occur, when they are retryable, or what the LLM should do next. E.g., 'analyze_test_csv' could fail on malformed CSV, missing columns, or invalid area, but no guidance provided.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Rainflow count a strain history (ASTM E1049), preserving cycle indices. Saves the full per-cycle table under ``name`` (recall with ``recall_result(name, "rainflow")``) and returns a compact summary. Set ``close_residue`` to treat the history as repeating. A non-None ``gate`` first drops swings smaller than the gate with the racetrack filter, which condenses long noisy histories.
Plastic strain energy per cycle of a Masing loop, in MJ/m³. ΔW_p = ((1 - n')/(1 + n')) Δσ Δε_p, with the total stress range in MPa, the total plastic strain range as a fraction, and the cyclic strain-hardening exponent n'. Exact for Masing behavior, an estimate otherwise. Feed the result to ``fit_energy_life`` or ``predict_life_energy`` when measured loop energies are unavailable.
Fit the Halford-Morrow energy-life relation, ΔW_p = W'_f (2N_f)^β. ``plastic_energy_per_cycle`` is the stabilized plastic strain energy per cycle of each test in MJ/m³, for example the half-life hysteresis energy from the per-cycle reduction, against reversals to failure. Returns W'_f, β (negative), r squared, and standard errors. Useful at high temperature, where the energy criterion captures the stress drop that a strain-only correlation misses. If ``material`` is given, the fit is saved for recall.
Fit strain-life constants from per-test reduced data. Returns Basquin (σ'_f, b), Coffin-Manson (ε'_f, c), Ramberg-Osgood (K', n'), the transition life, and a Masing consistency check. ``min_plastic_strain`` excludes near-runout points from the plastic branch. If ``material`` is given, the fit is saved for recall.
Equivalent fully-reversed stress amplitude under a mean-stress model. ``model`` is one of none, morrow, swt, walker. Morrow needs ``sigma_f``; Walker needs ``gamma`` (or ``sigma_u`` to estimate it for steel).
Predict reversals and cycles to failure for a total strain amplitude. Inverts the combined Basquin + Coffin-Manson strain-life equation.
Predict reversals and cycles to failure from the Halford-Morrow relation. Inverts ΔW_p = W'_f (2N_f)^β for a stabilized plastic strain energy per cycle in MJ/m³. ``beta`` is negative, like b and c.
Report how a lab export file would be read, without analyzing it. Returns the detected header row, delimiter, the resolved time/strain/ force/stress columns with their units and conversion factors, the row count, and notes (for example a strain column that looks like percent). Use this before ``analyze_test_csv`` or ``analyze_test_series`` when the file layout is uncertain.
Parameter constraints not fully documented. Numeric parameters (E, R, failure_pct, min_plastic_strain) lack min/max bounds in descriptions. E.g., 'failure_pct' defaults to 30.0 but no range stated, is 0 - 100? 0 - 1000?
Tool composition: 'analyze_test_series' is a mega-tool combining file discovery, per-test reduction, and strain-life fitting in one call. If fitting fails, the agent cannot retry just the fit without re-analyzing all tests. Consider splitting into separate tools.