Skip to main content

Prism logo

Prism

Dataset Analysis MCP for Mac

A stateful Model Context Protocol server that turns LLMs into data scientists.


Load a CSV. Ask your LLM to clean it, find outliers, normalize categories, encode features, split for ML, and export a reproducible pipeline config — all through natural language.

The server maintains in-memory state across tool calls, so the LLM doesn't need to pass DataFrames back and forth. Just talk to your data.


⚡ Quick Start (macOS)

Website: kushals256.github.io/mcp-server · Download: Latest release

# Recommended
pip install dataset-analysis-mcp
dataset-analysis-mcp-setup
dataset-analysis-mcp-doctor

Then quit Claude Desktop (Cmd+Q), reopen it, and try:

Load ~/datasets/sample_sales.csv and run a data quality check

Menu bar companion

Download the DMG for the native Mac menu bar app. When active, a chart icon appears in your menu bar — click it to disable the server, open your data folder, or run a health check.

The pip setup wizard configures Claude only; it does not include the menu bar app bundle.

Claude Desktop config (auto-written by setup)

{
  "mcpServers": {
    "dataset-analysis": {
      "command": "dataset-analysis-mcp",
      "args": [],
      "env": { "MCP_DATA_DIR": "~/datasets" }
    }
  }
}

If you use uv instead of pip, uvx dataset-analysis-mcp also works.

Developer setup

git clone <repository_url> && cd mcp-server
uv sync
source .venv/bin/activate
python main.py

Releasing

  1. Bump version in pyproject.toml
  2. Commit, tag, and push: git tag v0.1.2 && git push origin main --tags
  3. The Release GitHub Action builds the DMG, uploads assets, and publishes to PyPI

For PyPI trusted publishing, add a pending publisher for workflow release.yml at pypi.org/manage/account/publishing/.


📥 Loading Datasets

There are two ways to load data into the server:

Option 1: Load from anywhere (recommended)

Use load_dataset to load files from any location on your machine — no copying required:

User: "Analyze the file at ~/Downloads/sales.csv"
→ AI calls load_dataset("~/Downloads/sales.csv")

Supported path formats:

  • Absolute: /Users/me/data/sales.csv
  • Home shorthand: ~/Downloads/sales.csv
  • Relative (from CWD): ../data/sales.csv

Supported file types: .csv, .json, .parquet, .xlsx

Option 2: Use the data/ directory

Place files in the data/ folder and use the classic workflow:

1. list_datasets()           → see what's available
2. load_dataset_metadata("sales.csv")  → load into memory

By default, data/ is resolved relative to where you start the server. You can override this with the MCP_DATA_DIR environment variable (see Configuration).


🏗️ Architecture

┌──────────────────────────────────────────────────────────────────┐
│                        LLM (Claude, etc.)                        │
└─────────────────────────────┬────────────────────────────────────┘
                              │ MCP Protocol
┌─────────────────────────────▼────────────────────────────────────┐
│                      FastMCP Server (main.py)                    │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │              GlobalStateManager (Singleton)                 │ │
│  │  ┌──────────┐  ┌───────────┐  ┌──────────┐  ┌────────────┐  │ │
│  │  │ DataFrame│  │ Test Set  │  │ Pipeline │  │Transformers│  │ │
│  │  │ (active) │  │ (hidden)  │  │ History  │  │ (fitted)   │  │ │
│  │  └──────────┘  └───────────┘  └──────────┘  └────────────┘  │ │
│  └─────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  Phase 1        Phase 3         Phase 4          Phase 4.5       │
│  ┌─────────┐   ┌───────────┐   ┌────────────┐   ┌───────────┐    │
│  │Discovery│──▶│ Analysis  │──▶│  Transform │──▶│ Normalize │    │
│  └─────────┘   └───────────┘   └────────────┘   └─────┬─────┘    │
│                                                       │          │
│  Phase 5         Phase 6         Phase 2              │          │
│  ┌──────────┐   ┌───────────┐   ┌────────────┐        │          │
│  │ Feature  │◀──│ Validate  │   │  Persist   │◀───────┘          │
│  │  Eng.    │   │  (Dry-run)│   │  (Save)    │                   │
│  └──────────┘   └───────────┘   └────────────┘                   │
└──────────────────────────────────────────────────────────────────┘

🛠️ All 29 Tools

Phase 1 — Discovery

Tool Description
list_datasets Scan data/ for CSV & JSON files
load_dataset_metadata Load a file from data/ into memory + return metadata
peek_dataset_metadata Read-only inspection — no state mutation
load_dataset Load a dataset from any path on your machine (absolute, ~, relative)

Phase 2 — Persistence

Tool Description
save_processed_dataset Save to CSV / JSON / Parquet (train or test split)
export_pipeline_config Export all operations as reproducible JSON / YAML

