StatTools
Allows AI agents to load data as pandas DataFrames and perform data manipulation and analysis using pandas functions.
Provides a Python runtime with access to libraries such as sklearn, statsmodels, scipy, and pandas for statistical modeling and data science tasks.
Allows AI agents to call functions from SciPy for scientific computing and statistics.
Enables AI agents to use R packages from the tidyverse ecosystem, including dplyr, tidyr, and ggplot2, for data manipulation and visualization.
Click on "Install 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., "@StatToolssearch for linear regression"
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.
StatTools
MCP server that lets AI agents discover and call R and Python statistical functions without writing code.
What It Does
Search ~48k functions on a fresh clone after
build-index, and ~336k after the full Phase 7 + 7b tarball waves:"mixed effects model"findslme4::lmerValidate before executing:
stat_resolvechecks safety, generates parameter schemaExecute with structured JSON input/output: no R syntax, no script files, no console parsing
Track session state: data handles, model handles, resolved functions
Call methods on Python objects:
model.fit(X, y),model.predict(X_test),scaler.transform(X)Auto-index after install:
stat_installmakes new packages immediately searchable
Related MCP server: AutoLearn MCP Server
Architecture
Agent (Claude Code / Cursor / custom)
| MCP protocol (stdio)
v
TypeScript MCP Server
|-- SQLite FTS5 search index (~48k fresh-clone baseline, ~336k after the Phase 7 + 7b tarball waves)
|-- R Worker Pool (persistent subprocess, hot-standby, recycle/crash recovery)
|-- Python Worker (persistent subprocess, sklearn/statsmodels/scipy/pandas)
+-- Session state (handles, resolved functions, install jobs)Quick Start
Prerequisites
Node.js 22.x (enforced — see
.nvmrc)R >= 4.1 with
jsonlitepackage installedPython 3 with sklearn/statsmodels/scipy/pandas (optional — for Python workflows)
Install & Build
cd stattools
nvm use # Use pinned Node 22.x
npm install
npm run buildBuild the Search Index
npm run build-indexIndexes all installed R packages + CRAN metadata (~2 minutes).
Connect to Claude Code
Add to ~/.claude/settings.json. Use the full path to your Node 22 binary — better-sqlite3 will crash under a different Node version:
{
"mcpServers": {
"stattools": {
"command": "/path/to/.nvm/versions/node/v22.x.x/bin/node",
"args": ["/absolute/path/to/stattools/dist/index.js"],
"env": {
"STATTOOLS_DATA_ROOTS": "/Users/me/data:/tmp",
"R_PATH": "/path/to/Rscript",
"PATH": "/path/to/R/bin:/path/to/node/bin:/usr/bin:/bin"
}
}
}
}Find your Node 22 path with nvm which 22. R_PATH and PATH must include Rscript for the R worker pool to function.
Tools
Tool | Purpose |
| Search functions by natural language. Returns ranked results with safety class. |
| Validate a function + get full parameter schema. Required before |
| Execute a resolved function with JSON arguments. Returns structured results. |
| Call a method on a Python session object (fit, predict, transform, score). |
| Load CSV/TSV/RDS into session. Supports |
| View session state: handles, resolved functions, worker status, install jobs. |
| Inspect a handle: schema, head, dimensions, summary, str. |
| Install a CRAN package (async). Auto-indexes on completion. |
Example: R Workflow
stat_search({ query: "linear regression" })
-> stats::lm (safe), MASS::lm.ridge (safe), ...
stat_resolve({ package: "stats", function: "lm" })
-> { resolved: true, safety_class: "safe", schema: { formula, data, ... } }
stat_load_data({ file_path: "/tmp/sales.csv" })
-> { object_id: "sales", dimensions: { rows: 1000, cols: 8 }, ... }
stat_call({ package: "stats", function: "lm", args: { formula: "revenue ~ ad_spend", data: "sales" } })
-> { r_squared: 0.73, coefficients: { ad_spend: { estimate: 2.3, p_value: 0.001 }, ... } }Example: Python Workflow
stat_load_data({ file_path: "/tmp/data.csv", runtime: "python", name: "df" })
-> { object_id: "df", class: "DataFrame", dimensions: { rows: 500, cols: 10 } }
stat_resolve({ package: "sklearn.linear_model", function: "LinearRegression" })
-> { resolved: true, runtime: "python", schema: { ... } }
stat_call({ package: "sklearn.linear_model", function: "LinearRegression", args: {}, assign_to: "model" })
-> { objects_created: [{ id: "model", type: "model" }] }
stat_method({ object: "model", method: "fit", positional_args: ["X_train", "y_train"] })
-> { coefficients: [2.3, -0.5], intercept: 1.2 }
stat_method({ object: "model", method: "predict", positional_args: ["X_test"], assign_to: "preds" })
-> { class: "ndarray", shape: [100], ... }Safety Model
Functions are classified into tiers:
Class | Behavior |
| Fully callable. Pure computation. |
| Callable with warnings (e.g., NSE, graphics, RNG). |
| Blocked. File writes, network, system modification. |
| Blocked by default. Discoverable but not callable. |
2,024 safety overrides in CSV (~2,048 classified in the built DB including Python defaults). Unclassified functions are blocked — extend coverage by adding entries to data/safety_overrides.csv.
Search Quality
Benchmark: 111 queries across 12 categories.
Fresh clone (after build-index only): ~48k functions, ~570 classified. Benchmark pass rate depends on which packages are installed locally and whether tarball extraction has been run. Expect ~90% on a standard R installation.
Expanded index (after the full Phase 7 + 7b tarball waves + ranking/callability updates): ~336k functions, ~2.0k classified. 100% top-3 and 93% top-1 on 97/97 installable queries (MRR: 0.962) — tested on a machine with a rich local R library including the easystats suite. ML, IO, visualization, mixed-models, wrangling, and diagnostics categories are at 100% top-1; weaker categories (testing, bayesian) sit at 83%.
The headline 100% number requires both a rich local R library and tarball extraction. Your mileage will vary based on which packages are installed.
Environment Variables
Variable | Default | Description |
| Current directory | Colon-separated list of allowed data directories |
|
| Path to Rscript binary |
Setup Validation
After build + index, verify everything works:
npm run validate # Checks Node, R, build, index, server, and runs a real workflowThis runs 14 checks including safety-override integrity, starting the MCP server, inspecting Python runtime health, and executing a complete search → resolve → load → call → session workflow.
For real external-client validation through Claude Code CLI, including exact prompts for OLS, mixed-effects, reshape, ggplot2, and glmnet, see AGENT_WORKFLOW_RUNBOOK.md.
Development
nvm use # Enforce Node 22.x
npm test # Run the hermetic default test suite
npm run test:tarball-live # Optional live CRAN tarball smoke test
npm run test:benchmark # Run the heavy 111-query benchmark separately
npm run test:watch # Watch mode
npm run build # Compile TypeScript
npm run build-index # Rebuild search index
npm run apply-safety-overrides # Sync safety_overrides.csv into the current DB
npm run check-safety-overrides # Fail if safety_overrides.csv has orphan or duplicate IDs
npm run validate # Full setup validationStatus: Beta for Tier A workflows (v0.2.0)
Phase 6 closed with a four-round agent eval going from 80% → 84% → 92% → 98% weighted pass rate on a 25-task representative workflow set. The single remaining non-pass is an upstream R-package bug. See phase6-retrospective.md for the full story.
What works reliably:
Search: ~90% top-3 on a fresh clone. On the fully expanded Phase 7 + 7b index, the benchmark is 100% top-3 and 93% top-1 on 99 installable queries (MRR 0.963).
Core R workflows: OLS, logistic, t-test, ANOVA, correlation, random forest, PCA, k-means, mixed effects (lme4 random intercept/slope/GLMM), survival (Kaplan-Meier, Cox PH, Weibull), robust SE, broom tidy, VIF, stepwise selection, time series (auto.arima, STL, forecast), Bayesian regression (rstanarm), polynomial regression with model comparison, fixest panel regression — all validated end-to-end through agent evals.
Data loading: CSV/TSV/RDS via
file_path, built-in R datasets viadataset(mtcars, iris, sleepstudy, lung, cbpp, Grunfeld, AirPassengers, ...), pandas DataFrame viaruntime="python". Handles register identically.NSE-heavy verbs (dplyr, tidyr, ggplot2::aes):
stat_call'sexpressionsanddot_expressionsfields take R expression strings, parsed viarlang::parse_exprand forwarded as quosures. dplyr data-mask pronouns liken()and tidyselect helpers likeeverything()/-Speciesresolve correctly.stat_resolvereturns annse_hintfield for ~15 known NSE functions with worked examples.Multi-object dispatch (
anova(m1, m2),AIC(m1, m2)):stat_call'sdot_argsfield resolves session handle IDs as positional...args.Class coercion (factor/ts/matrix):
stat_call'scoercefield accepts whitelisted specs (factor,ts(frequency=N), etc.) and applies them before the call.stat_resolve'sclass_hintfield tells you when to use it.Python workflows: structured errors with
python_state(spawn_failed/modules_missing/crashed/healthy),python_path,missing_modules,recent_stderr, andhint— no separatestat_sessionround trip required.Verbose R functions: console output is captured/suppressed so it does not pollute the NDJSON channel.
Handle system: models and data persist in session across calls.
Install + auto-reindex:
stat_installinstalls and makes packages immediately searchable.Worker stability: hot-standby pool, crash recovery, handle persistence across recycles.
What works with caveats:
Python install path: the server uses whatever
python3/PYTHON_PATHresolves to at startup. If youpip installinto a different interpreter, the server won't see the modules. Install into the binarystat_sessionreports underpython.path, or setPYTHON_PATHexplicitly.Bayesian: rstanarm/brms are slow (MCMC compilation) and classified as
callable_with_caveats.bayestestR::hdi(stanreg_model)currently throws a names-length error on rstanarm fits (upstream bug) — usebayestestR::describe_posterior(model, ci_method="HDI")instead.lm(weights = ...): theweightsarg is captured viamodel.frame, not the rlang/dplyr NSE machinery.expressions={"weights": "1/hp"}is rejected. Workaround: extract the column withstat_extractand pass the resulting numeric vector handle.S3 dispatch on first positional arg (
randomForest,survival::Surv, etc.): when bothformulaandxare passed, R silently falls through to.default(matrix mode). Workaround: use matrix form (x=,y=) withcoerce={y:"factor"}for classification, or pass the formula as the first positional arg.
What doesn't work yet:
Only ~2.0k of ~336k functions are classified as callable. The rest are discoverable but blocked by the fail-closed safety model. Extend coverage by adding entries to
data/safety_overrides.csv.~14.9k packages are still stubs (no function-level metadata).
data/tarball_targets_phase7.txtcovers 8,500 priority packages.Tarball expansion is network-bound and incremental.
npm testis hermetic;npm run test:tarball-liverequires live CRAN access.Top-1 search accuracy is 93%; weakest in
testingandbayesiancategories at 83%. Top-3 remains 100%.No multi-tenant support — single-user local server only.
Known environment requirements:
Node 22.x (enforced; better-sqlite3 will crash on other versions)
R >= 4.1 with jsonlite
macOS or Linux (not tested on Windows)
For Python workflows: python3 with sklearn, scipy, statsmodels, pandas
Tier A Packages
Deeply classified packages with safety overrides, curated aliases, and workflow tests:
Core Stats: stats, base, utils, MASS, boot, cluster Tidyverse: dplyr, tidyr, ggplot2, readr, purrr, stringr, forcats, tibble, scales Modeling: lme4, nlme, mgcv, glmnet, survival, sandwich, car, lmtest, forecast ML: caret, randomForest, rpart, nnet, e1071 Model Output: broom, emmeans, marginaleffects, performance, parameters, effectsize Bayesian: rstanarm, brms, bayestestR Specialized: psych, lavaan, vegan, datawizard, insight, haven, data.table, fixest Python: sklearn (linear_model, ensemble, tree, svm, neighbors, cluster, decomposition, preprocessing, metrics, model_selection), statsmodels, scipy.stats, pandas
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/zhangxiany-tamu/StatTools'
If you have feedback or need assistance with the MCP directory API, please join our Discord server