Skip to main content
Glama
matious89pl

umami-analytics-mcp

by matious89pl
README.md
# umami-analytics-mcp

> Security-first [Model Context Protocol](https://modelcontextprotocol.io) server for [Umami](https://umami.is) analytics — **Umami Cloud and self-hosted (v3)**. Set up, analyze, report on, and (when you allow it) administer your Umami instance from any MCP client.

[![CI](https://github.com/matious89pl/umami-analytics-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/matious89pl/umami-analytics-mcp/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

- 🚀 **Local-first** — `npx umami-analytics-mcp`, zero build step, ~2 runtime deps.
- ☁️ **Or host it** — deploy to **Vercel** (one Web function) or run the bundled **Docker** HTTP server. One shared core, three transports.
- 🔒 **Credential-safe** — secrets live in env only; never placed in tool arguments, outputs, or logs (two-layer redaction). Remote endpoints are bearer-gated and **fail closed**.
- 🎚️ **Least privilege** — **read-only by default**; `write` and `admin` tiers are opt-in; destructive ops (delete/reset) are double-gated.
- 📊 **Comprehensive** — full Umami **v3** surface: stats, metrics, events, sessions, **reports** (funnel, retention, journey, attribution, revenue, UTM, web-vitals), segments, teams, share links, event ingestion, and self-hosted user administration.

---

## Contents

- [Quickstart (local / npx)](#quickstart-local--npx)
- [Configuration](#configuration)
- [Capability tiers](#capability-tiers)
- [MCP client setup](#mcp-client-setup)
- [Remote hosting](#remote-hosting) · [Vercel](#deploy-to-vercel) · [Docker / self-host](#docker--self-host)
- [Security model](#security-model)
- [Tool reference](#tool-reference)
- [Prompts & resources](#prompts--resources)
- [Development](#development)

---

## Quickstart (local / npx)

No install required. Point your MCP client at:

```bash
npx -y umami-analytics-mcp
```

…with credentials supplied via environment variables. For **Umami Cloud**, create an API key at *Dashboard → Settings → API keys* and set `UMAMI_API_KEY`. For **self-hosted**, set `UMAMI_API_URL` + `UMAMI_USERNAME` + `UMAMI_PASSWORD`. See [MCP client setup](#mcp-client-setup) for copy-paste configs.

By default the server is **read-only** (32 analytics tools). Opt into writes/admin explicitly — see [Capability tiers](#capability-tiers).

---

## Configuration

All configuration is via environment variables (secrets) and optional CLI flags (non-secrets).

| Variable | Mode | Description |
| --- | --- | --- |
| `UMAMI_API_KEY` | Cloud | Umami Cloud API key (selects Cloud mode). |
| `UMAMI_CLOUD_REGION` | Cloud | `us` or `eu` (optional regional base URL). |
| `UMAMI_API_URL` | self-hosted | Instance base URL, e.g. `https://stats.example.com` (`/api` appended). |
| `UMAMI_USERNAME` / `UMAMI_PASSWORD` | self-hosted | Login credentials → bearer token (cached, auto-renewed on 401). |
| `UMAMI_TEAM_ID` | both | Scope website listings to a team (optional). |
| `UMAMI_DEFAULT_TIMEZONE` | both | IANA tz for time-series tools (default `UTC`). |
| `UMAMI_ENABLE_WRITE` | both | `1` to expose create/update + `send_event` tools. |
| `UMAMI_ENABLE_ADMIN` | both | `1` to expose user-management tools (**self-hosted only**). |
| `UMAMI_ALLOW_DESTRUCTIVE` | both | `1` — also required to expose delete/reset tools. |
| `MCP_AUTH_TOKEN` | remote | Shared-secret bearer required by the Vercel/HTTP endpoints. |

> Self-hosted instances that issue API keys can use `UMAMI_API_URL` + `UMAMI_API_KEY` instead of username/password.

Surrounding quotes are stripped from values defensively. For local use you can keep settings in a file and load them with `--env-file`:

```bash
npx umami-analytics-mcp --env-file .env.local
```

Run `npx umami-analytics-mcp --help` for the full flag list.

---

## Capability tiers

The server exposes only the tools for the tiers you enable, layered **on top of** Umami's own role-based access (the API still enforces your account's real permissions — tiers just decide which tools are even visible).

| Tier | Enable with | Adds | Example tools |
| --- | --- | --- | --- |
| **read** | _(always on)_ | analytics & reporting | `get_stats`, `get_metrics`, `report_funnel`, `list_sessions` |
| **write** | `UMAMI_ENABLE_WRITE=1` | mutations + ingestion | `create_website`, `send_event`, `add_team_member` |
| **admin** | `UMAMI_ENABLE_ADMIN=1` _(self-hosted)_ | user administration | `create_user`, `set_user_role` |
| **destructive** | `UMAMI_ALLOW_DESTRUCTIVE=1` _(+ write/admin)_ | delete / reset | `delete_website`, `reset_website`, `delete_user` |

Tool counts: **32** read → **46** with write → **52** with destructive → **58** at full tier on self-hosted. On Cloud the admin tier is automatically disabled (Umami Cloud has no user-admin API) and the server explains why at startup. Destructive tools carry MCP `destructiveHint` annotations so clients can warn before running them.

---

## MCP client setup

### Claude Desktop / Cursor (`claude_desktop_config.json` / `.cursor/mcp.json`)

```jsonc
{
  "mcpServers": {
    "umami": {
      "command": "npx",
      "args": ["-y", "umami-analytics-mcp"],
      "env": {
        "UMAMI_API_KEY": "your_cloud_api_key"
        // self-hosted instead:
        // "UMAMI_API_URL": "https://stats.example.com",
        // "UMAMI_USERNAME": "admin",
        // "UMAMI_PASSWORD": "••••••",
        // opt into writes:
        // "UMAMI_ENABLE_WRITE": "1"
      }
    }
  }
}
```

### Claude Code

```bash
claude mcp add umami \
  -e UMAMI_API_KEY=your_cloud_api_key \
  -- npx -y umami-analytics-mcp
```

### VS Code (`.vscode/mcp.json`)

```jsonc
{
  "servers": {
    "umami": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "umami-analytics-mcp"],
      "env": { "UMAMI_API_KEY": "your_cloud_api_key" }
    }
  }
}
```

---

## Remote hosting

Both remote transports require `MCP_AUTH_TOKEN`; without it they **reject every request** (fail closed). Clients authenticate with `Authorization: Bearer <MCP_AUTH_TOKEN>`.

### Deploy to Vercel

The repo ships a single Web function at [`api/mcp.ts`](api/mcp.ts) (no Next.js required).

1. Push this repo to GitHub and **Import** it in Vercel.
2. Set Environment Variables: your Umami credentials (`UMAMI_API_KEY` *or* `UMAMI_API_URL`+`UMAMI_USERNAME`+`UMAMI_PASSWORD`), optional tier flags, and a strong `MCP_AUTH_TOKEN`.
3. Deploy. Your endpoint is `https://<deployment>.vercel.app/api/mcp`.
4. **Harden**: enable Vercel **Deployment Protection** (locks preview URLs) and **Firewall**.

Connect a Streamable-HTTP-capable client to the URL with the bearer header. stdio-only clients bridge via:

```bash
npx mcp-remote https://<deployment>.vercel.app/api/mcp \
  --header "Authorization: Bearer $MCP_AUTH_TOKEN"
```

### Docker / self-host

Runs the framework-free standalone HTTP server (`umami-mcp-http`):

```bash
docker build -t umami-mcp .
docker run --rm -p 8787:8787 \
  -e UMAMI_API_KEY=your_cloud_api_key \
  -e MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
  umami-mcp
# → endpoint at http://localhost:8787/mcp  (health: /health)
```

Or without Docker: `MCP_AUTH_TOKEN=… UMAMI_API_KEY=… npx -y umami-analytics-mcp umami-mcp-http` (bin `umami-mcp-http`). Set `HOST`, `PORT`, optional `MCP_ALLOWED_HOSTS` (enables DNS-rebinding protection), or `MCP_ALLOW_INSECURE=1` for **localhost-only** unauthenticated dev.

---

## Security model

- **Secrets in env only.** Never committed, never passed as flags, never persisted. The self-hosted bearer token is cached **in memory** and re-fetched on 401.
- **Never logged or echoed.** A redaction layer scrubs secrets by key *and* by literal value from every log line, error, and tool result. `get_me` and user/admin responses are sanitized of `token`/`authKey`/`shareToken`. stdio diagnostics go to **stderr** only (stdout is the JSON-RPC channel).
- **Remote endpoints are auth-gated and fail closed** — constant-time bearer comparison; no `MCP_AUTH_TOKEN` ⇒ all requests rejected.
- **Least privilege by default** — read-only unless you opt in; destructive operations double-gated and annotated.
- **No third-party credential collection.** Run your own instance of this server. Never point credentials at someone else's hosted MCP endpoint.

See [SECURITY.md](SECURITY.md) for the full threat model and disclosure policy.

---

## Tool reference

<details open>
<summary><strong>Read tier (32 — always on)</strong></summary>

`list_websites` · `get_website` · `get_website_daterange` · `get_active_visitors` · `get_realtime` · `get_stats` · `get_pageviews` · `get_metrics` · `get_website_values` · `get_events` · `get_event_data` · `list_sessions` · `get_session` · `get_session_activity` · `get_session_stats` · `get_session_properties` · `report_funnel` · `report_retention` · `report_journey` · `report_goals` · `report_attribution` · `report_revenue` · `report_utm` · `report_breakdown` · `list_reports` · `get_report` · `list_segments` · `get_segment` · `list_teams` · `get_team` · `get_team_members` · `get_me`
</details>

<details>
<summary><strong>Write tier (UMAMI_ENABLE_WRITE)</strong></summary>

`create_website` · `update_website` · `manage_website_share` · `transfer_website` · `send_event` · `create_team` · `update_team` · `join_team` · `add_team_member` · `update_team_member` · `create_segment` · `update_segment` · `create_report` · `update_report`

Destructive (also needs `UMAMI_ALLOW_DESTRUCTIVE`): `delete_website` · `reset_website` · `delete_team` · `remove_team_member` · `delete_segment` · `delete_report`
</details>

<details>
<summary><strong>Admin tier (UMAMI_ENABLE_ADMIN — self-hosted)</strong></summary>

`list_users` · `get_user` · `create_user` · `update_user` · `set_user_role`

Destructive: `delete_user`
</details>

Every tool returns a concise **text summary** plus a typed `structuredContent` payload, and accepts flexible date ranges (`range: "7d" | "today" | "this-month"`, or explicit `startAt`/`endAt`).

---

## Prompts & resources

**Prompts** (server-side, teach correct tool-chaining): `analytics_report`, `traffic_overview`, `top_pages`, `acquisition_channels`, `realtime_check`, `funnel_analysis`, `retention_analysis`, `audience_insights`, `compare_periods`.

**Resources**: `umami://websites`, `umami://website/{id}`, `umami://me` (sanitized).

---

## Development

```bash
npm install
npm run build        # tsup → dist/{cli,http,server}.js
npm test             # vitest (58 tests)
npm run typecheck    # tsc --noEmit
npm run inspect      # MCP Inspector against the stdio CLI
```

Architecture: a single `registerAll(server, ctx)` core ([src/server.ts](src/server.ts)) is shared by the stdio CLI ([src/bin/cli.ts](src/bin/cli.ts)), the standalone HTTP server ([src/http/server.ts](src/http/server.ts)), and the Vercel function ([api/mcp.ts](api/mcp.ts)) — so the tool surface never drifts between local and hosted modes. See the [design spec](docs/superpowers/specs/2026-06-30-umami-analytics-mcp-design.md).

## License

[MIT](LICENSE) © Mateusz Siatrak

TDQS

A3.6/5.0

Scored across 32 tools

Disambiguation4/5

Most tools have distinct purposes, but the high number (32) and some similar-sounding names (e.g., get_events vs get_metrics for events, get_realtime vs get_active_visitors) may cause confusion. Descriptions are clear enough to differentiate, but an agent might misselect without careful reading.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern in snake_case: get_*, list_*, report_*. This is a predictable and clear naming scheme that helps an agent quickly grasp the tool's action and subject.

Tool Count3/5

With 32 tools, the surface is heavy. While the analytics domain is broad and many tools serve distinct analytical needs, the count exceeds the 'heavy' threshold (16-25). Some tools could potentially be consolidated (e.g., report_* tools share similar structure).

Completeness5/5

The tool set covers the full analytics lifecycle: website and team metadata, time-series data, event tracking, session details, real-time, saved reports, segments, and various report types (funnels, goals, retention, etc.). It includes utility tools like get_website_daterange and get_website_values for validation. No obvious gaps for a read-only analytics server.

Maintenance

ActivityStale
ResponsivenessNo issues