mcp-analytics
Web analytics, reimagined for the AI era.
What it can do
- Get Started Guide: Markdown walkthrough of the mcp-analytics workflow: adding sites, installing the tracker, querying analytics, custom events.
- List Sites: List all sites on the authenticated account. Each entry contains: site_id, domain, privacy_mode, hits_this_month (current calendar month), plan_limit, created_at.
- Add Site: Register a new site. privacy_mode cannot be changed later.
What data it sees
Do you need an account
No: the server works without sign-in
Web analytics, reimagined for the AI era. Ask the question, get the answer, ship the fix — all in chat. Cursor installs the tracking snippet itself. Site optimization on autopilot from day one. Free for 100k hits/month.
How to connect
How to connect mcp-analytics to Claude
The server address to paste into Claude settings:
https://mcp-analytics--mcp-analytics.run.tools
- Open Claude (claude.ai or the desktop app).
- Go to Settings → Connectors.
- Click Add custom connector.
- Paste the server address copied below into Remote MCP server URL and click Add.
- In a chat, click + → Connectors and switch the new connector on.
Custom connectors are available on Free, Pro, Max, Team and Enterprise plans (Free is limited to one). On Team and Enterprise an organization Owner adds the connector first under Organization settings → Connectors.
Authorization
After you click Add, a sign-in window for the service opens. Sign in with your own account and approve access. Claude never sees your password.
How to connect mcp-analytics to ChatGPT
The server address to paste into ChatGPT settings:
https://mcp-analytics--mcp-analytics.run.tools
- Open ChatGPT in a browser (chatgpt.com). A Plus, Pro, Business, Enterprise or Edu plan is required.
- Turn on developer mode once: Settings → Apps → Advanced settings → Developer mode.
- Open Settings → Connectors and click Create.
- Fill in the form: Name (anything), Description (one line about what the service does), MCP server URL (copy it below).
- Under Authentication choose OAuth if the service requires sign-in, otherwise None. Click Create.
- In a new chat open + → Apps/Connectors and enable the connector.
OpenAI has renamed this section before (Connectors → Apps/Plugins). If the label differs, search settings for "developer mode". On Business/Enterprise workspaces an admin must allow custom connectors first.
Authorization
On first use ChatGPT opens the service's sign-in window. Sign in and approve access.
How to connect mcp-analytics to Cursor
The server address to paste into Cursor settings:
https://mcp-analytics--mcp-analytics.run.tools
Fastest: click Open in Cursor below and confirm the prompt.
Manually:
- In Cursor open Settings → Cursor Settings → MCP and click Add new global MCP server.
- Paste the JSON copied below into
~/.cursor/mcp.json(per project:.cursor/mcp.jsonin the repo root). - Save the file. The server appears in the MCP list; authorize it there if asked.
Authorization
If the service needs sign-in, an authorize button appears next to the server in the MCP list.
Server tool list (22)
Raw names from tools/list. Only developers need these.
| get_started_guide | Markdown walkthrough of the mcp-analytics workflow: adding sites, installing the tracker, querying analytics, custom events. |
| list_sites | List all sites on the authenticated account. Each entry contains: site_id, domain, privacy_mode, hits_this_month (current calendar month), plan_limit, created_at. |
| add_site | Register a new site. privacy_mode cannot be changed later. |
| get_tracking_snippet | Return the HTML <script> snippet for a given site_id. |
| remove_site | Soft-delete a site. Historical events remain until TTL expires. |
| get_overview | TL;DR for the period: headline metrics (pageviews, visitors, sessions, bounce rate, avg session duration) plus pageviews_change_pct vs the previous equivalent window, top page, top traffic source, bot share, and top 3 custom events. Designed so a single call answers 'how did <period> go?' without chaining other tools. Volume metrics (pageviews / visitors / sessions / bot_share) include AI-mediated human browsing (ai_user_action — Claude/ChatGPT fetching on a user's behalf); attribution metrics (top_source) count direct browser visits only because AI-mediated traffic loses original utm/referrer tags. See traffic_class_breakdown for the per-class split. |
| get_timeseries | Time-bucketed metric over a period. pageviews/visitors/sessions include AI-mediated human browsing (ai_user_action) — see traffic_class_breakdown to see the AI-vs-direct split. |
| top_pages | Most-viewed URL paths. Counts both direct browser visits and AI-mediated human browsing (ai_user_action) — see traffic_class_breakdown if you need to separate them. |
| top_referrers | Top referring hosts. Attribution metric — counts direct browser visits only ('user' class). AI-mediated traffic (Claude/ChatGPT fetching on a user's behalf) is excluded because the AI sets its own host as referrer or strips it; including it would inflate 'direct' or 'claude.ai' without telling you where the human attention actually came from. |
| top_sources | Top UTM source/medium/campaign combinations. Attribution metric — counts direct browser visits only ('user' class). AI-mediated traffic loses original UTM tags so it would only add noise. |
| breakdown | Breakdown of visits by browser, os, device_type, or country (country empty in MVP). Volume metric — counts include AI-mediated human browsing (ai_user_action). |
| list_events | All event names with counts (includes 'pageview' and custom events). Volume metric — counts include AI-mediated human browsing (ai_user_action). |
| event_details | Details for one event. Optionally break down by a custom property. Volume metric — counts include AI-mediated human browsing (ai_user_action). |
| compare_periods | Compare a metric between two periods. Volume metric — counts include AI-mediated human browsing (ai_user_action). |
| top_user_agents | Top User-Agent strings with their traffic_class. Default analytics queries hide everything except real visitors; this tool surfaces the rest so you can see who is actually fetching the site. Pass traffic_class to filter to one bucket. The 8 classes (Phase 2 Cloudflare-compatible taxonomy): - user: real human visitor with their own browser - ai_user_action: live AI browse — a human is chatting with ChatGPT/Claude/Perplexity/Copilot and the assistant fetched the page on their behalf (counts as human attention, just AI-mediated) - ai_search: AI search-engine indexers (PerplexityBot, OAI-SearchBot, ...) — your page is a candidate answer in their index - ai_training: AI training crawlers (GPTBot, ClaudeBot, CCBot, Bytespider, ...) — your content lands in training data, no human is actively reading right now - search_index: classic search engines (Googlebot, Bingbot, Yandex, DuckDuckBot, ...) - social_unfurl: link-preview / social-card bots (Slackbot, facebookexternalhit, Twitterbot, LinkedInBot, ...) - scanner: security/uptime/perf monitoring (Censys, Pingdom, Lighthouse, headless Chrome from a cloud range, ...) - bot_other: recognized as a bot but not in any specific bucket, OR a UA we caught spoofing (e.g. a fake "GPTBot" coming from a random EC2 IP) The `humans` filter alias expands to (user, ai_user_action) — useful for "real human attention including AI-mediated". |
| traffic_class_breakdown | Hit counts and percentages by traffic_class for the period. Sorted by hits descending. Classes with zero hits are omitted (a missing class means no hits in that period, treat as zero). The 8 classes (Phase 2 Cloudflare-compatible taxonomy): - user: real human visitor with their own browser - ai_user_action: live AI browse — a human is chatting with ChatGPT/Claude/Perplexity/Copilot and the assistant fetched the page on their behalf. Counts as human attention, just AI-mediated. - ai_search: AI search-engine indexers (PerplexityBot, OAI-SearchBot) — your page is a candidate answer in their index - ai_training: AI training crawlers (GPTBot, ClaudeBot, CCBot, Bytespider) — your content lands in training data, no human is actively reading right now - search_index: classic search engines (Googlebot, Bingbot, Yandex, DuckDuckBot) - social_unfurl: link-preview / social-card bots (Slackbot, facebookexternalhit, Twitterbot, LinkedInBot) - scanner: security/uptime/perf monitoring (Censys, Pingdom, Lighthouse, headless Chrome from a cloud range) - bot_other: recognized as a bot but not in any specific bucket, OR a UA we caught spoofing (e.g. a fake "GPTBot" coming from a random EC2 IP) For "how much human traffic did I get?" sum hits where traffic_class is 'user' or 'ai_user_action'. The same union is also exposed as the 'humans' alias in top_user_agents' traffic_class filter. Note on consistency: get_overview's `bot_share` field uses the same human/non-human split (excludes user + ai_user_action), so the two tools agree on what counts as bot traffic. Note on history: rows from before Phase 2 deployed were reclassified by User-Agent only (we don't store IPs for privacy), so older data may under-report scanner-via-cloud-IP and over-attribute spoofed UAs. |
| top_timezones | Top IANA timezones (Europe/Berlin, America/New_York, ...) of visitors. Quasi-geo signal without IP-based lookups — captured client-side via Intl.DateTimeFormat. |
| top_languages | Top browser languages (de-DE, en-US, ...) of visitors. From navigator.language. |
| color_scheme_breakdown | Share of visitors with prefers-color-scheme: dark vs light. Useful for product decisions ('should we default to dark mode?'). |
| viewport_breakdown | Pageviews bucketed by viewport width: mobile_xs (<480), mobile (<768), tablet (<1024), desktop (<1440), desktop_xl (≥1440). Real usable viewport, not screen resolution. |
| engagement_overview | Real reading time + scroll depth from the engagement beacon (fired on pagehide). Returns engaged_pages count, avg/median/p90 engagement seconds, and avg/median scroll-depth percentage. Better signal than session duration which counts inactive tabs. |
| get_account | Account info — email, current plan, total active sites, total_hits_this_month (across all sites), plan_limit, and api_token_first_chars (first 10 chars of the legacy API token, for identification only — not enough to authenticate). |