Phase 3 — Analysis

Tool Description
describe_dataset Statistical summary (mean, std, quantiles, value counts)
correlation_analysis Pearson · Spearman · Kendall · Cramér's V · Eta
detect_data_quality_issues Missing values · outliers · duplicates · high cardinality · zero-variance

Phase 4 — Transformation

Tool Description
drop_duplicate_rows Remove exact-match duplicate rows
handle_missing_values Impute or drop missing values (multiple strategies)
remove_outliers Z-score · IQR · Modified Z · Isolation Forest · LOF
cast_column_type Cast columns to int, float, str, bool, datetime, category
drop_columns Drop columns with duplicate-creation warnings for identity columns
encode_categorical_feature 8 methods: one-hot · label · ordinal · frequency · target · binary · hashing · leave-one-out
train_test_split Stratified splitting with immutability guarantees

Phase 4.5 — Categorical Normalization Pipeline

A 4-layer pipeline that runs before encoding to clean messy categorical data:

  ① normalize_categorical_text        surface cleanup (unicode, accents, casing)
              ↓
  ② harmonize_categorical_values      synonym → canonical mapping (FlashText)
              ↓
  ③ cluster_similar_categories        fuzzy typo clustering (RapidFuzz)
              ↓
  ④ ml_prepare_categorical            ML-aware dedup / GapEncoder (skrub)
Layer Tool Engine
1 normalize_categorical_text unicodedata · clean-text · text-unidecode
2 harmonize_categorical_values flashtext (Aho-Corasick)
3 cluster_similar_categories rapidfuzz
4 ml_prepare_categorical skrub (lazy-loaded)

Phase 5 — Feature Engineering

Tool Description
create_feature Create derived columns from Python/pandas expressions
extract_features Extract numeric features from text or datetime columns
reduce_features Dimensionality reduction (PCA, feature selection)
remove_features Drop engineered or redundant feature columns
generate_preprocessing_report Generate a summary report of all transformations

Phase 6 — Validation & Safety

Tool Description
validate_action Dry-run any tool — get memory estimates and risk flags before executing

Phase 7 — Versioning

Tool Description
list_versions List saved dataset versions in memory
rollback_version Restore a previous dataset version
diff_versions Compare two versions side by side

🔒 Safety Features

Feature How
Dry-run validation validate_action estimates memory, flags leakage risk, blocks unsafe cardinality
Source file protection save_processed_dataset blocks overwriting the loaded source file
Identity column warnings drop_columns warns when dropping ID columns would create duplicates
Split immutability train_test_split prevents re-splitting; test set is hidden from training operations
Cardinality guards One-hot encoding blocked at >100 unique values, warned at >20
Zero-variance detection detect_data_quality_issues flags constant and near-constant columns
NaN preservation All encoders explicitly preserve NaN rows through transformations

📂 Project Structure

mcp-server/
├── main.py                             # Server entry point — registers all 29 tools
├── config.py                           # Centralized thresholds & constants
├── tools/                              # Tool implementations
│   ├── discovery.py                    #   list, load, peek datasets
│   ├── save_dataset.py                 #   save data + export pipeline
│   ├── persistence.py                  #   preprocessing reports
│   ├── eda.py                          #   describe + correlation
│   ├── data_quality.py                 #   quality issue detection
│   ├── cleaning.py                     #   drop duplicates
│   ├── handle_missing_values.py        #   missing value strategies
│   ├── remove_outliers.py              #   5 outlier removal methods
│   ├── cast_column_type.py             #   type casting
│   ├── drop_columns.py                 #   column dropping + warnings
│   ├── encode_categorical.py           #   8 encoding methods
│   ├── train_test_split.py             #   stratified splitting
│   ├── normalize_categorical.py        #   Layer 1: surface cleanup
│   ├── harmonize_categorical.py        #   Layer 2: synonym mapping
│   ├── cluster_categorical.py          #   Layer 3: fuzzy clustering
│   ├── ml_prepare_categorical.py       #   Layer 4: ML-aware prep
│   ├── feature_engineering.py          #   expression-based features
│   ├── versioning.py                   #   list, rollback, diff versions
│   └── validation.py                   #   dry-run safety checks
├── utils/
│   └── state_manager.py                # GlobalStateManager singleton
├── tests/                              # 18 test suites
├── data/                               # Input/output datasets
├── pyproject.toml                      # Dependencies & build config
└── requirements.txt                    # Pip-compatible deps

🧪 Testing

# Run all tests
python -m pytest tests/ -v

# Run a specific suite
python -m pytest tests/test_encode_categorical.py -v

# Run normalization pipeline tests
python -m pytest tests/test_normalize_categorical.py \
                 tests/test_harmonize_categorical.py \
                 tests/test_cluster_categorical.py \
                 tests/test_ml_prepare_categorical.py -v

