Skip to main content
Glama
Mzaxd

Umami MCP Server

by Mzaxd
README.md
# Umami MCP Server

Read-only MCP server for Umami analytics. It talks to the Umami REST API directly over HTTP, supports self-hosted Umami first, and also works with Umami Cloud API keys.

This repo is built so upper-layer agents can ask for analytics without re-reading the Umami docs each time. No browser automation, no DOM scraping, no write operations.

## Features

- Read-only MCP tools for the most common Umami analytics queries
- Two auth modes:
  - `UMAMI_API_KEY`
  - `UMAMI_USERNAME` + `UMAMI_PASSWORD`
- Self-hosted bearer token caching in memory
- Automatic re-login and one retry on `401` for username/password mode
- ISO time strings and millisecond timestamps both accepted
- Shared filter handling across stats, pageviews, breakdowns, and event series
- Strict TypeScript with small, maintainable modules
- Clear structured tool output and explicit error categories

## Requirements

- Node.js `>= 20`
- pnpm `>= 10`

## Install

From npm:

```bash
npm install -g umami-analytics-mcp
```

Or run without installing:

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

For local development in this repo:

```bash
pnpm install
```

## Configure

Create a `.env` file from `.env.example`.

```bash
cp .env.example .env
```

Fill in one of the following auth options:

1. API key mode

```env
UMAMI_API_URL=https://api.umami.is/v1
UMAMI_API_KEY=your-api-key
UMAMI_DEFAULT_TIMEZONE=Asia/Shanghai
```

2. Self-hosted username/password mode

```env
UMAMI_API_URL=https://umami.example.com/api
UMAMI_USERNAME=admin
UMAMI_PASSWORD=secret
UMAMI_DEFAULT_TIMEZONE=Asia/Shanghai
```

Notes:

- `UMAMI_API_URL` should point to the API base, not just the site origin.
- If both `UMAMI_API_KEY` and username/password are set, `UMAMI_API_KEY` wins.
- `UMAMI_DEFAULT_TIMEZONE` is used when a tool supports timezone and you omit it.

## Run Locally

Development mode:

```bash
pnpm dev
```

Build and run:

```bash
pnpm build
pnpm start
```

The server uses MCP stdio transport, so it stays attached to stdin/stdout until the client disconnects.

If installed from npm, the equivalent command is:

```bash
umami-analytics-mcp
```

## Test

```bash
pnpm test
pnpm build
```

There is also a real-API integration test template that is skipped by default:

```bash
UMAMI_INTEGRATION_TEST=1 pnpm test:integration
```

## MCP Inspector

Build first:

```bash
pnpm build
```

Then launch the official MCP Inspector against the built server:

```bash
npx @modelcontextprotocol/inspector node dist/cli.js
```

For hot reload during development, this also works:

```bash
npx @modelcontextprotocol/inspector pnpm dev
```

If you want to test the published package path instead, use:

```bash
npx @modelcontextprotocol/inspector npx -y umami-analytics-mcp
```

Make sure the same Umami environment variables are available to the Inspector process.

Recommended smoke calls in Inspector:

1. `umami_ping`
2. `umami_list_websites`
3. `umami_get_stats`
4. `umami_get_breakdown`

## Tools

### `umami_ping`

Validates configuration and authentication.

Example:

```json
{}
```

### `umami_list_websites`

Lists accessible websites.

Example:

```json
{}
```

### `umami_find_website`

Fuzzy search by website name or domain.

Example:

```json
{
  "query": "example.com"
}
```

### `umami_get_stats`

Summary stats for a website and time range.

Example:

```json
{
  "websiteId": "8f2f8ce2-1234-4567-89ab-0123456789ab",
  "startAt": "2026-04-23T00:00:00+08:00",
  "endAt": "2026-04-23T23:59:59+08:00",
  "filters": {
    "path": "/pricing"
  }
}
```

### `umami_get_pageviews`

Time-series pageviews and sessions.

Example:

