MCP server for Plausible Analytics — query traffic, conversions, and compare time periods from any AI tool that supports Model Context Protocol.
Built for teams that want to ask questions like:
- "Did our deploy on Tuesday affect traffic to /pricing?"
- "What's the signup conversion rate on /blog this month?"
- "How does this week's bounce rate compare to last week?"
| Tool | Description |
|---|---|
list_sites |
List sites accessible to the current API key |
get_aggregate |
Aggregate traffic and conversion metrics for a date range |
get_realtime_visitors |
Current visitors active in the last 5 minutes |
get_goals |
List goals configured for a site |
get_pages |
Top pages without manually choosing event:page |
get_sources |
Top traffic sources without manually choosing visit:source |
get_countries |
Top countries without manually choosing visit:country |
get_devices |
Device, browser, and OS breakdowns in one call |
get_entry_exit_pages |
Entry and exit page rankings in one call |
get_utm_campaigns |
UTM medium/source/campaign/content/term breakdowns |
get_page_timeseries |
Page-level trend query with required page |
find_traffic_anomalies |
Biggest dimension-level changes between two periods |
get_mcp_config |
Non-sensitive MCP runtime configuration |
get_site_health |
Stats and realtime health checks for one site |
detect_plausible_capabilities |
Detect Stats, Realtime, Sites, and Goals API availability |
get_timeseries |
Traffic and conversion metrics over time (daily/weekly/monthly) |
get_breakdown |
Break down by page, source, country, device, browser, OS, UTM params |
get_conversions |
Goal conversion rates, optionally per-page |
compare_periods |
Side-by-side comparison of two date ranges with absolute and % deltas |
All tools are read-only and annotated with readOnlyHint: true.
Deploy your own remote Worker and point your MCP client at its /mcp endpoint. Each user provides their own Plausible API key as a Bearer token.
Add to Claude Code:
claude mcp add --transport http plausible https://YOUR_WORKER_DOMAIN/mcp --header "Authorization: Bearer YOUR_PLAUSIBLE_API_KEY"Or add manually to your MCP client config (Claude Desktop, Cursor, etc.):
{
"mcpServers": {
"plausible": {
"url": "https://YOUR_WORKER_DOMAIN/mcp",
"headers": {
"Authorization": "Bearer YOUR_PLAUSIBLE_API_KEY"
}
}
}
}If you prefer to run it locally:
git clone https://github.com/Patrick5D/plausible-mcp.git
cd plausible-mcp
bun installAdd to Claude Code:
claude mcp add plausible -e PLAUSIBLE_API_KEY=your-key -- bun run src/index.tsOr Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"plausible": {
"command": "bun",
"args": ["run", "/path/to/plausible-mcp/src/index.ts"],
"env": {
"PLAUSIBLE_API_KEY": "your-key"
}
}
}
}Deploy your own instance:
git clone https://github.com/Patrick5D/plausible-mcp.git
cd plausible-mcp
bun install
bun run deployThe worker is multi-tenant: each user passes their own Plausible API key via the Authorization: Bearer header. It applies per-IP rate limiting before authentication. Set MCP_RATE_LIMIT_PER_MINUTE to tune the built-in limiter, or bind a Cloudflare RATE_LIMITER if your account uses Cloudflare's Rate Limiting binding.
| Environment Variable | Required | Default | Description |
|---|---|---|---|
PLAUSIBLE_API_KEY |
Yes (STDIO) | — | Your Plausible API key (get one here) |
PLAUSIBLE_BASE_URL |
No | https://plausible.io |
URL of your Plausible instance (for self-hosted) |
PLAUSIBLE_DEFAULT_SITE_ID |
No | — | Default site domain so you don't have to pass site_id every call |
PLAUSIBLE_SITE_IDS |
No | — | Comma-separated site domains used as a list_sites fallback when the Sites API is unavailable |
MCP_RATE_LIMIT_PER_MINUTE |
No | 60 |
Per-IP Worker request limit used when no Cloudflare RATE_LIMITER binding is present |
For the Cloudflare Worker, PLAUSIBLE_API_KEY is not needed as an env var — each user passes their own key via the Authorization: Bearer header.
This server wraps the Plausible Stats API v2 (POST /api/v2/query) and falls back to v1 stats endpoints when v2 is unavailable. It also uses selected v1 Sites and Realtime endpoints for site discovery, goal discovery, and current visitor counts. If the Sites API is unavailable on self-hosted Community Edition, list_sites can fall back to PLAUSIBLE_SITE_IDS, and get_goals falls back to a Stats API event:goal breakdown.
visitors, visits, pageviews, views_per_visit, bounce_rate, visit_duration, events, scroll_depth, percentage, conversion_rate, group_conversion_rate, average_revenue, total_revenue, time_on_page
event:page, event:goal, event:hostname, visit:entry_page, visit:exit_page, visit:source, visit:referrer, visit:channel, visit:utm_medium, visit:utm_source, visit:utm_campaign, visit:utm_content, visit:utm_term, visit:device, visit:browser, visit:browser_version, visit:os, visit:os_version, visit:country, visit:region, visit:city
bun install
bun run build # TypeScript compilation
bun run test # Run unit + integration tests
bun run test:watch # Watch modePLAUSIBLE_API_KEY=your-key npx @modelcontextprotocol/inspector bun run src/index.tsVerifies Claude picks the right tool for natural language analytics questions:
ANTHROPIC_API_KEY=sk-... bun run evalsrc/
├── index.ts # STDIO entry point (local use)
├── worker.ts # Cloudflare Worker entry point (remote)
├── server.ts # Creates McpServer, registers all tools
├── plausible.ts # PlausibleClient — standalone API client
├── schemas.ts # Shared Zod schemas and filter helpers
└── tools/
├── list-sites.ts
├── get-aggregate.ts
├── get-realtime-visitors.ts
├── get-goals.ts
├── breakdown-presets.ts
├── get-pages.ts
├── get-sources.ts
├── get-countries.ts
├── get-devices.ts
├── get-entry-exit-pages.ts
├── get-utm-campaigns.ts
├── get-page-timeseries.ts
├── find-traffic-anomalies.ts
├── get-mcp-config.ts
├── get-site-health.ts
├── detect-plausible-capabilities.ts
├── get-timeseries.ts
├── get-breakdown.ts
├── get-conversions.ts
└── compare-periods.ts
PlausibleClient has zero MCP dependency and can be used standalone.
MIT — see LICENSE.