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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dataset_analysis_mcp-0.1.2.tar.gz (2.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dataset_analysis_mcp-0.1.2-py3-none-any.whl (89.6 kB view details)

Uploaded Python 3

File details

Details for the file dataset_analysis_mcp-0.1.2.tar.gz.

File metadata

  • Download URL: dataset_analysis_mcp-0.1.2.tar.gz
  • Upload date:
  • Size: 2.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dataset_analysis_mcp-0.1.2.tar.gz
Algorithm Hash digest
SHA256 7d5d3a8e2c8f0789d53b86eea4894c4fb77ffdaba64f854aa763e5a6958f29f2
MD5 5b972b418da65fd89c3bb587995b3c3e
BLAKE2b-256 1b01cba6559de71eb112aadf59d1d54c723d4e5af20fc6d58cf1341565084d9d

See more details on using hashes here.

Provenance

The following attestation bundles were made for dataset_analysis_mcp-0.1.2.tar.gz:

Publisher: publish-pypi.yml on kushals256/mcp-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dataset_analysis_mcp-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for dataset_analysis_mcp-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f574b419f898bbac86966394af42cf398375a9f895aa7681400afe40e8957e88
MD5 123505a6989b489b82c1aca738b4d447
BLAKE2b-256 3a3d1edc83c3b8be55a97a225bd4868303d47700c9e3b400e41842739d716f79

See more details on using hashes here.

Provenance

The following attestation bundles were made for dataset_analysis_mcp-0.1.2-py3-none-any.whl:

Publisher: publish-pypi.yml on kushals256/mcp-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page