mcp-chainladder
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-chainladder Run chain ladder on my paid-loss triangle"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-chainladder
Actuarial chain-ladder reserving for Claude. A Model Context Protocol server that hands Claude the tools to compute IBNR, project ultimates, run Mack (1993) stochastic error estimates, check Mack (1994) model assumptions, and parse loss triangles from CSV — all from a natural- language conversation.
Calculation only — not actuarial advice. This is a mechanical chain-ladder calculator. Selection of data, factors, tails, and exclusions, and the interpretation of stochastic error measures, require professional actuarial judgement.
What it does
Eight tools, exposed over MCP. Claude picks the right one when you ask a question; you don't have to call them by name.
Tool | When Claude reaches for it |
| "What's the IBNR on this triangle?" — the workhorse |
| "What does the full projected triangle look like?" |
| "What's the uncertainty on the total reserve?" |
| "Are there outliers or trend issues?" |
| "Run the chain ladder on this CSV file" |
| "Show me the incremental development pattern" |
| "Cumulate these incremental values" |
| "Show me a working example" — quick demo |
All numerical conventions match the Mack 1993 and Mack 1994 papers; results are stable to ~1e-12 against hand calculation on the textbook 10×10 triangle.
Related MCP server: ModelRisk MCP
Install
pipx install mcp-chainladder
# or, to run on demand without installing:
uvx mcp-chainladderPython 3.10 or newer; no other runtime dependencies beyond the official MCP SDK.
Hook into Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"chainladder": {
"command": "uvx",
"args": ["mcp-chainladder"]
}
}
}Quit and reopen Claude Desktop. The triangle tools appear under the 🔌 icon in any conversation.
For Cursor / Cline / Continue / Zed — same mcpServers block, each app
has its own config file location (their docs walk you through it).
Examples
Run the chain ladder on a CSV
Me: I have a paid-loss triangle at ~/Desktop/motor_2026Q1.csv.
Run the chain ladder and tell me the IBNR.
Claude: [calls parse_csv_triangle, then compute_chain_ladder]
Loaded a 10×10 cumulative triangle. Using volume-weighted
factors:
• Total paid to date: 49,458,000 USD
• Total ultimate: 65,883,400 USD
• Total IBNR: 16,425,400 USD
Selected factors trend from 1.879 at the front of the
triangle down to 1.002 at the tail.Check whether you should worry about assumptions
Me: Same triangle — any reason not to trust the projection?
Claude: [calls mack_diagnostics]
Three flags worth a look:
• Inflation trend: slope 0.053, p ≈ 1e-12 — STRONG evidence
link ratios are drifting upward across accident years.
This violates Mack's homogeneity assumption; consider
weighting recent years more.
• Calendar-year: Z = 0.0, p = 1.0 — no diagonal effect.
• Independence: Z = -0.35, p = 0.73 — no obvious dependence
across development columns.
• Outliers: 0 cells exceed |2σ|.
The inflation finding is the one to act on.Exclude an outlier and re-run
Me: Drop the link ratio at AY 3, dev period 2→3. What changes?
Claude: [calls compute_chain_ladder with excluded=[[2, 1]]]
Excluding (AY 3, 2→3):
• Volume factor at 2→3 moves from 1.331 to 1.328
• Total IBNR moves from 16,425 to 16,389 (−36)
• Mack SE total moves from ±354.6 to ±348.2
Net: small enough to be a "robustness check passes" rather
than a finding.Tool reference
Each tool returns a JSON object (or a 2-D list, in the case of
project_triangle/to_incremental/to_cumulative). Claude reads the
descriptions and types directly from the server — you don't need to
memorise the shapes — but here's the cheat sheet.
compute_chain_ladder(triangle, selected_factors?, tail?, excluded?)
End-to-end chain ladder.
Field returned | Meaning |
| All-year volume-weighted age-to-age factor for transition j→j+1 |
| Unweighted average of individual link ratios |
| The factor set actually used to project (defaults to volume) |
| Per-row link ratio |
| Cumulative dev factor to ultimate; |
| Most recent observed value per AY |
| Projected ultimate per AY |
| Ultimate − Latest per AY |
| Sums of the three above |
| Triangle dimensions |
mack_stochastic(triangle, selected_factors, excluded?)
Mack (1993) distribution-free standard errors. Returns σ̂²_j per dev period (tail-rule backfilled when only one observation), SE & CV per row, and SE_total / CV_total including cross-row covariance per eq. 5.15.
mack_diagnostics(triangle, selected_factors, excluded?, outlier_threshold?)
Returns standardised residuals, outliers (|r| > threshold, default
2.0), the calendar-year sign test, Spearman independence test across
adjacent dev columns, and the inflation slope of mean log-link-ratio
against accident-year index.
p-value bands to translate to plain English:
p < 0.005 → strong evidence
p < 0.05 → significant
p < 0.10 → borderline
p ≥ 0.10 → no evidenceparse_csv_triangle(path)
Reads a CSV from disk, treats blank / NA / NaN / N/A / − cells as unobserved, strips embedded thousand-separator commas, and skips header / metadata rows. Returns the triangle + dimensions + the absolute path read (useful for the assistant to confirm what it loaded).
project_triangle(triangle, selected_factors)
Fills the lower-right of the triangle with chain-ladder projections.
Returns a fully-rectangular list[list[float]] (no nulls). NaN where
a row has no observation to project forward from.
to_incremental(cumulative) / to_cumulative(incremental)
Two conversions. Unobserved cells stay unobserved; the inverse on observed cells is exact.
sample_triangle()
Returns the textbook 10×10 cumulative paid triangle. Use as a
self-check: pass it to compute_chain_ladder and you should get
Paid 49,458 / Ultimate 65,883 / IBNR 16,425.
Triangle format
[
# AY 1 — fully developed
[1000, 1855, 2423, 2988, 3335, 3483, 3552, 3603, 3624, 3631],
# AY 2 — observed through dev 9
[1113, 2103, 2774, 3422, 3844, 4010, 4090, 4148, 4172, None],
# …
# AY 10 — only the first observation
[2640, None, None, None, None, None, None, None, None, None]
]Outer index = accident year, oldest first
Inner index = development period, 0 = first age
Use
None(or JSONnull) for unobserved cellsAll rows must be the same length — pad with trailing
null
Testing
pipx install --editable mcp-chainladder
pytest -qTests pin every public tool against the textbook triangle's well-known parity values to ~1e-9.
Pro tier
<< UNDER REVIEW - COMING SOON >>
The free tier covers all 8 tools listed above. Pro unlocks
additional methods + bulk workflows, gated by a local license file
at ~/.chainladder/license (or wherever $CHAINLADDER_LICENSE_FILE
points).
Pro licenses are currently for internal and testing purposes only — not open to the public. No purchase channel is available at this time. The Pro tools are listed below for reference and will continue to return
pro_license_requiredfor external users.
Pro tool | What it does |
| Inspect current license state (free to call) |
| Mack tests with verdict labels + plain-English summaries + recommended actions |
| Drop each link ratio one-at-a-time and rank by IBNR impact |
| Fit exponential + inverse-power tail models, recommend best fit |
| BF reserving method with side-by-side CL comparison |
| Run CL + BF in one call, report deltas + largest divergence |
| Full 5-page actuarial PDF — cover / triangle / factors / results / 3D loss surface |
| Fold the chain ladder over a directory of CSV triangles |
| Additional reserving methods, all returning side-by-side comparisons |
License file format
{
"product": "mcp-chainladder-pro",
"owner": "alice@example.com",
"expires": null,
"key": "CL-PRO-1A2B3C4D",
"signature": "…"
}Drop it at ~/.chainladder/license (the file's directory must exist;
the server doesn't create it). Pro tools immediately respond as
unlocked the next time Claude calls them.
When the license is missing or expired, every Pro tool returns
{"error": "pro_license_required", "status": {...}} instead of
computing — Claude reads the status and points you to the upgrade
URL. The free-tier tools always work regardless of license state.
License
MIT. See LICENSE.
Available Tools
14 toolsbornhuetter_fergusonA
Bornhuetter-Ferguson (1972) reserving method. Pro tier.
Combines the chain-ladder development pattern with an externally- provided a-priori ultimate per accident year, giving a result that is far less sensitive to noisy late development than pure chain ladder. The canonical "second method" for benchmarking reserves — when chain-ladder and BF agree, you can publish with confidence; when they diverge, the divergence is the finding.
Args:
triangle: Cumulative loss triangle, same shape as
compute_chain_ladder.
a_priori_ultimates: Expected ultimate per accident-year row,
usually derived from premium × expected loss ratio or
a plan figure. Must have length n_acc.
selected_factors: Override factor set; defaults to volume-
weighted (same default as chain ladder).
tail: Multiplicative tail factor. Default 1.0.
excluded: Outlier exclusions, same shape as in
compute_chain_ladder.
Returns either:
- On success: {a_priori_ultimates, used_up_proportion, bf_ultimates, bf_ibnr, cl_ultimates, cl_ibnr, total_bf_ultimate, total_bf_ibnr, total_cl_ultimate, total_cl_ibnr} — note the chain-ladder values are returned
alongside so the user can see the two methods side-by-side.
- On license failure: {error, status} with status giving the
upgrade URL and reason. Free-tier callers get this and can
still see the API shape; no compute happens.
Inputs: triangle (required), a_priori_ultimates (required), selected_factors, tail, +1 more. Returns: object
compare_methodsA
Run chain ladder + Bornhuetter-Ferguson on the same triangle and return a side-by-side comparison. Pro tier.
The canonical "second opinion" — when both methods agree, the reserve is defensible; when they diverge, the divergence is the finding. Reports total deltas plus the single AY where the two methods disagree most.
Args:
triangle: As in compute_chain_ladder.
a_priori_ultimates: One expected ultimate per AY for the BF
method.
selected_factors, tail, excluded: As in compute_chain_ladder.
Returns either:
- On success: {chain_ladder, bornhuetter_ferguson, diffs_by_ay, total_diff_ultimate, total_diff_ibnr, largest_divergence}.
- On license failure: {error, status}.
Inputs: triangle (required), a_priori_ultimates (required), selected_factors, tail, +1 more. Returns: object
compute_chain_ladderA
Run a full chain-ladder reserving calculation on a cumulative loss triangle. This is the workhorse tool — call it whenever the user asks "what's the IBNR?", "what does the chain ladder say?", or hands you a triangle and asks for projections.
Args:
triangle: Cumulative loss triangle as a list of lists. Outer index
is the accident-year row (oldest first). Inner index is the
development period (0 = first age). Cells are numbers or null;
null means unobserved (typical lower-right corner of a real
triangle). All rows should be the same length — pad with
trailing nulls if needed.
selected_factors: Optional list of user-chosen age-to-age factors,
one per development-period transition (length = n_dev - 1).
When omitted, the volume-weighted factors derived from the
triangle are used as the selected set.
tail: Multiplicative tail factor applied beyond the last
development period. Default 1.0 (no tail).
excluded: List of [row_i, dev_j] pairs identifying individual
link ratios to drop from the volume and simple averages. Use
this for outlier handling — typically after consulting
mack_diagnostics to find suspect cells.
Returns:
A dictionary containing:
- volume_factors: list[float] — volume-weighted age-to-age
- simple_factors: list[float] — simple average of link ratios
- selected_factors: list[float] — the set actually used
- individual_factors: list[list[float | None]] — per-row link
ratios C[i, j+1] / C[i, j]; null where the pair is unobserved
- cdf: list[float] — cumulative dev factors to ultimate; last
element is tail
- latest_diagonal: list[float] — most recent observed value per
accident row
- ultimates: list[float] — projected ultimate per accident row
- ibnr: list[float] — Ultimate − Latest, per accident row
- total_latest, total_ultimate, total_ibnr: float scalars
- n_acc, n_dev: int — triangle dimensions for convenience
Inputs: triangle (required), selected_factors, tail, excluded. Returns: object
interpret_diagnosticsA
Run Mack assumption diagnostics + label each result with a plain- English verdict and a recommended action. Pro tier.
Free-tier mack_diagnostics returns raw Z-scores and p-values; this
Pro variant adds:
• verdict band ("strong evidence" / "significant" / "borderline" / "no evidence") for each test, using the standard p-value cutoffs • a one-paragraph summary written so Claude can read it back to the user without further interpretation • a specific recommended action for each finding ("try BF", "weight recent years only", "investigate cells X, Y, Z", …) • an overall verdict pulling the three tests + outlier scan together into a single sentence
Use this when the user asks "is the chain ladder OK?", "should I publish this?", or "what does the model tell me about itself?".
Args:
triangle: As in compute_chain_ladder.
selected_factors: Length-(n_dev - 1) factor set used for the
point estimate.
excluded: Outlier exclusions to honour.
outlier_threshold: Absolute residual threshold for flagging
cells (default 2.0).
Returns either:
- On success: {calendar_year, independence, inflation, outliers, overall} — each test object carries stat,
p_value, verdict, summary, recommendation. The
outliers object also reports count, severity
(clean / mild / moderate / severe), and a list of flagged
cells.
- On license failure: {error: "pro_license_required", status: {...}}.
Inputs: triangle (required), selected_factors (required), excluded, outlier_threshold. Returns: object
mack_diagnosticsA
Mack (1994) assumption diagnostics — three statistical tests plus standardised-residual outlier detection. Use when the user asks "does the chain ladder look OK?", "are there any outliers?", or "should I be worried about [calendar-year / inflation / dependence] effects?".
Args:
triangle: As in compute_chain_ladder.
selected_factors: Length-(n_dev - 1) factor set.
excluded: Outlier exclusions to honour.
outlier_threshold: Absolute standardised-residual threshold for
flagging an outlier. Default 2.0 (the Tk app's default).
Returns:
- standardised_residuals: list[list[float | null]] — per-cell
residual r[i,j] = (C[i,j+1] − f_j·C[i,j]) / (σ_j·√C[i,j]);
null where the cell is excluded or the pair is unobserved
- outliers: list of {row: int, dev: int, residual: float} —
cells with |residual| > outlier_threshold
- calendar_year: {z: float, p_two_sided: float} — Tarbell
sign test for calendar-year effects (large |z| ⇒ suspect)
- independence: {z: float, p_two_sided: float} — Spearman
rank-correlation between adjacent development columns (large
|z| ⇒ link ratios are not independent)
- inflation: {slope: float, p_value: float} — OLS slope of
mean(ln link-ratio) on accident-year index (non-zero ⇒
accident-year trend in link ratios)
Verdict guidance for translating p-values to plain English: p < 0.005 → "strong evidence"; p < 0.05 → "significant"; p < 0.10 → "borderline"; p ≥ 0.10 → "no evidence".
Inputs: triangle (required), selected_factors (required), excluded, outlier_threshold. Returns: object
mack_stochasticA
Mack (1993) stochastic chain-ladder error estimation. Returns distribution-free standard errors and coefficients of variation per accident row plus the totals — the canonical sensitivity check for a deterministic chain-ladder result.
Use this when the user asks about uncertainty, reserve risk, or
confidence intervals. Pair it with compute_chain_ladder (use the
same selected_factors for consistency).
Args:
triangle: As in compute_chain_ladder.
selected_factors: The factors used for the point-estimate
projection. Length = n_dev - 1.
excluded: Outlier exclusions to honour, same shape as in
compute_chain_ladder.
Returns:
- sigma2: list[float] — σ̂_j² per development period; backfilled
via Mack's tail rule when only one observation is available
- se_per_row: list[float] — standard error of each ultimate
- cv_per_row: list[float] — coefficient of variation (SE /
Ultimate) per accident row
- se_total: float — SE of the sum of all ultimates (includes
cross-row covariance per Mack eq. 5.15)
- cv_total: float — CV of the total ultimate
Inputs: triangle (required), selected_factors (required), excluded. Returns: object
parse_csv_triangleA
Parse a CSV file from disk into a cumulative loss triangle.
Reads the file, treats empty cells and the tokens "NA", "N/A", "NaN", "-" as unobserved, strips embedded commas (thousand separators), and drops any leading row whose first cell is non-numeric but whose remaining cells are mostly numeric (e.g. a "Dev 1, Dev 2, …" header). Auto-pads jagged rows to a rectangle with nulls.
Use this when the user gives you a CSV file path and wants to run the chain ladder on it.
Args:
path: Absolute or ~-relative path to the CSV file. Must be
readable by the server process.
Returns:
- triangle: list[list[float | null]] — parsed cells, ready to
pass to compute_chain_ladder
- n_acc: int — number of accident-year rows
- n_dev: int — number of development periods (max row length)
- source: str — absolute path actually read
Inputs: path (required). Returns: object
project_triangleA
Fill the lower-right (unobserved) cells of a cumulative triangle using the supplied age-to-age factors.
Args:
triangle: As in compute_chain_ladder.
selected_factors: One factor per development-period transition.
Length must be n_dev - 1.
Returns a dict with:
- triangle: 2-D list of floats, same shape as the input, with
unobserved cells filled in by chain-ladder projection. Rows
with no observation contain nan for the projected cells.
- disclaimer: standard actuarial-use disclaimer.
Inputs: triangle (required), selected_factors (required). Returns: object
pro_license_statusA
Inspect the current Pro-tier license state. Returns whether Pro tools are unlocked, the registered owner, an expiry date if any, and a human-readable message that Claude can relay to the user. Free to call regardless of license state.
Returns:
- active: bool — whether the license is currently valid
- owner: str | null — email associated with the license
- expires: int | null — unix-epoch seconds, null = perpetual
- message: str — plain-English status (great for Claude to
read back to the user)
- upgrade_url: str — where to buy / renew
Inputs: no named parameters. Returns: object
sample_triangleA
Return the classic textbook 10×10 cumulative-paid triangle
(Friedland-style). Useful for demos, examples, and verifying the
server is working — feed it to compute_chain_ladder to get the
well-known parity values (Paid 49,458 / Ultimate 65,883 /
IBNR 16,425 / Mack SE ±354.61).
Returns:
- triangle: the 10×10 list with the lower-right as null
- n_acc: 10
- n_dev: 10
- expected_totals: well-known parity values for cross-checking
Inputs: no named parameters. Returns: object
sensitivity_analysisA
Drop each observable link ratio one at a time, rerun the chain ladder, and rank the link ratios by their impact on total IBNR. Pro tier.
The fastest way to find the few observations that are actually
driving the projection. Use after mack_diagnostics flags outliers
— these are the cells to investigate first.
Args:
triangle: As in compute_chain_ladder.
selected_factors: Override factor set; defaults to volume-
weighted.
tail: Multiplicative tail factor.
excluded: Existing exclusions; the analysis honours these and
tests one additional cell at a time.
top_n: Cap on the number of "most influential" cells returned.
Default 10. Set higher for larger triangles.
Returns either:
- On success: {baseline_ibnr, n_tested, top_influential[], summary} — each top_influential entry has row, dev,
ratio, ibnr_with_excluded, ibnr_delta, ibnr_delta_pct.
- On license failure: {error, status}.
Inputs: triangle (required), selected_factors, tail, excluded, +1 more. Returns: object
tail_extrapolationA
Fit parametric tail models to the late development factors and extrapolate forward. Pro tier.
Fits two candidate models — exponential decay
(ln(f_j - 1) = a + b·j) and inverse-power
(ln(f_j - 1) = a + b·ln(j+1)) — picks the better R², and
returns the implied tail factor for plugging back into
compute_chain_ladder(tail=…).
Use this when the triangle obviously hasn't reached ultimate by the last observed development period — i.e., the last selected factor is still meaningfully above 1.
Args: selected_factors: The factor set you want to extrapolate from. n_extra: How many extra development periods to project. Default 6 (covers most P&C lines).
Returns either:
- On success: {fits[], recommended, summary} — each fits
entry has model, parameters, r_squared,
extrapolated[], tail_factor.
- On license failure: {error, status}.
Inputs: selected_factors (required), n_extra. Returns: object
to_cumulativeA
Convert an incremental triangle to cumulative (running sum per
row). Unobserved cells propagate as null. Inverse of
to_incremental on observed cells.
Args: incremental: Incremental triangle.
Returns dict with triangle (cumulative, same shape) and the
standard disclaimer.
Inputs: incremental (required). Returns: object
to_incrementalA
Convert a cumulative triangle to incremental (per-period) values.
inc[i, 0] = cum[i, 0]
inc[i, j>0] = cum[i, j] - cum[i, j-1] (when both observed)
Unobserved cells stay unobserved.
Args: cumulative: Cumulative triangle, possibly with unobserved cells.
Returns dict with triangle (incremental, same shape) and the
standard disclaimer.
Inputs: cumulative (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Each tool has a clearly distinct purpose: core calculation (compute_chain_ladder), alternative method (bornhuetter_ferguson), comparison, diagnostics (raw and interpreted), stochastic error, sensitivity, tail extrapolation, data I/O, conversions, license status. No overlap.
All tool names follow a consistent verb_noun pattern with snake_case, e.g., compute_chain_ladder, mack_diagnostics, parse_csv_triangle. The style is uniform and predictable across all 14 tools.
14 tools is well-scoped for an actuarial reserving server, covering core methods, diagnostics, error estimation, sensitivity, tail extrapolation, data I/O, and conversions. No extraneous tools, and each serves a necessary function.
The tool set covers the full typical reserving workflow: data input (parse_csv_triangle, sample_triangle), core deterministic calculation, alternative method, comparison, diagnostics, stochastic error, sensitivity analysis, tail extrapolation, and format conversions. No obvious gaps.
Maintenance
Related MCP Connectors
Insurance pricing: build, validate and test rating models, then price quotes from your AI client.
All the ease of Claude. All the rigor of a real macro tracker.
Your audit methodology inside Claude: findings, risks, controls and workpapers in your team format.
36 free private calculator tools for Claude. No accounts, no data leaves your session.
Related MCP Servers
- AlicenseAqualityDmaintenanceConnect Claude to your Power BI semantic models. Browse workspaces, tables, and measures, run DAX queries, and get results — with large datasets automatically saved to local CSV files to protect the LLM context window. Includes a query history log for cross-session reuse and auditability.1337 PyPI14MIT

ModelRisk MCPofficial
AlicenseBqualityBmaintenanceEnables Monte Carlo risk modeling in Excel via conversation, including model building, fitting, simulation, and audit.5943 PyPIMIT- AlicenseNot gradedqualityCmaintenanceLets Claude run validated, auditable HEOR analyses (cohort construction, outcome computation, overlap-weighted comparison) as deterministic tools on synthetic healthcare data.MIT
- AlicenseNot gradedqualityDmaintenanceProvides quantitative analytics and statistical inference for financial data, including Monte Carlo DCF valuation, risk metrics, and trend regression diagnostics, enabling natural language-driven financial analysis via Claude Desktop.MIT