dotplot-mcp
MCP server for product analytics using dot plots to visualize individual user activity, with tools for user classification, aha moment detection, retention analysis, and generating shareable HTML reports.
README
Dot Plot MCP
See individual users, not aggregate charts.
English | 한국어

DAU/MAU charts trend "up and to the right" as long as new users arrive — even when nobody sticks. This MCP server implements YC's Dot Plot methodology (David Lieb): until you have hundreds of users, the most informative dashboard is one row per user, one cell per day.
Design principle: code computes the numbers, AI only interprets them. Statistics never come from an LLM, so they are never wrong.
What it does
1. Tracking audit compare events in your code vs events in your data → find broken/missing tracking
2. Dot plot every user's activity as dots — churn, weekend-only, core fans at a glance
3. Classification used-once / weekend-only / almost-daily, automatically
4. Aha moments scan every action for "what turns users into regulars"
5. Report hand-drawn style HTML + plain-language insights → share as a link
6. Benchmark (opt-in) compare your metrics with teams at your industry & stage
30-second demo

Quick start
Requirements: uv, and three columns of data:
who, when, what — user_id, date, event.
Whatever your database tool already exports is fine. CSV, TSV, JSON, and JSONL
are read directly, columns are matched by name (uid, customer_id,
created_at, event_name, … all work), and timestamps are cut down to days:
psql -c "..." --csv > events.csv # Postgres
mysql --json -e "..." > events.json # MySQL
mongoexport --collection=orders ... # MongoDB
bq query --format=json "..." > events.json # BigQuery
That is the whole "which databases are supported" answer: the ones you can already query. The data goes from your database to a file to the report — it never passes through the model.
One command — no clone, no setup:
claude mcp add dotplot -- uvx dotplot-mcp
No data yet? Clone and try the sample:
uv run sample_data.py # generates events.csv (40 fake users)
uv run harness.py # watch the whole pipeline run
Then say one thing:
"Analyze my product"
That's the whole interface. Claude finds your data, picks the action that means "this user got value", and hands back the report above. If your database has no events table — most early products don't — it builds the events out of the tables you already have:
SELECT user_id, created_at::date AS date, 'purchase' AS event FROM orders
UNION ALL
SELECT user_id, added_at::date, 'add_to_wishlist' FROM wishlist_items
Your orders table is an event log. It just isn't named like one. No SDK, no
tracking code, no signup.
Tools
analyze is the whole product. Everything below it is a part that analyze
already uses — reach for one only when you want a single number on its own
("just show me retention").
| Tool | What it does |
|---|---|
analyze |
Data in, finished report out. Start here. |
describe_events |
Understand the data shape |
dot_plot |
Text dot plot (◎ signup day, ● active day, custom marks) |
classify_users |
Automatic behavioral pattern classification |
find_aha_moments |
Scan all events for "regular-converting" actions (before/after behavior change) |
onboarding_funnel |
Signup → first value → return → still active: where users leak |
retention_curve |
Weekly retention — the number investors always ask |
load_from_db |
Pull events straight from Postgres/Supabase (no CSV export step) |
history_compare |
"Since last report" deltas — snapshots auto-saved locally on every report |
find_similar_cases |
Match your diagnosis to real documented cases (Facebook's 7-friends, Slack's 2k messages...) |
audit_tracking |
Compare events in code vs data (find tracking gaps) |
generate_report |
Hand-drawn style HTML report + rule-based insights |
publish_report |
Host the report at a random URL, get a share link (Vercel) |
submit_benchmark |
Submit aggregates to the anonymous benchmark (explicit consent required) |
compare_benchmark |
Compare your metrics with percentiles of similar teams |
Languages
Reports work in any language. English, 한국어, and 日本語 are built in;
for every other language the agent translates the report strings on the fly
(get_report_strings → translate → custom_strings), while the code validates
that number placeholders survive translation — so statistics stay exact.
Want your language built in? It's one dictionary in i18n.py. PRs welcome.
See the same report in English · 한국어 · 日本語.
Anonymous benchmark — what gets sent
Opt-in only. Nothing is ever sent without explicit consent.
If you consent, these five aggregates are sent — and this is everything:
{
"users_count": 40,
"churned_rate": 0.30,
"weekend_rate": 0.175,
"regular_rate": 0.275,
"aha_lift": 0.82
}
Never sent: user IDs, event logs, dates, your service's name, IP-based identifiers.
The backend is INSERT-only (row-level security) — submitted data cannot be read back with the public key, and comparisons go through a function that returns percentile statistics only. Verify yourself: benchmark.py (~60 lines).
Architecture
analysis.py all computation — pure Python, knows nothing about MCP (the brain)
server.py thin shell exposing computations as MCP tools
report.py HTML report rendering + rule-based insight sentences
benchmark.py anonymous benchmark client
i18n.py every user-facing sentence, per language
harness.py run the whole pipeline end-to-end without an agent
sample_data.py sample data with planted patterns (for verifying the tool)
hosting/ Vercel project template for report hosting
Why it's built this way
- LLMs don't compute — same data, same numbers, every time
- Small samples withhold judgment — groups under 5 users are excluded from aha candidates
- Correlation ≠ causation — every insight ships with a "verify with an experiment" warning
- Vanity metrics blocked — pick
open_app,page_view,session_start(and friends) as your value event and the code refuses, with a list of what you can pick instead - Typos can't lie to you — a value event that isn't in your data is rejected, so you never get a plausible-looking "100% churned" report from a misspelling
FAQ
How do I analyze user flows / user behavior for my early-stage product?
If you have under ~1,000 users, skip the heavyweight analytics suites. Export a
3-column CSV (user_id, date, event) or connect your Postgres, then ask Claude
to draw a dot plot — one row per user, one dot per active day. Churn, weekend-only
users, and habit changes become visible in seconds. That's exactly what this MCP does.
How do I find my product's aha moment?
find_aha_moments scans every event and measures, per user, how activity changed
before vs after first doing that action — so frequency noise (scrolling, popups)
doesn't fool the ranking. The report aligns all users on "day zero" so you can
see the habit change with your own eyes.
How is this different from Mixpanel / Amplitude / PostHog? Those are built for thousands of users and aggregate charts. This is built for your first hundred: per-user visibility, runs locally inside your coding agent, no SDK, no signup, stats computed by code (never by the LLM). Graduate to the big tools later — this is the stage before them.
License
MIT
<!-- mcp-name: io.github.brownglasses/dotplot-mcp -->
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。