# With coverage
python -m pytest tests/ --cov=tools --cov-report=term-missing

🧑‍💻 Adding a New Tool

# 1. Create tools/my_tool.py
from utils.state_manager import GlobalStateManager

def my_tool(dataset_name: str, column: str) -> dict:
    manager = GlobalStateManager()
    df = manager.get_data()
    if df is None:
        return {"error": "No dataset loaded"}

    # ... transform df ...

    manager.load_data(df_modified, dataset_name, reset_split=False)
    manager.log_action("my_tool", {"column": column})
    return {"result": "done"}
# 2. Register in main.py
from tools.my_tool import my_tool
mcp.tool()(my_tool)
# 3. Add to validate_action (tools/validation.py)
elif tool == "my_tool":
    return ValidateActionResponse(allowed=True, reason="...", estimated_memory_mb=current_memory_mb)

⚙️ Configuration

Data Directory (MCP_DATA_DIR)

The data/ directory used by list_datasets, load_dataset_metadata, and save_processed_dataset defaults to ./data/ relative to your current working directory. Override it with an environment variable:

CLI:

export MCP_DATA_DIR=/Users/me/my-datasets
python main.py

Claude Desktop:

{
  "mcpServers": {
    "dataset-analysis": {
      "command": "/path/to/.venv/bin/python",
      "args": ["/path/to/mcp-server/main.py"],
      "env": { "MCP_DATA_DIR": "/Users/me/my-datasets" }
    }
  }
}

Note: load_dataset accepts full file paths directly, so it works regardless of MCP_DATA_DIR.

Algorithm Thresholds

All thresholds live in config.py:

Category Key Constants
Outlier Detection DEFAULT_ZSCORE_THRESHOLD=3.0, DEFAULT_IQR_MULTIPLIER=1.5
Encoding Limits ONE_HOT_MAX_CARDINALITY=20, ONE_HOT_BLOCK_CARDINALITY=100
Fuzzy Matching FUZZY_SCORE_THRESHOLD=85, FUZZY_MAX_COMPARISONS=1000
Missing Values Low/Medium/High severity thresholds
Quality Detection Cardinality ratios, skewness/kurtosis bounds

📦 Dependencies

Package Purpose
mcp Model Context Protocol server framework
pandas DataFrame operations
scikit-learn Outlier detection, label encoding, train/test split
category-encoders Target, binary, hashing, leave-one-out encoding
rapidfuzz Fuzzy string matching for category clustering
flashtext Aho-Corasick keyword replacement for synonym mapping
skrub ML-aware deduplication and GapEncoder
clean-text Unicode fixing, control char stripping
scipy Statistical tests for correlation analysis

🛠️ Troubleshooting

Server won't start
source .venv/bin/activate
python --version  # Must be 3.10+
uv sync           # or pip install -r requirements.txt
Dataset not found
  • Quickest fix: Use load_dataset("~/path/to/your/file.csv") to load from any location.
  • Using data/ folder: Make sure you're running the server from the directory that contains data/, or set MCP_DATA_DIR to point to the right place.
  • Verify: Run list_datasets() to see what the server can find.
"Unknown tool" in validate_action

Ensure the tool name matches exactly — use the registered function name, not aliases. All 29 tools are covered in validate_action as of the latest version.

Import errors

Run from the project root. Ensure __init__.py exists in tools/ and utils/.


Built with ❤️ using Model Context Protocol

Metadata

Release files for dataset-analysis-mcp 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dataset-analysis-mcp 0.1.4
File Size Uploaded
dataset_analysis_mcp-0.1.4.tar.gz 2.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for dataset-analysis-mcp 0.1.4
File Interpreter ABI Platform
dataset_analysis_mcp-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 3.0 MB

Release files / dataset_analysis_mcp-0.1.4.tar.gz

Download URL dataset_analysis_mcp-0.1.4.tar.gz
Size 2.9 MB
Tags Source
SHA-256 checksum
How to use checksums
dd826ee900b02e5cb98164dc1ba7d56e26fa764ffd805cb63c9b58f368c6f71f
BLAKE2b-256 checksum
How to use checksums
0355b3efcafe24a444bee932b4fa1fbea658862dfd4153f8168685d3b3bf7dec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / dataset_analysis_mcp-0.1.4-py3-none-any.whl

Download URL dataset_analysis_mcp-0.1.4-py3-none-any.whl
Size 89.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
264329e7c4aafae77fc804abfd787f22808477648a17c2c4ebe5cbf7038514f4
BLAKE2b-256 checksum
How to use checksums
83c84a665ad8985e7ea44302482ebc91ba813b5944592b34ab095ad8dfcf4110
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page