Skip to main content
Glama
Kirill-FD

llm-analytics-mcp

by Kirill-FD

MCP統合を備えたLLMベースの分析システム

MCPサーバーは、言語モデルに表形式データ分析のためのツール一式(読み込み、クリーニング、グラフ作成、レポート生成)を提供します。独自のチャットインターフェースは開発せず、既製プラットフォームのウェブインターフェースを使用します(メインクライアントはClaude、代替はChatGPT)。

同じツールレジストリが、2つのプロトコルで同時に公開されます。

プロトコル

エンドポイント

クライアント

MCP (Streamable HTTP)

/mcp

Claude — ウェブ、デスクトップ、任意のMCPクライアント

REST + OpenAPI

/tools/*, /openapi.json

ChatGPT Custom GPT Action


システムのできること

12のツール、5つのスキル。 完全な一覧は describe_system の呼び出し、または ARCHITECTURE.md にあります。

ツール

スキル

用途

list_datasets

—

利用可能なデータのカタログ

load_data

DataLoadingSkill

カタログ、パス、またはURLからCSV/TSV/Excel/JSON/Parquetを読み込む

describe_data

DataLoadingSkill

構造、型、欠損、重複

clean_data

DataCleaningSkill

重複、欠損、正規化、外れ値

suggest_analysis

InsightGenerationSkill

データ構造に合わせた分析プランの自動提案

plot_trend

VisualizationSkill

メトリクスの時間推移

plot_distribution

VisualizationSkill

ヒストグラムまたはバーチャート(タイプは自動選択)

correlation_analysis

VisualizationSkill

相関のヒートマップ

plot_breakdown

VisualizationSkill

カテゴリ別のメトリクス内訳

collect_evidence

InsightGenerationSkill

レポート本文用の検証可能な数値

build_report

ReportingSkill

Markdown、HTML、PDF形式のレポート

describe_system

—

自己検証: スキルとツールの構成

追加機能:

  1. 分析の自動提案 — suggest_analysis は、どの列が時間軸で、どの列がメトリクスで、どの列が切り口かを判定し、各ステップの根拠とともに、すぐに使える呼び出しプランを返します。

  2. マルチフォーマット&マルチソース — CSV、TSV、Excel、JSON、Parquet、カタログ、ローカルパス、またはHTTP(S)リンク。最後の点はウェブシナリオで重要です。ブラウザチャットにアップロードされたファイルはサーバーからアクセスできないためです。

  3. 1コマンドでのレポート生成 — build_report は不足しているグラフを自動で補完し、3つの形式でドキュメントを出力します。


Related MCP server: Claude Data Buddy

インストール

Python 3.10以降が必要です。

git clone <адрес-репозитория>
cd llm-analytics-mcp

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

pip install -r requirements.txt

ステップ1. テストデータ

リポジトリのデータは、Superstoreスキーマに基づいて合成生成されています。仕様書でも明確に認められています。「データは自分で生成するか、既知のデータセットを使用してよい」と。

python scripts/prepare_dataset.py --synthetic --rows 4000

完成済みのファイルはすでに data/ にあります。コマンドが必要なのは、ファイルを再生成したい場合やデータ量を変更したい場合だけです。

なぜKaggleではなく合成データか

ジェネレータを使うと、システムが何をデモするのかを正確に制御できます。

  • 検証可能なパターンが組み込まれている — 上昇トレンド、年末にピークを迎える年間季節性、「割引率30%超 → マイナス利益」の関連性。これにより、分析結果は偶然ではなく意味のあるものになります。

  • 欠陥は意図的に混入されている。 実際のSuperstoreはほぼ完璧にクリーンで、欠損も重複もないため、DataCleaningSkill は「0行削除」と報告し、クリーニングのデモができなくなってしまいます。

  • 再現性。 seed=42 に固定しているため、検証者は例と同じデータとレポート内の同じ数値を得られます。

  • リポジトリは自己完結している。 プロジェクトを実行するためにKaggleアカウントは不要です。

実際のSuperstoreの読み込みにも対応しています。列構造が同じだからです。

python scripts/prepare_dataset.py --input ~/Downloads/Sample-Superstore.csv

スクリプトが生成するもの

ファイル

用途

data/superstore_clean.csv

仕様書の列に合わせたデータ

data/superstore_raw.csv

同じテーブルに欠陥を混入したもの

列は Date、Product、Region、Sales、Quantity、Profit(仕様書より)に加え、切り口として Category、Sub-Category、Segment、Discount、Ship Mode があります。期間は2021〜2024年の48か月間です。

欠陥の内訳は実行時に表示され、決定的です。

欠陥

量

Sales / Profit / Quantity の欠損

~3.5% / 4.5% / 2%

完全に重複した行

~0.8%

Region の表記ゆれ(west、East、CENTRAL)

~6%の行

Sales の極端な外れ値

12行

代替日付形式(15/03/2022)

~10%の行


ステップ2. サーバーなしでの確認

読み込みからPDFレポートまでの全チェーンを一気通貫で実行します。

PYTHONPATH=src python -m analytics_mcp.selfcheck

このスクリプトは、LLMがダイアログで行う処理を決定的に再現します。デモ前のスモークテストとして有用です。これが通れば、問題はほぼ確実に分析ではなく統合にあります。


ステップ3. サーバーの起動

PYTHONPATH=src uvicorn analytics_mcp.app:app --host 127.0.0.1 --port 8000

確認:

curl http://127.0.0.1:8000/health

便利なアドレス:

アドレス

内容

http://127.0.0.1:8000/health

ステータスと登録済みコンポーネントの数

http://127.0.0.1:8000/docs

Swagger UI: すべてのツールを手動で呼び出せる

http://127.0.0.1:8000/openapi.json

Custom GPT Action用の仕様書

http://127.0.0.1:8000/mcp

MCPエンドポイント

ポートが占有されている場合。 以前に起動したプロセスが古いコードのまま応答し続けることがあります。この症状は分かりにくく、/health は応答するのに変更が反映されません。再起動する前に: pkill -f uvicorn


ステップ4. ngrokによる公開アドレス

Claudeは外部からサーバーにアクセスするため、HTTPSアドレスが必要です。

# 1. Установка и регистрация: https://ngrok.com/download
ngrok config add-authtoken <ваш-токен>

# 2. В личном кабинете ngrok зарезервируйте бесплатный статический домен
#    (Domains -> Create Domain). Без него адрес меняется при каждом
#    перезапуске, и настройку коннектора придётся повторять.

# 3. Запуск туннеля
ngrok http 8000 --domain=ваш-домен.ngrok-free.app

次に、アドレスを環境に設定してサーバーを再起動します:

cp .env.example .env
# в .env укажите:
#   PUBLIC_BASE_URL=https://ваш-домен.ngrok-free.app

export PUBLIC_BASE_URL=https://ваш-домен.ngrok-free.app
export MCP_ALLOWED_HOSTS='127.0.0.1:*,localhost:*,*.ngrok-free.app'
PYTHONPATH=src uvicorn analytics_mcp.app:app --host 127.0.0.1 --port 8000

「接続できない」の最も多い原因。 MCP SDKはデフォルトでDNSリバインディング対策を有効にしており、Host ヘッダーが localhost の場合のみ受け入れます。トンネル経由では Host にngrokのドメインが含まれるため、コネクタの接続段階でリクエストが拒否され、インターフェースには明確なエラーが表示されません。環境変数 MCP_ALLOWED_HOSTS がまさにこの問題を解決します。


ステップ5. Claudeへの接続(メインシナリオ)

  1. Settings → Connectors → Add custom connector を開きます。

  2. アドレスを指定します: https://ваш-домен.ngrok-free.app/mcp(末尾の /mcp に注意)。

  3. 保存し、コネクタが接続済み状態になることを確認します。

  4. 新しい会話で、ツールメニューからコネクタ analytics_mcp を有効にします。

  5. prompts/system_prompt.md の内容をプロジェクトの説明(Project instructions)にコピーします。これにより呼び出し順序が指定されます。

確認用のリクエスト: 「どのデータセットが利用できますか?」 — モデルは list_datasets を呼び出し、カタログの内容を表示するはずです。


ステップ6. ChatGPTへの接続(代替シナリオ)

  1. 公開アドレスから仕様書を取得します:

PUBLIC_BASE_URL=https://ваш-домен.ngrok-free.app \
  PYTHONPATH=src python scripts/export_openapi.py
  1. Custom GPTを作成します: Explore GPTs → Create → Configure。

  2. Create new action → Schema — openapi.json の内容を貼り付けます。

  3. Authentication: None。

  4. Instructionsフィールドに prompts/system_prompt.md を貼り付けます。

詳細とグラフ表示の注意点は prompts/gpt_action_setup.md にあります。


デモシナリオ

リクエストの順序は、単一のリクエストではなく呼び出しチェーンがスクリーンショットに写るように調整されています。重要な場面はステップ4で、ハードコードではなくモデルが何を計画しているかが分かります。

#

ユーザーからのリクエスト

期待される呼び出し

1

どのデータセットが利用できますか?

list_datasets

2

superstore_rawを読み込んで構造を説明して

load_data, describe_data

3

データをクリーニングして

clean_data

4

ここでは何を分析すべきですか?

suggest_analysis

5

これらのグラフを作成して

plot_trend, plot_breakdown, plot_distribution, correlation_analysis

6

結論と推奨事項を含むレポートを作成して

collect_evidence, build_report

結果の例は docs/report_example.md、グラフは docs/plots/ にあります。


動作スクリーンショット

デモ資料は docs/screenshots/ にあります。

ファイル

内容

01-list-datasets.png

Claudeが list_datasets を呼び出し、サーバーのカタログを表示している

02-clean.png

clean_data のレポート: Regionの正規化、30件の重複、817件の外れ値

02.2-clean.png

データセットの「欠損補完あり」と「なし」のバージョン比較

03-suggest-analysis.png

モデルがレポートの仮説を新しいツール呼び出しで検証している

03.2-suggest-analysis.png

今後の分析方針の優先順位付きリスト

04-plots.png

グラフの作成。モデルがツールのできないことを明示的に指摘している

スクリーンショットは、システムの重要な特性を示しています。呼び出しチェーンを制御するのはLLMです。モデルはどのツールを呼び出すかを自ら決定し、ツールセットの制約(たとえば行フィルタリングがないこと)を発見し、出力を無理に合わせるのではなく、それを報告します。

統合の確認

# Полный цикл по обоим транспортам: initialize, tools/list, tools/call,
# возврат изображения, обработка ошибочных аргументов
python scripts/integration_test.py

リポジトリ構造

llm-analytics-mcp/
├── README.md                    инструкция (этот файл)
├── ARCHITECTURE.md              архитектура и роль MCP/скиллов
├── openapi.json                 спецификация для Custom GPT Action
├── requirements.txt
├── .env.example
├── data/                        тестовые данные
├── docs/
│   ├── report_example.md/html/pdf   пример сгенерированного отчёта
│   ├── plots/                       примеры графиков
│   └── screenshots/                 скриншоты диалога
├── prompts/
│   ├── system_prompt.md         инструкция для LLM
│   └── gpt_action_setup.md      настройка Custom GPT Action
├── scripts/
│   ├── prepare_dataset.py       подготовка данных
│   ├── export_openapi.py        выгрузка спецификации
│   └── integration_test.py      проверка обоих транспортов
└── src/analytics_mcp/
    ├── core/                    реестр инструментов, хранилище, модели
    ├── skills/                  бизнес-логика этапов анализа
    ├── tools/                   инструменты, публикуемые наружу
    ├── transports/              адаптеры MCP и REST
    ├── rendering/               оформление графиков, артефакты
    ├── app.py                   сборка ASGI-приложения
    └── selfcheck.py             сквозная самопроверка

独自ツールの追加方法

このときコアは変更されません。ファイル src/analytics_mcp/tools/my_tools.py を作成してください:

from __future__ import annotations

from analytics_mcp.core.datasets import store
from analytics_mcp.core.registry import tool


@tool(tags=("stats",), skill="DataLoadingSkill", title="Топ значений")
def top_values(column: str, dataset_id: str | None = None, limit: int = 10) -> dict:
    """Возвращает самые частые значения колонки.

    Args:
        column: Имя колонки.
        dataset_id: Датасет. По умолчанию — последний использованный.
        limit: Сколько значений вернуть.
    """
    record = store.get(dataset_id)
    record.require_column(column)
    counts = record.df[column].value_counts().head(limit)
    return {str(k): int(v) for k, v in counts.items()}

サーバーを再起動します。ツールは両方のプロトコルに即座に現れます。MCPの tools/list とRESTの /openapi.json の両方です。tools パッケージはモジュールを自動的にインポートし、JSONスキーマはシグネチャから、説明はドクストリングから生成されます。


既知の制限事項

意図的に挙げています。これらはプロトタイプの境界であり、未完成箇所ではありません。

  • データセットのインメモリ保存。 サーバーを再起動すると、読み込まれた データは失われます。プロトタイプでは許容可能。本番では — Redisまたはディスク。

  • 認証なし。 デモ環境は一時的なトンネルの背後にあります。 本番では — ヘッダー内のAPIキーと、FastAPI側での検証。

  • 行のフィルタリングなし。 ツールはデータセット全体を操作します: 「2024年のWest地域だけ」というスライスは構築できません。これは デモで顕著です — モデルは計算できないことを正直に伝え、 出力をこじつけることはしません。

  • スキルは5つ、それ以上はない。 意図的な選択です。機能する5つが、 形だけの10個より優れています。

  • ユニットテストなし — エンドツーエンドの自己チェックselfcheck.pyと、 両方のトランスポートの統合テストのみ。

Related MCP Connectors

Related MCP Servers