AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Plausible Mcp

mcp-getsentry-plausible-mcp · by getsentry

MCP server for Plausible Analytics — query traffic, conversions, and compare periods from any AI tool

No reviews yet
0 installs
21 views
0.0% view→install

Install

$ agentstack add mcp-getsentry-plausible-mcp

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-getsentry-plausible-mcp)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
27d ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Plausible Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

plausible-mcp

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?"

Tools

| Tool | Description | |------|-------------| | 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.

Quick Start

Remote (Hosted)

A hosted instance is available at https://plausible-mcp.sentry.dev.

With your own Plausible API key (any user):

claude mcp add --transport http plausible https://plausible-mcp.sentry.dev/mcp --header "Authorization: Bearer YOUR_PLAUSIBLE_API_KEY"

> Keep the URL before --header. --header is variadic, so if it comes last it swallows the URL and the CLI fails with error: missing required argument 'commandOrUrl'.

Or add manually to your MCP client config (Claude Desktop, Cursor, etc.):

{
  "mcpServers": {
    "plausible": {
      "url": "https://plausible-mcp.sentry.dev/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_PLAUSIBLE_API_KEY"
      }
    }
  }
}

Sentry employees (via OAuth 2.1 + Cloudflare Access):

The /internal endpoint is an OAuth 2.1 server — no API key needed. Add it as a remote/custom connector in any OAuth-capable MCP client (Cowork, Claude.ai connectors, Claude Desktop):

https://plausible-mcp.sentry.dev/internal

The client discovers the OAuth endpoints automatically, sends you through Sentry SSO (Cloudflare Access), and only @sentry.io identities are granted access. Queries run against a shared, server-side Plausible API key — you never handle a key.

> The hosted /internal at plausible-mcp.sentry.dev is Sentry-only and can't be used outside the org. To run /internal for a different organization, [self-host](#self-hosting-cloudflare-workers) and set ALLOWED_EMAIL_DOMAIN to your own domain. (The public /mcp bring-your-own-key endpoint has no such restriction.)

Local (STDIO)

If you prefer to run it locally:

git clone https://github.com/getsentry/plausible-mcp.git
cd plausible-mcp
pnpm install
pnpm build

Add to Claude Code:

claude mcp add plausible -e PLAUSIBLE_API_KEY=your-key -- node /path/to/plausible-mcp/dist/index.js

Or Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "plausible": {
      "command": "node",
      "args": ["/path/to/plausible-mcp/dist/index.js"],
      "env": {
        "PLAUSIBLE_API_KEY": "your-key"
      }
    }
  }
}

Self-Hosting (Cloudflare Workers)

Deploy your own instance:

git clone https://github.com/getsentry/plausible-mcp.git
cd plausible-mcp
pnpm install
npx wrangler deploy

The worker exposes two endpoints:

  • /mcp — bring-your-own-key. Each user passes their own Plausible API key via the Authorization: Bearer header. No shared secrets needed on the server. Works with any header-capable MCP client (Claude Code, Cursor, MCP Inspector).
  • /internal — Access-protected MCP endpoint for managed connectors (Cowork, Claude.ai). A Cloudflare Access application with Managed OAuth fronts the whole Worker hostname (see the constraint below): Access runs the OAuth 2.1 handshake with the client and forwards each request to the Worker with a Cf-Access-Jwt-Assertion header. The Worker verifies that header and queries a shared, server-side Plausible API key. Access is gated to the email domain(s) in ALLOWED_EMAIL_DOMAIN (defaults to sentry.io) — not tied to Sentry when you self-host; set it to your own domain.

Because the Managed OAuth application must cover the bare hostname with no path (Cloudflare rejects a path when OAuth is enabled — domain can not have a path if oauth is configured), it also gates /mcp. To keep the bring-your-own-key /mcp endpoint public you add a second, more-specific Access application scoped to the /mcp path with a Bypass policy. Cloudflare matches the most specific hostname+path first, so /mcp requests bypass Access entirely while everything else goes through OAuth. Both apps live on one hostname; no separate subdomain is required.

> Beta / client requirement. Cloudflare Access Managed OAuth is in Beta and requires an MCP client that supports RFC 8707 (resource indicators). Confirm your connector supports it before relying on this path.

Setting up the /internal endpoint (Cloudflare Access Managed OAuth)

The Worker runs no OAuth server — Cloudflare Access is the authorization server. There is no OAUTH_KV, no cookie key, and no OAuth client id/secret. You create two Access applications on the same hostname.

  1. Create the Managed OAuth application over the bare hostname (Zero Trust → Access → Applications): a self-hosted app or MCP server application whose domain is plausible-mcp.sentry.dev with no path.
  • ⚠️ Do not scope it to /internal. Once Managed OAuth is enabled, Cloudflare rejects any path with access.api.error.invalid_request: domain can not have a path if oauth is configured. The app must be the whole host; the Worker enforces the /internal route itself.
  • Add an Access policy (Action Allow) restricting to your email domain (e.g. @acme.com) and identity provider.
  • Enable Managed OAuth (Advanced settings → Managed OAuth) and set Allowed redirect URIs to your connector's actual callback — for Claude/Cowork that is https://claude.ai/api/mcp/auth_callback. Public HTTPS callbacks must be listed or Dynamic Client Registration fails with invalid_client_metadata: redirect_uri is not allowed by the account configuration; loopback (http://localhost:*) callbacks are allowed by default.
  • Copy the application's AUD tag → this becomes CF_ACCESS_AUD.
  1. Carve /mcp back out with a second, path-scoped Bypass application. Because step 1 covers the whole host, /mcp (bring-your-own-key) is now gated too. Create another self-hosted app, domain plausible-mcp.sentry.dev path mcp, with Managed OAuth OFF, and a policy whose Action is Bypass with the selector Everyone.
  • BypassAllow: an Allow policy still forces an interactive login (the client gets an HTML 302 to the login page and fails with Unexpected content type: text/html). Only Bypass lets the request through with no authentication, so the Worker's own Bearer-key check applies.
  1. Set the worker secrets:

