correlation-discovery-mcp
README.md
# correlation-discovery-mcp
**Sub-200ms Automated Correlation, Driver Discovery & Regression Outlier Detection MCP Server for any DuckDB, Parquet, or CSV Datasets**
**あらゆる DuckDB / Parquet / CSV データソースから「相関係数 ($r$値)」「目的変数に対する要因ランキング」「回帰からの外れ値(異常値)」を0.2秒で一括算出する汎用 MCP サーバー**
[](LICENSE)
[](https://modelcontextprotocol.io)
[](https://www.python.org/)
[](https://duckdb.org/)
[English](#english-documentation) | [日本語ドキュメント](#japanese-documentation)
---
<a name="english-documentation"></a>
## 🌍 English Documentation
### Why `correlation-discovery-mcp`?
When connecting local LLMs (such as **Qwen3-8B**, **Llama-3**, or **Mistral** via LM Studio / Ollama) or cloud AI agents (Claude Desktop, Cursor, Windsurf, Cline) to large tabular datasets, asking the LLM to write multi-table statistical SQL (`JOIN`, `GROUP BY`, `corr()`, `regr_slope()`, residual Z-scores) often leads to:
1. **Hallucinated table/column names** or syntax errors in complex SQL queries.
2. **Cartesian explosion (Many-to-Many JOIN traps)** when joining entity-level tables with facility/transaction-level tables.
3. **Spurious correlations** where variables appear correlated simply because of population or entity scale.
4. **Slow iterative trial-and-error** taking dozens of seconds per prompt.
**`correlation-discovery-mcp`** solves all of these problems in a single, zero-configuration MCP tool (`discover_correlations`):
- **Zero-Hardcoding Dynamic Schema Introspection**: Automatically scans any `.duckdb`, `.parquet`, or `.csv` files in `DATA_SOURCE_DIR`, dynamically detecting shared join keys (`municipality_code`, `prefecture`, `corporate_number`, `year`, `region_code`, `customer_id`, etc.) and numeric metric columns. Add 100+ new Parquet files and it adapts with **zero code changes**.
- **Sub-200ms Statistical Execution**: Pre-aggregates key-level vectors with automatic signature caching to compute exact Pearson $r$, $R^2$, linear regression slopes/intercepts, top/bottom 5 records, and **top 5 regression outliers (anomalies with residual Z-scores)** in **0.01s – 0.15s**.
- **Per-Capita Normalization (`normalize_by`)**: Eliminates spurious correlations caused by population or company size in a single parameter (`normalize_by="population"`).
- **Analytical Perspective Prompts (`include_perspective_prompts`)**: Automatically attaches structured reasoning prompts (outlier deep-dive, reverse causality & confounder check, bottom-tier structural commonality) grounded in the actual computed records.
- **Enterprise-Grade Security & Sandboxing**:
- Connects to external DuckDB databases strictly with `read_only=True` and locks down the engine with `enable_external_access=false` and `lock_configuration=true` (SELECT-only execution).
- Confines cache file writes strictly within the designated directory using `Path.resolve()` path-traversal verification (`../` rejected) with zero file-deletion capabilities.
- Wraps untrusted/external text labels in `<untrusted_data>...</untrusted_data>` boundary tags to prevent prompt injection.
---
### ✨ Three Unified Exploration Modes (`discover_correlations`)
| Mode | Purpose | Required / Key Parameters | What It Returns in <0.2s |
| :--- | :--- | :--- | :--- |
| **`"pair"`** | **Verify a Specific Pair & Detect Anomalies** | `table_x`, `column_x`, `table_y`, `column_y` | Exact Pearson $r$, $R^2$, sample size $n$, regression slope/intercept, **Top 5 & Bottom 5 records**, and **Top 5 Regression Outliers** (actual vs. predicted $Y$ and residual Z-score). |
| **`"find_drivers"`** | **Exhaustive Driver Ranking Scan** | `target_table`, `target_column` | Scans **all joinable tables and numeric columns** against your target variable, returning ranked **Top Positive Drivers**, **Top Negative Drivers**, and each driver's #1 outlier. |
| **`"serendipity"`** | **Cross-Domain Unexpected Discovery** | *(None — just `mode="serendipity"`)* | Cross-references tables across **different semantic categories** to surface unexpected strong correlations ($\|r\| \ge 0.5$) and notable anomalies when you don't have a hypothesis yet. |
---
### 🚀 Quick Start
#### 1. Installation
```bash
git clone https://github.com/japan-opendata-lab/correlation-discovery-mcp.git
cd correlation-discovery-mcp
pip install -e .
```
#### 2. Configure in LM Studio (`~/.lmstudio/mcp.json`) or Claude Desktop / Cursor
Point `DATA_SOURCE_DIR` to **any directory containing `.parquet` / `.csv` / `.duckdb` files**, or directly to a `.duckdb` database file:
```json
{
"mcpServers": {
"correlation-discovery-mcp": {
"command": "python",
"args": [
"-X",
"utf8",
"./oss_mcp/correlation-discovery-mcp/server.py"
],
"env": {
"PYTHONIOENCODING": "utf-8",
"DATA_SOURCE_DIR": "./data/platform_dist/global_megabank.duckdb;./data/dist"
}
}
}
}
```
---
### 🔗 Synergy with `japan-data-mcp` & Japan Official Data Megabank (RapidAPI)
While `correlation-discovery-mcp` works with **any custom DuckDB / Parquet / CSV dataset worldwide**, it becomes an instant socioeconomic intelligence engine when paired with the **162+ standardized Japanese & Global datasets** from **Japan Open Data Lab**:
- **MCP Companion Server**: [`japan-data-mcp`](https://github.com/japan-opendata-lab/japan-data-mcp) — Search, inspect, and fetch normalized records across 162 official government datasets (Demographics, Official Land Prices, GEPS Procurement, Medical/DPC Hospitals, Vacant Houses, Renewable Energy, Crime/Safety, etc.).
- **Official Python SDK**: [`japan-official-data-megabank`](https://github.com/japan-opendata-lab/japan-official-data-megabank)
- **Cloud API Hub (RapidAPI)**: [Japan Official Data Megabank API on RapidAPI](https://rapidapi.com/organization/japan-opendata-lab)
- **Sample Parquet Datasets (Hugging Face)**: [`japan-opendata-lab/japan-official-data-megabank`](https://huggingface.co/datasets/japan-opendata-lab/japan-official-data-megabank)
#### Example Workflow: Local LLM (`Qwen3-8B`) + `correlation-discovery-mcp` + `japan-data-mcp`
1. **Discover Drivers (`find_drivers`)**: Ask *"What factors drive official land prices (`land_prices_official`) across Japanese municipalities?"* → `correlation-discovery-mcp` scans 900+ numeric columns across 160+ datasets in **0.05 seconds**, revealing top positive drivers (`building_construction` $r=+0.98$, `daily_traffic_volume` $r=+0.90$, `demographics` taxable income $r=+0.71$) and negative drivers (`surveillance_cameras` $r=-0.77$, `ski_resorts` $r=-0.72$).
2. **Inspect Regression Outliers (`pair`)**: Verify `demographics` (taxable income) vs. `land_prices_official` ($r=+0.7105, n=1,354$) and immediately spot municipalities whose land prices significantly outperform or underperform their income trend line (`residual_z_score > +3.0σ`).
3. **Fetch Entity Details (`japan-data-mcp`)**: Pass the discovered outlier `municipality_code` to `japan-data-mcp` (`search_japan_official_data`) to inspect specific infrastructure, procurement contracts, or hospital facilities in that exact municipality.
---
<a name="japanese-documentation"></a>
## 🇯🇵 日本語ドキュメント
### なぜ `correlation-discovery-mcp` が必要なのか?
LM Studio 上のローカルLLM(`Qwen3-8B` 等)や Claude Desktop / Cursor などの AI エージェントに DuckDB や Parquet データを分析させる際、LLM 自身に複雑な統計 SQL(複数テーブルの `JOIN`、キー別事前集約、`corr()`、`regr_slope()`、残差 Zスコアによる外れ値抽出)を書かせると、以下の課題が頻発します。
1. **カラム名・テーブル名のハルシネーション**や複雑な SQL 構文エラー
2. **多対多 JOIN による直積爆発(Cartesian Explosion)**と計算時間の肥大化
3. **人口規模や企業規模による「見せかけの相関(擬似相関)」**の見落とし
4. **外れ値(回帰直線から大きく外れた異常値レコード)**の算出漏れ
**`correlation-discovery-mcp`** は、これらの課題を単一の統合ツール `discover_correlations` で解決するオープンソースの高速統計探索エンジンです。
### 4大特徴
1. **スキーマ自動検出(ハードコード完全ゼロ)**
- 接続先の DuckDB (`.duckdb`) / Parquet (`.parquet`) / CSV (`.csv`) 群から、「結合可能な共通キー(`municipality_code`, `prefecture`, `corporate_number`, `year`, または任意の同名ID列)」と「数値型カラム」を動的に自動検出します。
- データセットが今後何百個増えても、また独自業務データ(売上・顧客・センサー・金融データ等)に差し替えても、**コード変更ゼロ**で即座に自動対応します。
2. **0.2秒以内の超高速一括算出**
- DuckDB のカラムナ集計とデータソース署名(SHA-256)に基づく自動ベクトルキャッシュにより、160テーブル超・900カラム超の総当たりスキャンでも **0.005秒〜0.15秒(200ms未満)** で応答します。
3. **1ツール・3モード統合 + 擬似相関除去 & 分析視点プロンプト付与**
- **`mode="pair"`(指定ペア検証)**: 2つのテーブル・数値カラム間のピアソン相関係数 ($r$値)、決定係数 ($R^2$)、サンプル数 $n$、上位/下位5件、および回帰直線から最も離れた**「外れ値(異常値レコード5件・残差Zスコア付き)」**を正確に算出。
- **`mode="find_drivers"`(要因総当たりスキャン)**: 指定した1つの目的変数(例:公示地価、空き家率、売上など)に対し、共通キーで結合可能な他の全テーブル・全数値カラムを総当たりスキャンし、正の相関・負の相関が強い順にランキング形式で返却。
- **`mode="serendipity"`(未知の相関発掘)**: 分析テーマが決まっていない時の探索モード。異なるカテゴリのテーブル同士を掛け合わせ、偶然強い相関($\|r\| \ge 0.5$)や顕著な外れ値が出ている異種ペアを自動発掘。
- **`normalize_by`(任意)**: 人口(`population`)等で割った「1人あたり(Per Capita)」で正規化し、都市規模等による見せかけの相関(擬似相関)を除外。
- **`include_perspective_prompts`(デフォルト `True`)**: 算出された実データの外れ値名や相関係数を埋め込んだ4つの分析視点(外れ値の深掘り、逆因果・交絡因子の検討、最下位グループの共通点分析、次の検証アクション)をメタデータとして自動付与。
4. **厳格なセキュリティ&サンドボックス設計**
- DuckDB 接続時は `read_only=True` および `enable_external_access=false` / `lock_configuration=true` を徹底し、単一 `SELECT` 文のみを許可。
- ファイル出力時は `Path.resolve()` により指定ディレクトリ外のパストラバーサル(`../`)を厳格に検知・拒否し、ファイル削除機能は一切持ちません。
- 外部由来のテキストはプロンプトインジェクション対策として `<untrusted_data>...</untrusted_data>` データ境界タグで囲み、システム命令として解釈されないよう無害化します。
---
### 🛠 セットアップと LM Studio / Claude Desktop 登録方法
#### 1. インストールと単体テストの実行
```bash
git clone https://github.com/japan-opendata-lab/correlation-discovery-mcp.git
cd correlation-discovery-mcp
pip install -e ".[dev]"
pytest -v
```
#### 2. LM Studio (`~/.lmstudio/mcp.json`) への登録例
```json
{
"mcpServers": {
"correlation-discovery-mcp": {
"command": "python",
"args": [
"-X",
"utf8",
"./oss_mcp/correlation-discovery-mcp/server.py"
],
"env": {
"PYTHONIOENCODING": "utf-8",
"DATA_SOURCE_DIR": "./data/platform_dist/global_megabank.duckdb;./data/dist"
}
}
}
}
```
> **💡 任意の独自データで使いたい場合**:
> 環境変数 `DATA_SOURCE_DIR` にご自身の `.duckdb` ファイルや `.parquet` / `.csv` が入ったフォルダパスを指定するだけで、共通ID列と数値カラムを自動検出して即座に分析可能です。
---
### 📊 出力サンプル (`mode="pair"`)
```json
{
"status": "success",
"mode": "pair",
"join_key": "municipality_code",
"aggregation": "AVG",
"normalized_by": null,
"pair": {
"table_x": "demographics",
"column_x": "capital_amount_jpy",
"category_x": "demographics_population",
"table_y": "land_prices_official",
"column_y": "capital_amount_jpy",
"category_y": "real_estate_housing"
},
"statistics": {
"pearson_r": 0.7105,
"r_squared": 0.5048,
"sample_size_n": 1354,
"regression_slope": 0.341285,
"regression_intercept": -984120.5,
"strength_interpretation": "strong_positive"
},
"top_5_records": [
{ "key": "13101", "label": "千代田区, 東京都", "x_value": 10065653.0, "y_value": 5495833.3333 },
{ "key": "13102", "label": "中央区, 東京都", "x_value": 7598445.0, "y_value": 5178378.3784 }
],
"outliers": [
{
"key": "13102",
"label": "中央区, 東京都",
"x_value": 7598445.0,
"y_value": 5178378.3784,
"predicted_y": 1609114.2,
"residual": 3569264.18,
"residual_z_score": 14.82,
"direction": "above_trend"
}
],
"perspective_prompts": [
{
"perspective": "outlier_anomaly_deep_dive",
"title": "回帰外れ値(異常値レコード)の固有要因分析 / Outlier Deep-Dive",
"prompt": "回帰直線から最も大きく乖離している筆頭外れ値 <untrusted_data>中央区, 東京都</untrusted_data> (key=13102) に着目してください..."
}
],
"elapsed_seconds": 0.0052
}
```
---
### 🌐 関連エコシステム(Japan Open Data Lab)
- **[`japan-data-mcp`](https://github.com/japan-opendata-lab/japan-data-mcp)**: 日本の公的オープンデータ(全162データセット・1,150万件超)を自然言語・標準フィルタ・SQLで検索できる公式 MCP サーバー
- **[`japan-official-data-megabank`](https://github.com/japan-opendata-lab/japan-official-data-megabank)**: 公式 Python SDK & スターターキット
- **[RapidAPI Hub — Japan Open Data Lab](https://rapidapi.com/organization/japan-opendata-lab)**: クラウド API サブスクリプション(無料 BASIC プランあり)
- **[Hugging Face Datasets](https://huggingface.co/datasets/japan-opendata-lab/japan-official-data-megabank)**: サンプル Parquet データセット公開ページ
---
## License
MIT License — Copyright (c) 2026 Japan Open Data Lab (`japan.opendata.lab@gmail.com`)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues