Skip to main content
Glama
Kirill-FD

llm-analytics-mcp

by Kirill-FD

LLM-Based Analytics System with MCP Integration

An MCP server that gives the language model a set of tools for analyzing tabular data: loading, cleaning, plotting, and report assembly. No custom chat interface is developed — the web interface of a ready-made platform is used (Claude as the primary client, ChatGPT as an alternative).

The same tool registry is published over two protocols at once:

Protocol

Endpoint

Client

MCP (Streamable HTTP)

/mcp

Claude — web, desktop, any MCP client

REST + OpenAPI

/tools/*, /openapi.json

ChatGPT Custom GPT Action


What the system can do

12 tools, 5 skills. The full list — by calling describe_system or in ARCHITECTURE.md.

Tool

Skill

Purpose

list_datasets

Catalog of available data

load_data

DataLoadingSkill

Load CSV/TSV/Excel/JSON/Parquet from the catalog, a path, or a URL

describe_data

DataLoadingSkill

Structure, types, missing values, duplicates

clean_data

DataCleaningSkill

Duplicates, missing values, normalization, outliers

suggest_analysis

InsightGenerationSkill

Auto-selection of an analysis plan based on data structure

plot_trend

VisualizationSkill

Metric dynamics over time

plot_distribution

VisualizationSkill

Histogram or bar chart (the type is chosen automatically)

correlation_analysis

VisualizationSkill

Correlation heatmap

plot_breakdown

VisualizationSkill

Metric breakdown by categories

collect_evidence

InsightGenerationSkill

Verifiable figures for the report text

build_report

ReportingSkill

Report in Markdown, HTML, and PDF

describe_system

Introspection: composition of skills and tools

Additional capabilities:

  1. Auto-selected analysissuggest_analysis determines which column is the time axis, which are metrics, which are breakdowns, and returns a ready-made call plan with a justification for each step.

  2. Multi-format and multi-source — CSV, TSV, Excel, JSON, Parquet; a catalog, a local path, or an HTTP(S) link. The latter is essential for the web scenario: a file uploaded to a browser chat is unavailable to the server.

  3. One-command report assemblybuild_report builds the missing charts itself and produces the document in three formats.


Related MCP server: Claude Data Buddy

Installation

Requires Python 3.10 or newer.

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

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

pip install -r requirements.txt

Step 1. Test data

The data in the repository is synthetically generated according to the Superstore schema. The spec explicitly allows this: "you can generate the data yourself or use a well-known dataset."

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

The ready-made files are already in data/ — the command is needed only if you want to regenerate them or change the volume.

Why synthetic data instead of Kaggle

The generator provides control over exactly what the system demonstrates:

  • Verifiable patterns are built in — an upward trend, annual seasonality with a peak at the end of the year, and a "discount above 30% → negative profit" relationship. This makes the analysis conclusions meaningful rather than random.

  • Defects are introduced intentionally. The real Superstore is almost perfectly clean: without missing values and duplicates, DataCleaningSkill would report "0 rows removed," and there would be nothing to demonstrate cleaning with.

  • Reproducibility. A fixed seed=42 — the reviewer gets exactly the same data and the same figures in the report as in the example.

  • The repository is self-contained. No Kaggle account is needed to run the project.

Loading the real Superstore is also supported — the column structure matches:

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

What the script creates

File

Purpose

data/superstore_clean.csv

Data normalized to the columns from the spec

data/superstore_raw.csv

The same table with injected defects

Columns: Date, Product, Region, Sales, Quantity, Profit (from the spec) plus the breakdowns Category, Sub-Category, Segment, Discount, Ship Mode. Period — 2021–2024, 48 months.

The composition of defects is printed at startup and is deterministic:

Defect

Volume

Missing values in Sales / Profit / Quantity

~3.5% / 4.5% / 2%

Fully duplicate rows

~0.8%

Inconsistent Region spelling (west, East, CENTRAL)

~6% of rows

Extreme outliers in Sales

12 rows

Alternative date format (15/03/2022)

~10% of rows


Step 2. Verification without a server

An end-to-end run of the entire chain — from loading to a PDF report:

PYTHONPATH=src python -m analytics_mcp.selfcheck

The script repeats what the LLM does in a dialogue, but deterministically. It is useful as a smoke test before a demo: if it passes, the problem is almost certainly in the integration, not in the analytics.


Step 3. Starting the server

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

Verification:

curl http://127.0.0.1:8000/health

Useful addresses:

Address

What it is

http://127.0.0.1:8000/health

Status and the number of registered components

http://127.0.0.1:8000/docs

Swagger UI: all tools can be called manually

http://127.0.0.1:8000/openapi.json

Specification for the Custom GPT Action

http://127.0.0.1:8000/mcp

MCP endpoint

If the port is busy. A previously started process may continue responding with old code — the symptom is deceptive: /health responds, but changes are not applied. Before restarting: pkill -f uvicorn.


Step 4. Public address via ngrok

Claude accesses the server from outside, so an HTTPS address is needed.

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

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

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

Then set the address in the environment and restart the server:

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

The most common "can't connect" cause. The MCP SDK by default enables DNS rebinding protection and accepts only a Host header of the form localhost. Behind a tunnel, Host contains the ngrok domain, and the request is rejected at the connector connection stage, without a clear error in the interface. The MCP_ALLOWED_HOSTS variable solves exactly this problem.


Step 5. Connecting to Claude (primary scenario)

  1. Open Settings → Connectors → Add custom connector.

  2. Specify the address: https://your-domain.ngrok-free.app/mcp (note the /mcp suffix).

  3. Save and make sure the connector transitions to the connected state.

  4. In a new dialogue, enable the analytics_mcp connector via the tools menu.

  5. Copy the contents of prompts/system_prompt.md into the project description (Project instructions) — this sets the call order.

Verification request: "What datasets are available?" — the model should call list_datasets and show the contents of the catalog.


Step 6. Connecting to ChatGPT (alternative scenario)

  1. Download the specification from the public address:

    PUBLIC_BASE_URL=https://ваш-домен.ngrok-free.app \
      PYTHONPATH=src python scripts/export_openapi.py
  2. Create a Custom GPT: Explore GPTs → Create → Configure.

  3. Create new action → Schema — paste the contents of openapi.json.

  4. Authentication: None.

  5. In the Instructions field, paste prompts/system_prompt.md.

Details and specifics of chart rendering — in prompts/gpt_action_setup.md.


Demonstration scenario

The order of requests is chosen so that the screenshots show a chain of calls, not a single request. The key frame is step 4: it shows what the model plans, not hardcoded logic.

#

User request

Expected calls

1

What datasets are available?

list_datasets

2

Load superstore_raw and describe the structure

load_data, describe_data

3

Clean the data

clean_data

4

What is worth analyzing here?

suggest_analysis

5

Build these charts

plot_trend, plot_breakdown, plot_distribution, correlation_analysis

6

Make a report with conclusions and recommendations

collect_evidence, build_report

Example result — docs/report_example.md, charts — in docs/plots/.


Work screenshots

Demo materials are in docs/screenshots/:

File

What is shown

01-list-datasets.png

Claude calls list_datasets and shows the server catalog

02-clean.png

clean_data report: Region normalization, 30 duplicates, 817 outliers

02.2-clean.png

Comparison of dataset versions "with missing values filled" and "without"

03-suggest-analysis.png

The model checks hypotheses from the report with new tool calls

03.2-suggest-analysis.png

Prioritized list of directions for further analysis

04-plots.png

Chart building; the model explicitly notes what the tools cannot do

The screenshots show the key property of the system: the chain of calls is controlled by the LLM. The model itself decides which tools to call, finds the limitations of the set (for example, the absence of row filtering), and reports them instead of forcing the output to fit.

Integration verification

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

Repository structure

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             сквозная самопроверка

How to add your own tool

The core does not change. Create a file 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()}

Restart the server. The tool will appear immediately in both protocols: in tools/list for MCP and in /openapi.json for REST. The tools package imports its modules automatically, the JSON schema is derived from the signature, and the description — from the docstring.


Known limitations

They are named deliberately — these are the boundaries of the prototype, not unfinished work:

  • In-memory dataset storage. When the server restarts, loaded data is lost. Acceptable for a prototype; in production — Redis or disk.

  • No authorization. Demo environment is behind a temporary tunnel. For production — an API key in the header and validation on the FastAPI side.

  • No row filtering. Tools work with the dataset as a whole: you cannot build a slice like “only the West region for 2024”. This is noticeable in the demo — the model honestly reports what it cannot compute, instead of fudging the output.

  • Five skills, not more. A deliberate choice: better five working skills than ten formal ones.

  • No unit tests — only the end-to-end self-check selfcheck.py and an integration test of both transports.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.

  • The grounded data layer for any LLM: governed SQL, metrics, lineage and catalog over your data.

  • The statistical analyst in your AI chat — validated, citable, re-runnable analysis of your data.

View all MCP Connectors

Latest Blog Posts

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/Kirill-FD/llm-analytics-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server