``bash npx wrangler secret put CF_ACCESS_TEAM_DOMAIN # https://.cloudflareaccess.com (no trailing slash) npx wrangler secret put CF_ACCESS_AUD # the Managed OAuth application's AUD tag (from step 1) npx wrangler secret put PLAUSIBLE_API_KEY # shared key for /internal queries ``

  1. Set the [vars] in wrangler.toml:
  • ALLOWED_EMAIL_DOMAIN — the email domain(s) allowed to sign in, comma-separated, @ optional (default sentry.io). Enforced in code in addition to the Access policy in step 1, so set it to your own domain — otherwise every login is rejected.
  1. Deploy (npx wrangler deploy), then point an RFC 8707-capable MCP client at https:///internal.

Troubleshooting. All of these are Cloudflare Access configuration, not the Worker — a request only reaches the Worker (and its Sentry spans) once Access forwards it:

| Symptom (in the connector) | Cause | Fix | |---|---|---| | Couldn't register … / add an OAuth Client ID | Connector callback isn't in Allowed redirect URIs | Add the exact callback (step 1); read the rejected redirect_uri from Zero Trust → Logs → Access | | domain can not have a path if oauth is configured | Managed OAuth app scoped to a path | Rescope app 1 to the bare host (step 1) | | /mcp: Unexpected content type: text/html | /mcp app policy is Allow, not Bypass | Set the app-2 policy Action to Bypass (step 2) | | /mcp: OAuth 401 invalid_token | No /mcp bypass app; the whole-host OAuth app is gating it | Create app 2 (step 2) |

Configuration

| 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 | | CF_ACCESS_TEAM_DOMAIN | Yes (Worker /internal) | — | https://.cloudflareaccess.com — verifies the Cf-Access-Jwt-Assertion JWKS + issuer. No trailing slash. | | CF_ACCESS_AUD | Yes (Worker /internal) | — | The Access application's Application Audience (AUD) tag — checked against the assertion's aud. | | ALLOWED_EMAIL_DOMAIN | No (Worker /internal) | sentry.io | Comma-separated email domain(s) allowed to sign in to /internal. Set to your own domain when self-hosting. |

On the Worker, the /mcp endpoint needs no server-side key — each user passes their own via Authorization: Bearer. The /internal endpoint is fronted by Cloudflare Access Managed OAuth and uses a shared server-side PLAUSIBLE_API_KEY secret (see [self-hosting](#setting-up-the-internal-endpoint-cloudflare-access-managed-oauth)).

Plausible API

This server wraps the Plausible Stats API v2 (POST /api/v2/query). It works with both Plausible Cloud and self-hosted instances.

Supported Metrics

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

Supported Dimensions

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, visit:country_name, visit:region_name, visit:city_name

The *_name geography dimensions return human-readable names (e.g. "Canada"); the plain visit:country/region/city return ISO/Geoname codes.

Development

pnpm install
pnpm build         # TypeScript compilation
pnpm test          # Run unit + integration tests
pnpm test:watch    # Watch mode

Testing with MCP Inspector

pnpm build
PLAUSIBLE_API_KEY=your-key npx @modelcontextprotocol/inspector node dist/index.js

LLM Evals

Verifies Claude picks the right tool for natural language analytics questions:

ANTHROPIC_API_KEY=sk-... pnpm eval

Architecture

src/
├── 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/
    ├── get-timeseries.ts
    ├── get-breakdown.ts
    ├── get-conversions.ts
    └── compare-periods.ts

PlausibleClient has zero MCP dependency and can be used standalone.

Observability & data collection

The Worker reports to Sentry with an endpoint-dependent privacy posture:

  • /mcp (bring-your-own-key) — fully anonymous. Tool inputs and outputs are not recorded (that data belongs to the caller and their own key), no identity is attached, and the ingest-inferred client IP is stripped (src/redaction.ts). Only operational telemetry remains: tool names, span timings, and failures.
  • /internal (SSO-gated) — attributed. Requests carry the authenticated @sentry.io email (Sentry.setUser), and tool inputs/outputs are recorded (recordToolIO) for attribution and abuse-tracing on the shared server-side key.

Authorization / Cookie / Cf-Access-Jwt-Assertion headers are stripped from spans on both paths. As a belt-and-suspenders backstop, enable Prevent Storing of IP Addresses in the Sentry project's Security & Privacy settings.

License

MIT — see [LICENSE](LICENSE).

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.