| list_modelsA | List all trained P2Predict models in the configured models directory. Call this first to discover which models are available. Each model carries
a plain `say_to_user` line, its target, and its specs. Lead with
`say_to_user`; do NOT read out raw fields like algorithm or R² (and never
the words 'SHAP', 'log-target', 'R²') to a category manager. Pass
include_internal=true only when you need the algorithm name / R² / log-target
flag for your own reasoning.
The response also carries a `server` block (version + git short-SHA + source
path) identifying the build this server process loaded — useful to confirm a
code change actually took effect (MCP servers are long-lived; a stale process
serves old code until restarted).
|
| get_model_infoA | Get detailed information about a specific model. Returns a plain `say_to_user` line, the target, and the model's specs with
their types (Numerical/Categorical) and allowed categories — everything you
need to build a predict/explain call. Use it to understand what inputs a
model expects. Lead with `say_to_user`; do NOT surface algorithm / R² /
log-target (or the words 'SHAP', 'log-target', 'R²') to the user. Pass
include_internal=true for those raw fields when you need them to reason.
|
| predictA | Predict the target value (e.g. price) for a single part. Pass the model_id from list_models and a dictionary of feature values
matching the model's expected features. Example:
{"Weight": 15, "Region": "EU", "Supplier": "A"}
Returns an `in_domain` block alongside the prediction — read it before you
quote the number. 'out_of_domain' means the part sits outside the data the
model was built on (an unseen supplier, a spec far past anything observed),
so the estimate isn't reliable no matter how confident it looks; quote
`in_domain.say_to_user` and point the user at a real quote.
|
| predict_batchA | Predict the target value for multiple parts at once. More efficient than calling predict repeatedly. Pass a list of
feature dictionaries, one per part. Returns one prediction per row.
Optionally enriches every row with the same views the single-part tools
give, so you don't have to fan out to explain / predict_interval:
- coverage (1-99): adds a likely-price range per row (conformal interval)
when the model carries calibration data; read `interval.reliability`
and `interval.say_to_user` per row exactly as predict_interval does.
Left None (default) for plain point predictions.
- with_explanation: adds the per-row price drivers (same `explanation`
shape as explain). Surface the high-importance, correctly-signed
drivers in dollars/percent; never say 'SHAP' to a category manager.
|
| explainA | Explain what is driving a part's predicted price, spec by spec. Returns a business-ready view to quote directly — `starting_point` (the
baseline price every part starts from) and `price_drivers` (each spec /
supplier's effect in BOTH dollars and percent, biggest mover first) — plus
the underlying technical attribution for your own reasoning. top_n controls
how many top drivers are highlighted (default 3).
Reading it for the user: the explanation carries an axiom check
(baseline +/x contributions = prediction); if it fails the explanation is
unsound. SIGN-CHECK the drivers against intuition — a counterintuitive
sign (e.g. "more cells -> cheaper") on a LOW-importance driver means that
spec is under-sampled, not that the world is upside-down. Quote the
high-importance, correctly-signed drivers; flag the rest as noise. State
effects in the user's terms ("this supplier adds $0.72" / "+18%") — never
say "SHAP", "contribution", or "baseline" to a category manager.
|
| predict_intervalA | Predict with a likely range (conformal prediction interval). For a 90% interval, about 9 in 10 similar parts fall within the range.
coverage is an integer 1-99 (default 90). Requires a model trained with
P2Predict v0.5+ (which stores calibration data).
Reading it for the user: the band WIDTH is the per-part trust signal, and
the payload computes it for you — `interval.reliability`
('trust' | 'caution' | 'quote') and a plain `interval.say_to_user` sentence
you can quote directly. A tight band = predict with confidence; a very wide
band — or a lower bound at/below $0 on an additive (non-log) model — means
"get a quote, don't benchmark." Always surface the range, not just the point
estimate, when the user will act on the number.
|
| what_ifA | Compare a base scenario with a counterfactual where features change. Returns a plain `summary` to quote directly (does the change add or save,
how many dollars, what percent, old vs. new price), plus both predictions,
the delta, and per-driver attribution of each change for your reasoning.
Answers "what if we switch from supplier A to B?" Set coverage to null to
skip intervals.
`summary.reliability` grades how far to trust the DIRECTION of the move —
'trust' | 'caution' | 'quote' — with a plain `summary.say_to_user` line to
quote. It fires when the changed spec is thinly sampled, or when the swing
is driven by knock-on effects rather than the change itself (a `quote` here
means the number is unstable — relay the caution, don't present the
direction as fact). It flags instability, not a wrong domain sign, so still
sign-check a 'trust' result against intuition.
|
| predict_from_csvA | Batch-predict from a CSV file on the local filesystem. The file-based sibling of predict_batch — use it when the user drops a
spreadsheet of parts. Reads csv_path, predicts every row, and returns one
prediction per row (point estimates by default).
The same opt-in enrichments as predict_batch apply per row:
- coverage (1-99): adds a likely-price range per row (conformal interval)
with its `interval.reliability` / `interval.say_to_user` read. Requires
a model with calibration data; an explicit coverage on an uncalibrated
model returns a no_calibration error. Left None (default) for plain
point predictions.
- with_explanation: adds the per-row price drivers (same `explanation`
shape as explain). State drivers in dollars/percent; never say 'SHAP'
to a category manager.
|
| propose_training_planA | Inspect a training CSV and return a plain-language plan BEFORE training. Call this first whenever a user wants to build a should-cost / pricing
model. It reads the CSV, decides what it would predict, which columns it
would use as specs, which it would leave out (and why — target leakage,
ID-like columns), and whether the target should use a log-target. It
trains nothing and writes nothing.
Relay `plain_summary` and `questions_for_the_user` to the user in their
own language, get confirmation, then call `train` (passing the agreed
`features` and `log_target`).
|
| trainA | Train a new P2Predict model from a local CSV file. Prefer calling `propose_training_plan` first and confirming with the user
— this tool is the execution step. The CSV must have spec columns and a
price/cost target column. Training runs locally; no data leaves the
machine. The trained model is saved and immediately available.
Safe defaults (always surfaced in the returned `warnings` list):
- When features are auto-selected (features=None), columns that look
like target leakage — a near-duplicate of the price being predicted —
are excluded automatically.
- For a strictly-positive (price/cost) target where the automatic skew
test leaves the log-target off, the result recommends log_target="on".
algorithm: "auto" (default), "ridge", "random_forest", or "xgboost".
budget: "fast" (default) or "thorough".
log_target: "auto" (default), "on", or "off". Use "on" for prices.
allow_leaky_features: set True only to override the leakage guard and
train on an explicitly-requested feature that looks like leakage.
|
| get_model_qualityA | Structured, agent-readable model-quality report — the JSON form of the PDF. Use this (not just generate_report, which only writes a PDF) when you need
to *reason about or relay* model quality. Every judgment is computed so you
don't eyeball thresholds:
- `assessment.verdict` — LEAD WITH THIS. One of: 'trustworthy' | 'usable'
| 'unreliable' | 'unknown' | 'insufficient_data'. It folds bias and
sample size into a plain `headline` you can quote verbatim — e.g. a
modest model that is even-handed reads 'usable', not just 'Needs
Improvement'. `assessment.confidence` is 'high' | 'limited' |
'insufficient'.
- `assessment.typical_bias_pct` — how far the model runs high or low on a
typical part, in percent. `assessment.bias_resolution_pct` is the
smallest offset this holdout could have detected; when the verdict is
'unknown', quote it as the bound you CAN rule out.
- `calibration_by_price_band[].reliability` — 'trust' | 'caution' |
'quote' per price range (with `low_confidence` when a band is thin).
Each band carries a `say_to_user` sentence in plain words — quote it to
tell the user which prices to benchmark vs. get a quote on.
- `feature_importance[].signal` — 'strong' | 'moderate' | 'weak', each
with its own `say_to_user` sentence. Only quote findings resting on
'strong' drivers to a stakeholder.
The default payload is deliberately business-only — every string is safe to
read to a category manager. NEVER say 'SHAP', 'R²', 'p-value', 'log-target',
'residual' to the user. The raw statistics (R², p-value, algorithm,
log-target) are NOT in the default response; pass include_metrics=true to
add them under `metrics`/`provenance` for your own developer-level reasoning.
Set include_holdout=true to also get the raw actual/predicted arrays, so an
agent with a code/plotting tool can draw its own charts (predicted-vs-actual,
residuals, error-by-band).
Requires a model trained via the MCP train tool (which stores holdout data).
|
| generate_reportA | Generate a procurement-style model-quality PDF report (3 pages). Page 1: summary metrics + predicted vs actual scatter.
Page 2: error distribution + median % error by price band.
Page 3: top-N feature importance.
The PDF is the human deliverable; the return value also echoes the same
numbers as a structured `quality` block (identical to get_model_quality)
so you can both hand the user the file AND reason over the metrics.
Works best with models trained via the MCP train tool (which stores
holdout data). For older models, the report may be unavailable.
|