mcp-data-summary
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-data-summary Generate a visual summary report for the sales dataset."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-data-summary
A learning project for building an MCP server with the official Python SDK.
The server lets an LLM produce a visual summary report from CSV datasets without ever loading raw data into the model's context. It simulates a REST API (fake GET/POST), exposes data schemas as MCP Resources, provides chart and document generation as MCP Tools, and guides the whole workflow with an MCP Prompt.
What it demonstrates
MCP concept | File | What it does |
Resources |
| Expose dataset schemas via fake GET endpoints |
Tools |
| Generate bar, line, histogram, pie charts, dataset subset |
Tools |
| Descriptive stats + correlation matrix + scatter plot |
Tools |
| Build HTML report + export PDF via fake POST |
Prompts |
| 7-step guided workflow for the LLM |
Fake API |
| Simulated REST client backed by local CSV and JSON files |
Schemas |
| Pydantic models for all API responses |
Related MCP server: mcp-server
How it works
The LLM never sees raw tabular data. Instead it follows this pipeline:
GET /datasets → discover available datasets
GET /datasets/{name} → inspect a plot-friendly schema (columns, dtypes, sample values)
tool: get_summary_statistics → understand distributions and correlations
tool: generate_*_chart → produce PNG charts saved to output/ and feedbacks to understand the charts
tool: build_html_report → render a Jinja2 HTML report from the chart paths
tool: export_pdf_report → convert HTML to PDF and POST it back to the fake APIProject structure
mcp-data-summary/
├── data/ # Sample CSV files and JSON dataset descriptions (auto-discovered)
│ ├── descriptions.json
│ ├── sales.csv
│ └── users.csv
├── output/ # Generated charts, HTML and PDF reports
├── scripts/
│ └── run_pipeline.py # End-to-end pipeline runner (no LLM needed)
├── tests/
│ ├── conftest.py # Shared pytest fixtures
│ ├── test_fake_client.py # Unit tests for the API layer
│ ├── test_chart_tools.py # Tests for all chart tools
│ └── test_stats_and_docs.py # Tests for stats tool + HTML builder
├── src/
│ └── mcp_data_summary/
│ ├── server.py # Entry point — wires everything together
│ ├── api/
│ │ ├── fake_client.py # Simulates GET /datasets and POST /reports
| | ├── json_encoder.py # Custom JSON encoder
│ │ └── schemas.py # Pydantic models for API responses
│ ├── resources/
│ │ └── datasets.py # MCP Resources: dataset list + schema
│ ├── tools/
│ │ ├── chart_tools.py # Bar, line, histogram, pie chart tools
│ │ ├── stats_tools.py # Summary statistics + scatter plot
│ │ └── document_tools.py # HTML report builder + PDF exporter
│ └── prompts/
│ └── summary_prompt.py # Guided 7-step workflow prompt
└── pyproject.tomlQuick start
1. Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh2. Install dependencies
uv sync3. Verify everything works (no LLM required)
Run the pipeline script — it simulates the full LLM workflow end-to-end:
uv run python scripts/run_pipeline.py
# Restrict to a single dataset
uv run python scripts/run_pipeline.py --datasets salesCharts and a report will appear in output/.
4. Run the test suite
uv run pytest5. Open the MCP Inspector (browser-based debug UI)
uv run mcp dev src/mcp_data_summary/server.pyThis lets you browse Resources, call Tools manually, and inspect request/response payloads
6. Example - Connect to Claude Desktop
Add this block to your claude_desktop_config.json
(~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows):
{
"mcpServers": {
"data-summary": {
"command": "uv",
"args": [
"--directory", "/absolute/path/to/mcp-data-summary",
"run", "mcp-data-summary"
]
}
}
}Restart Claude Desktop, then load the data_summary_workflow prompt. The LLM will discover datasets, inspect schemas, generate charts, and produce a PDF report autonomously.
Available tools
Tool | Input | Output |
| dataset name | JSON with |
| dataset, x/y columns, optional | PNG path and chart data |
| dataset, x/y columns, optional | PNG path and chart data |
| dataset, column, bins | PNG path and chart data |
| dataset, category + value columns | PNG path and chart data |
| dataset, x/y columns, optional | PNG path and chart data |
| dataset, filters | Subset name, path and schema |
| title, chart paths, captions, summary | HTML path |
| HTML path, report name | JSON with pdf path + report_id |
Available resources
URI | Returns |
| JSON array of available dataset names |
| Plot-friendly schema: columns, dtypes, n_unique, sample values |
Adding your own CSV
Drop any .csv file into data/. The server auto-discovers it on startup. Add a description in data/descriptions.json:
{
"your_file": "Description the LLM will see when reading the schema.",
}Date columns are auto-detected if their name contains "date".
System dependencies for PDF export
WeasyPrint (used by export_pdf_report) requires Cairo and Pango to be installed at the OS level. The HTML report and all charts work without them.
# Ubuntu / Debian
sudo apt install libpango-1.0-0 libcairo2 libpangocairo-1.0-0
# macOS
brew install pango cairo
# Windows — follow the WeasyPrint install guide:
# https://doc.courtbouillon.org/weasyprint/stable/first_steps.htmlNext steps
Support multi-dataset joins before charting
Introduce a simple auth token to the fake API layer
Stream chart generation progress back to the client using MCP notifications
Available Tools
10 toolsbuild_html_reportA
Render an HTML summary report from a set of pre-generated charts.
Call this after all chart tools have been run and you have collected
their output paths.
Args:
report_title: Title shown on the cover page.
datasets: List of dataset names included in the report.
chart_paths: List of relative paths to chart PNG files.
chart_titles: List of titles — one per chart, same order as chart_paths.
chart_captions: List of caption strings, same order as chart_paths.
executive_summary: Optional paragraph summarising the key findings.
output_filename: HTML filename to write (auto-generated if empty).
Returns:
Relative path to the saved HTML file.
Inputs: datasets (required), chart_paths (required), chart_titles (required), report_title (required), +3 more. Returns: result
build_subset_datasetA
Filter a dataset by categorical, numeric, and datetime criteria, then save the result.
All filter types are applied independently and intersected to produce the final subset.
Args:
source_dataset_name: Name of the registered source dataset.
categorical_filters: List of (column, value) tuples for exact value matching.
E.g. [("region", "South"), ("region", "North"), ("category", "Hardware")]
numeric_filters: List of (column, value, operator) tuples for numeric comparison.
E.g. [("age", 30, ">="), ("salary", 50000, ">")]
datetime_column: Column name to filter by date range. Leave empty to skip.
datetime_from: Start of date range (inclusive). Leave empty for no lower bound.
datetime_to: End of date range (inclusive). Leave empty for no upper bound.
output_dataset_name: Name for the output subset. Auto-generated if empty.
output_dataset_desc: Description of the subset. Auto-generated if empty.
Returns:
A JSON str with {"dataset_name":"...","dataset_path":"...","dataset_schema":"..."}
Inputs: source_dataset_name (required), datetime_to, datetime_from, datetime_column, +4 more. Returns: result
discover_datasetsA
List the available datasets and get their schemas :
column names, dtypes, sample values,
and a categorised column list (numeric / categorical / datetime).
Inputs: no named parameters.
export_pdf_reportA
Convert an HTML report to PDF and POST it to the (fake) API.
Args:
html_path: Path to the HTML file (output of build_html_report).
report_name: Logical name for the report used in the API call.
Returns:
A JSON str with {"pdf_path":"...","report_id":"...","message":"..."}
Inputs: html_path (required), report_name. Returns: result
generate_bar_chartA
Generate a bar chart from a dataset column.
Args:
dataset: Name of the dataset (e.g. "sales", "users").
x_column: Column to use for the X axis (categorical or date).
y_column: Numeric column to aggregate on the Y axis (sum by default).
title: Chart title shown at the top.
group_by: Optional column to group bars by colour (e.g. "category").
filename: Output filename (auto-generated if empty).
Returns:
A JSON str with {"chart_path":"...","chart_data":"..."}.
Inputs: title (required), dataset (required), x_column (required), y_column (required), +2 more. Returns: result
generate_histogramA
Generate a histogram showing the distribution of a numeric column.
Args:
dataset: Name of the dataset.
column: Numeric column to plot.
title: Chart title.
bins: Number of bins (default 20).
filename: Output filename (auto-generated if empty).
Returns:
A JSON str with {"chart_path":"...","chart_data":"..."}.
Inputs: title (required), column (required), dataset (required), bins, +1 more. Returns: result
generate_line_chartA
Generate a line chart — great for time series or trends.
Args:
dataset: Name of the dataset.
x_column: Column for the X axis, ideally a date or ordered category.
y_column: Numeric column for the Y axis (summed per X value).
title: Chart title.
group_by: Optional column to draw one line per group.
filename: Output filename (auto-generated if empty).
Returns:
A JSON str with {"chart_path":"...","chart_data":"..."}.
Inputs: title (required), dataset (required), x_column (required), y_column (required), +2 more. Returns: result
generate_pie_chartA
Generate a pie chart showing the composition of a categorical column.
Args:
dataset: Name of the dataset.
category_column: Categorical column whose values form the slices.
value_column: Numeric column to sum per category.
title: Chart title.
filename: Output filename (auto-generated if empty).
Returns:
A JSON str with {"chart_path":"...","chart_data":"..."}.
Inputs: title (required), dataset (required), value_column (required), category_column (required), +1 more. Returns: result
generate_scatter_plotA
Generate a scatter plot comparing two numeric columns.
Best used when get_summary_statistics reveals a notable correlation
between two columns worth visualising.
Args:
dataset: Name of the dataset.
x_column: Numeric column for the X axis.
y_column: Numeric column for the Y axis.
title: Chart title.
color_by: Optional categorical column to colour points by group.
filename: Output filename (auto-generated if empty).
Returns:
A JSON str with {"chart_path":"...","chart_data":"..."}.
Inputs: title (required), dataset (required), x_column (required), y_column (required), +2 more. Returns: result
get_summary_statisticsA
Return descriptive statistics and a correlation matrix for a dataset.
Call this before generating charts to understand distributions,
spot outliers, and find which numeric columns correlate strongly
(good candidates for scatter plots).
Args:
dataset: Name of the dataset.
Returns:
JSON string with two keys:
- "describe": per-column stats (count, mean, std, min/max, quartiles)
- "correlation": Pearson correlation matrix for numeric columns
Inputs: dataset (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 10 tools
Each generate_* chart tool targets a distinct chart type, and build/discover/export tools are clearly separate. The only mild overlap is between generate_pie_chart and generate_bar_chart, both of which can visualize categorical composition, though their descriptions clarify the intended use.
All tool names follow a consistent verb_noun pattern using snake_case (e.g., generate_pie_chart, discover_datasets, build_html_report). The verbs vary by action but are predictable and semantically appropriate, with no mixing of camelCase or inconsistent styles.
Ten tools is a well-scoped set for a data summary server. Each tool covers a distinct step in the exploration-to-report workflow, and none feel redundant or unnecessary.
The tool set provides a complete pipeline: discover datasets, inspect statistics, filter subsets, generate multiple chart types, assemble an HTML report, and export to PDF. There are no obvious dead ends or major missing operations for the stated purpose.
Maintenance
Related MCP Connectors
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
MCP-Native LLM Orchestration Agent
LLM Orchestration Agent (Mcp)
LLM Orchestration MCP Agent
Related MCP Servers
- FlicenseBqualityDmaintenanceAn MCP server that provides data visualization and machine learning tools, featuring automated intent-based pipeline routing for data cleaning and model training. It enables LLMs to process CSV or JSON data to generate visual charts, perform regressions, or execute clustering analysis.16-
- FlicenseNot gradedqualityDmaintenanceEnables AI models to interact with local CSV and Parquet data through MCP tools, providing summarization and analysis capabilities.-
- FlicenseAqualityDmaintenanceAn MCP server for dataset exploration and analysis, enabling LLM clients to perform summary, correlation, distribution, missing value analysis, data cleaning, and statistical tests directly on CSV files.3-
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to safely execute pandas code for data analysis and generate interactive visualizations through MCP protocol.MIT