Skip to main content
Glama
AryanKo

Plausible Analytics MCP Server

by AryanKo
README.md
# Plausible Analytics MCP Server

A stdio-based Model Context Protocol (MCP) server that gives Large Language Models (LLMs) tools to read analytics data from a Plausible Analytics account (cloud-hosted or self-hosted). It operates as a read-only proxy — it does not store, transform, cache, or mutate anything. Every tool call maps to exactly one Plausible API request.

## Prerequisites

- **Python**: 3.12 or higher
- **Package Manager**: [`uv`](https://github.com/astral-sh/uv)
- **Plausible Account**: Plausible Cloud or self-hosted instance with an API key (Personal Access Token)

## Setup Instructions

1. Clone the repository and navigate into the directory:
   ```bash
   git clone <repository-url>
   cd plausible-mcp
   ```

2. Install dependencies using `uv`:
   ```bash
   uv sync
   ```

3. Create and configure your environment file:
   ```bash
   cp .env.example .env
   ```

4. Edit `.env` to set your credentials:
   ```env
   PLAUSIBLE_API_KEY=your_secret_api_key_here
   PLAUSIBLE_BASE_URL=https://plausible.io
   ```
   *(For self-hosted instances, replace `https://plausible.io` with your custom instance URL).*

## Running the Server

Start the server locally over stdio transport:
```bash
uv run python -m src.server
```

## MCP Client Configuration (Claude Desktop)

To connect this MCP server to Claude Desktop, add the following entry to your `claude_desktop_config.json` file (typically located at `%APPDATA%\Claude\claude_desktop_config.json` on Windows or `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "plausible-mcp": {
      "command": "uv",
      "args": [
        "--directory",
        "C:/path/to/plausible-mcp",
        "run",
        "python",
        "-m",
        "src.server"
      ],
      "env": {
        "PLAUSIBLE_API_KEY": "your_secret_api_key_here",
        "PLAUSIBLE_BASE_URL": "https://plausible.io"
      }
    }
  }
}
```

## Tool Reference

### 1. `list_sites`
- **Description**: Returns the list of sites/domains accessible by the configured Plausible API key.
- **Parameters**: None
- **Example Call**:
  ```python
  list_sites()
  ```

### 2. `query_stats`
- **Description**: General-purpose analytics query endpoint wrapping Plausible Stats API v2 (`POST /api/v2/query`).
- **Parameters**:
  - `site_id` (`str`, required): The domain name configured in Plausible (min length 1).
  - `metrics` (`list[Metric]`, required): List of confirmed metrics (e.g. `visitors`, `visits`, `pageviews`, `bounce_rate`, `visit_duration`, `events`, `scroll_depth`, `percentage`, `conversion_rate`, `group_conversion_rate`, `average_revenue`, `total_revenue`, `time_on_page`).
  - `date_range` (`DateRangePreset` | `DateRangeCustom`, required): Either a preset string (`day`, `24h`, `7d`, `28d`, `30d`, `91d`, `month`, `6mo`, `12mo`, `year`, `all`) or a 2-element list of ISO8601 date/datetime strings (e.g., `["2026-01-01", "2026-01-07"]`).
  - `dimensions` (`list[str]`, optional): List of event, visit, or time dimensions (e.g., `visit:source`, `event:page`, `time:day`).
  - `filters` (`list[FilterClause]`, optional): Structurally validated filter clauses (e.g., `[["is", "visit:country", ["US"]]]`).
  - `order_by` (`list[tuple[str, "asc" | "desc"]]`, optional): Sorting specifications.
  - `pagination` (`Pagination`, optional): Limits and offsets (`{"limit": 10000, "offset": 0}`).
- **Example Call**:
  ```python
  query_stats(
      site_id="example.com",
      metrics=["visitors", "pageviews"],
      date_range="7d",
      dimensions=["visit:source"],
      order_by=[("visitors", "desc")]
  )
  ```

### 3. `get_realtime_visitors`
- **Description**: Convenience wrapper querying the current active visitor count over a server-fixed 5-minute window (`now - 5 minutes` to `now`).
- **Parameters**:
  - `site_id` (`str`, required): The domain name configured in Plausible.
- **Example Call**:
  ```python
  get_realtime_visitors(site_id="example.com")
  ```

## Known Limitations

- **Filter DSL Structural Validation Only**: Filter clauses undergo structural validation (checking element length and operator string), but semantic validation of Plausible's full filter DSL is delegated to the Plausible API itself.
- **stdio Transport Only**: Only stdio transport is supported in this release.
- **Single Account / Single API Key**: Designed for single-tenant operations per server instance.
- **Read-Only Scope**: Purely read-only proxy. Endpoint calls to record pageviews, provision sites, or mutate goals are strictly out of scope.

## License

Not yet decided.

TDQS

B3.3/5.0

Scored across 3 tools

Disambiguation4/5

The three tools are mostly distinct: list_sites retrieves site metadata, query_stats provides general analytics data, and get_realtime_visitors focuses on current active visitors. There is slight overlap between query_stats and get_realtime_visitors, but the descriptions clearly differentiate realtime from historical querying.

Naming Consistency5/5

All tool names follow the verb_noun pattern: list_sites, query_stats, get_realtime_visitors. The naming is consistent, predictable, and clearly indicates the action and target resource.

Tool Count4/5

With only 3 tools, the server is minimal but focused. The count is not excessive and covers the core analytics needs (site listing, stats querying, and realtime tracking) without adding redundant tools.

Completeness4/5

The server covers the essential read-only analytics lifecycle for Plausible: listing sites, querying statistics, and checking realtime visitors. Minor gaps exist such as site management (add/delete) or specific breakdown endpoints, but query_stats likely abstracts several API v2 query types, so the surface is reasonably complete for typical analytics workflows.

Maintenance

ActivitySlowing
ResponsivenessNo issues