```json
{
  "websiteId": "8f2f8ce2-1234-4567-89ab-0123456789ab",
  "startAt": "2026-04-17T00:00:00+08:00",
  "endAt": "2026-04-23T23:59:59+08:00",
  "unit": "day",
  "compare": "prev",
  "filters": {
    "path": "/blog"
  }
}
```

### `umami_get_breakdown`

Breakdown rows such as top pages, referrers, countries, browsers, devices, and more.

Example:

```json
{
  "websiteId": "8f2f8ce2-1234-4567-89ab-0123456789ab",
  "startAt": "2026-04-17T00:00:00+08:00",
  "endAt": "2026-04-23T23:59:59+08:00",
  "type": "path",
  "limit": 10,
  "expanded": false
}
```

### `umami_get_active`

Returns the current active visitor count.

Example:

```json
{
  "websiteId": "8f2f8ce2-1234-4567-89ab-0123456789ab"
}
```

### `umami_get_events_series`

Returns custom event counts over time.

Example:

```json
{
  "websiteId": "8f2f8ce2-1234-4567-89ab-0123456789ab",
  "startAt": "2026-04-17T00:00:00+08:00",
  "endAt": "2026-04-23T23:59:59+08:00",
  "unit": "day"
}
```

## Shared Filters

These tools support the same `filters` object:

- `path`
- `referrer`
- `title`
- `query`
- `browser`
- `os`
- `device`
- `country`
- `region`
- `city`
- `hostname`

## Error Handling

Tool errors are returned as structured MCP tool results with these categories:

- `config_missing`
- `auth_failed`
- `website_not_found`
- `umami_http_error`
- `network_timeout`
- `network_error`
- `invalid_input`

## Mount In Any Stdio MCP Client

Any stdio-based MCP client can run this server with:

- `command`: `npx`
- `args`: `["-y", "umami-analytics-mcp"]`
- `env`: your Umami variables

Example JSON snippet for clients that use an `mcpServers` object:

```json
{
  "mcpServers": {
    "umami": {
      "command": "npx",
      "args": ["-y", "umami-analytics-mcp"],
      "env": {
        "UMAMI_API_URL": "https://umami.example.com/api",
        "UMAMI_USERNAME": "admin",
        "UMAMI_PASSWORD": "secret",
        "UMAMI_DEFAULT_TIMEZONE": "Asia/Shanghai"
      }
    }
  }
}
```

For a local unreleased checkout, you can still point directly to the built file:

```json
{
  "mcpServers": {
    "umami": {
      "command": "node",
      "args": ["/absolute/path/to/umami-mcp/dist/cli.js"]
    }
  }
}
```

## Publish To npm

This repo is now structured as an npm CLI package.

Recommended release flow:

```bash
pnpm test
pnpm build
pnpm pack --dry-run
npm login
pnpm publish
```

Notes:

- The package name is set to `umami-analytics-mcp` because `umami-mcp` is already taken on npm.
- The current `license` is `UNLICENSED` as a safe placeholder. Replace it before a real public open-source release if you want a permissive license.
- If you later publish under your own npm scope, change only the `name` field in `package.json`.

## Internal Docs

- API summary used by this repo: [docs/umami-api.md](docs/umami-api.md)

TDQS

A4.2/5.0

Scored across 8 tools

Disambiguation5/5

Each tool serves a distinct purpose: searching, listing, validating, and retrieving various analytics metrics (active visitors, breakdown, events, pageviews, stats). No overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent 'umami_verb_noun' pattern (e.g., umami_find_website, umami_get_active). The pattern is uniform and predictable.

Tool Count5/5

With 8 tools, the set is well-scoped for an analytics API. It covers essential query operations without being bloated or sparse.

Completeness5/5

The tool set provides comprehensive read-only access to Umami analytics: website listing/search, active visitors, pageviews, events, breakdowns, stats, and authentication validation. No obvious gaps for querying use cases.

Maintenance

ActivityInactive
ResponsivenessNo issues