pypi autocarverstdioMITupdated 9d ago
AutoCarver turns raw numeric, categorical, and ordinal columns into optimal, drift-robust, human-readable bins in a few lines of code. Stop losing model performance to suboptimal manual binning β and stop discovering overfit bins in production monitoring.
What can you do with autocarver?
AutoCarver turns raw numeric, categorical, and ordinal columns into optimal, drift-robust, human-readable bins in a few lines of code. Stop losing model performance to suboptimal manual binning β and stop discovering overfit bins in production monitoring.
- Provably optimal β exhaustive search: for a fixed
min_freq,max_n_modand metric (Tschuprow's T by default, or CramΓ©r's V), no other admissible bin combination scores higher. It checked them all so you don't have to. - Robust by construction β every candidate grouping is vetoed unless it holds on a held-out dev set (and optional CV folds), at
fittime rather than in monitoring. - Define β carve β model β declare your
Features,fita carver,transform: the whole feature set is carved in one supervised pass, not one notebook per feature. One carver per target type βBinaryCarver,MulticlassCarver,OrdinalCarver,ContinuousCarver(regression) β all with the identical API. - AI-assisted β a local MCP server lets your LLM assistant qualify and carve columns through tool calls, fully on your machine.
On the Titanic quick start, Fare collapses from 72 pre-carving modalities to 2 bins while its association with survival rises: Tschuprow's T 0.18 raw β 0.29 carved.
Built for credit scoring, fraud detection, and risk modeling.
π What's New
π Cross-validated robustness. fit now accepts a cv argument for extra
held-out robustness views on top of (or instead of) a dev set:
carver.fit(X, y, cv=5). Accepts an int, any scikit-learn splitter, or
explicit index pairs, resolved via sklearn.model_selection.check_cv β folds
veto over-fit combinations but never reorder them (ranks stay anchored to the
full train set). See Cross-validation folds.
π€ LLM & MCP integration. AutoCarver now ships a local Model Context Protocol server: point an MCP-aware assistant (VS Code Copilot, Claude Desktop, Cursor, β¦) at a data file and let it qualify the columns and carve them against your target through tool calls. The server runs fully on your machine β your dataset is never sent to AutoCarver or any external service (only your own LLM provider sees what the assistant shares). Carving quality depends on the LLM, so have a human confirm the feature definitions before production use. See the LLM & MCP guide.
pip install "autocarver[mcp]"
Once configured, just ask your assistant:
Qualify the columns in
titanic.csvand carve them againstSurvived.
The assistant infers feature types, proposes a carving, and returns the summary table β no code written by hand.
Add to .vscode/mcp.json (VS Code / GitHub Copilot) or claude_desktop_config.json (Claude Desktop, under mcpServers instead of servers):
{
"servers": {
"autocarver": {
"command": "python",
"args": ["-m", "AutoCarver.mcp"]
}
}
}
If you use uv, point command at uv instead so it resolves the environment for you:
{
"servers": {
"autocarver": {
"command": "uv",
"args": ["run", "python", "-m", "AutoCarver.mcp"]
}
}
}
Install
pip install autocarver
Quick Start
You already have a DataFrame and a target β that's the first box ticked before you start:
- Load data
- Split train / dev
- Declare features by type
- Fit the carver, validated on the dev set
- Inspect the carved bins
- Persist
The rest is the snippet below β binary classification on the Titanic dataset:
from pathlib import Path
import pandas as pd
from sklearn.model_selection import train_test_split
from AutoCarver import BinaryCarver, Features
# 1. Load data
url = "https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv"
data = pd.read_csv(url)
target = "Survived"
# 2. Train / dev split, stratified on the target
train, dev = train_test_split(data, test_size=0.33, random_state=42, stratify=data[target])
# 3. Declare features by type
features = Features(
categoricals=["Sex"],
numericals=["Age", "Fare", "Siblings/Spouses Aboard", "Parents/Children Aboard"],
ordinals={"Pclass": ["1", "2", "3"]},
)
# 4. Fit the carver (dev set drives the robustness checks)
carver = BinaryCarver(features=features)
train_processed = carver.fit_transform(train, train[target], X_dev=dev, y_dev=dev[target])
dev_processed = carver.transform(dev)
# 5. Inspect the carved buckets, target rate, and association
carver.summary
# 6. Persist for later use
carver.save(Path("titanic_carver.json"))
# 7. Load the carver back in
carver = BinaryCarver.load(Path("titanic_carver.json"))
dev_processed = carver.transform(dev)
min_freq and max_n_mod are the only two knobs that matter to start with β the defaults (0.02 / 5) reflect common scoring practice, and every behavioral toggle lives in one ProcessingConfig object. Scan, adjust, move on.
For multiclass classification use MulticlassCarver (one binning per feature, against the full K-class target) β or OneVsRestCarver for a separate binning per class; for ordinal targets use OrdinalCarver; for regression use ContinuousCarver β the API is identical. To pre-select features by target association and inter-feature redundancy, pipe the carved output through ClassificationSelector or RegressionSelector.
What you get
Two questions worth answering before your next model review: can you defend every bin boundary of your current model to a stakeholder β and can you show each one holds on data it has never seen? AutoCarver makes both a one-liner:
-
No performance left on the table β exhaustive search over admissible bin combinations maximizes Tschuprow's T (default) or CramΓ©r's V: for fixed
min_freq,max_n_modand metric, no other combination scores higher, so you never wonder whether a better grouping existed. -
Stop silent overfitting before production β bins that only exist in your training sample degrade quietly under drift. Every candidate combination is validated on a dev set (and optional CV folds): any whose target rates flip or whose buckets fall below
min_freqis rejected at fit time, not discovered in monitoring. -
First-class ordinal features β
OrdinalDiscretizerenforces your declared modality order, so under-represented levels are merged with their nearest neighbour instead of being collapsed by frequency. -
You are the final auditor β
features.summaryandfeatures.historyexpose the bin definitions, per-bin target rate / frequency, and the full carving trace; disagree with a boundary and you can override it, andtransformapplies your fix like any carved bin:feature = features("Siblings/Spouses Aboard") # any fitted feature; labels are [0, 1, 2] feature.group([1], 2) # merge two bins you consider equivalent -
Interpretable buckets β human-readable boundaries you can audit, document, and ship to a scorecard.
-
Dimensionality reduction β groups under-represented modalities and caps bins per feature (
max_n_mod), which is especially useful before one-hot encoding. -
Feature pre-selection β
ClassificationSelector/RegressionSelectorrank features by target association and filter on inter-feature correlation.
Titanic Age, one BinaryCarver.fit call: 84 raw values collapse to 3 buckets with a monotonic survival rate.
How does it compare?
| Manual binning | AutoCarver | optbinning | sklearn KBinsDiscretizer | |
|---|---|---|---|---|
| Algorithm | eyeballing distributions, notebook by notebook | exhaustive search over admissible combinations | CART pre-binning, then CP solver (CP-SAT default; MIP optional) | quantile / uniform / k-means β unsupervised |
Optimality for given min_freq / max_n_mod / metric |
none β first acceptable grouping wins | guaranteed β best of every admissible combination | provably optimal over its pre-bins, under its constraints | n/a β no target objective |
| Target types | any, at ~1 feature/hour | binary, multiclass, ordinal, continuous | binary, multiclass, continuous | n/a |
All feature types in one fit (numeric, categorical, ordinal, NaN) |
each feature is its own project | yes β declared ordinal order enforced, NaN as its own modality |
yes via BinningProcess; no first-class ordinal type (user_splits workaround) |
numeric only; NaN raises |
| Held-out dev-set robustness check | rarely β too tedious to script per feature | yes β dev set + optional k-fold CV, built into fit |
no (script CV yourself) | no |
Per-bin stats + carving history after fit |
scattered notebook cells | features.summary, features.history |
binning_table |
no |
All three libraries are sklearn-Pipeline compatible; AutoCarver adds JSON round-trip persistence (carver.save("...json")) and feature pre-selection helpers (ClassificationSelector, RegressionSelector). The full feature matrix, side-by-side runnable snippets, and a "when to pick which" guide live on the comparison page.
Documentation
Full reference, tutorials, and end-to-end notebook examples on ReadTheDocs.
Install
Add autocarver to your client. Pick the one you use.
claude mcp add autocarver -- uvx autocarvercodex mcp add autocarver -- uvx autocarveramp mcp add autocarver -- uvx autocarver{
"mcpServers": {
"autocarver": {
"command": "uvx",
"args": [
"autocarver"
]
}
}
}Add to `claude_desktop_config.json`, then restart Claude Desktop.
{
"mcpServers": {
"autocarver": {
"command": "uvx",
"args": [
"autocarver"
]
}
}
}Add to `~/.cursor/mcp.json`, or `.cursor/mcp.json` for a single project.
code --add-mcp '{"name":"autocarver","command":"uvx","args":["autocarver"]}'Or add the block manually to `.vscode/mcp.json` under `servers`.
{
"mcpServers": {
"autocarver": {
"command": "uvx",
"args": [
"autocarver"
]
}
}
}Add to `~/.codeium/windsurf/mcp_config.json`.
{
"mcpServers": {
"autocarver": {
"command": "uvx",
"args": [
"autocarver"
]
}
}
}Add to `cline_mcp_settings.json` via the MCP Servers panel.
{
"mcpServers": {
"autocarver": {
"command": "uvx",
"args": [
"autocarver"
]
}
}
}Add to `~/.gemini/settings.json`.
{
"mcpServers": {
"autocarver": {
"type": "local",
"command": "uvx",
"args": [
"autocarver"
],
"tools": [
"*"
]
}
}
}Add to `~/.copilot/mcp-config.json`, or run `/mcp add` inside the CLI.
{
"context_servers": {
"autocarver": {
"command": {
"path": "uvx",
"args": [
"autocarver"
]
}
}
}
}Add to your Zed `settings.json`.
uvx autocarverRun `goose configure`, choose **Add Extension β Command-line Extension**, and paste this command.
Score
39 / 100
Incomplete
- Documentation21/25
- Maintenance25/25
- Trust13/20
- Capability0/15
- Install experience12/15
- Documents what it does and how to connect
- Has a resolvable package or endpoint
- Exposes at least one tool, prompt or resource
- README has substantive content
- Includes a code example
- Documents its configuration
- Mentions credentials or security posture
- Last commit 1 days ago
- Has a release history
- Repository is not archived
- Licensed MIT
- Namespace verified in the official MCP registry
- Claimed by its owner
- Published under an organisation
- 0 tool(s) documented
- Provides prompt templates
- Provides resources
- 12 documented install method(s)
- Published to a package registry
- Offers a hosted endpoint β no local install
Version history
| Versions | Published |
|---|---|
| 7.7.2Latest | Aug 30, 2026 |
| 7.7.1 | Aug 30, 2026 |
| 7.7.0 | Aug 12, 2026 |
| 7.6.3 | Aug 3, 2026 |
| 7.6.2 | Aug 3, 2026 |
| 7.6.1 | Aug 1, 2026 |
| 7.6.0 | Jul 29, 2026 |
| 7.5.5 | Jul 13, 2026 |