Umami MCP
Provides read-only access to Umami analytics, enabling assistants to list websites and retrieve stats, pageviews, ranked metric breakdowns, active visitors, and recent custom events. Supports resolving websites by id, name, or domain and querying common date ranges with timezone handling.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Umami MCP
Repository: https://github.com/kennethreitz/umami-mcp
A read-only MCP server for Umami. An assistant can list your websites and read stats, pageviews, breakdowns, active visitors, and events.
It speaks stdio for a local client and streamable HTTP for a hosted one. HTTP mode refuses to start unless MCP_AUTH_TOKEN is set.
The server uses the official mcp Python SDK. In SDK 2.x the high-level class is MCPServer (the class that used to be called FastMCP).
Tools
Tool | What it returns |
| Websites you can read, including team sites. Optional |
| Pageviews, visitors, visits, bounces, and total time, each compared with the previous period of the same length. |
| Pageviews and sessions over time. The bucket is chosen from the range unless you pass |
| A ranked breakdown. |
| Visitors active in the last few minutes. |
| Recent custom events, newest first. |
Pass a website id, name, or domain. Exact name or domain wins; otherwise a unique substring match is used. If several sites match, the tool lists them and stops.
Date ranges accept today, yesterday, 24h, 7d, 30d, 90d, this week, last week, this month, last month, this year, last year, a day (2026-01-15), or a span (2026-01-01/2026-01-31 or 2026-01-01 to 2026-01-31). Ranges are resolved in timezone (IANA name). The default is America/New_York, or UMAMI_TIMEZONE when that is set.
Every tool is marked read-only. There is no write endpoint.
Related MCP server: yawa
Configure
Copy .env.example to .env if you want a file to edit. The process reads the environment; it does not load .env by itself.
Variable | Required | Purpose |
| One of these auth modes | Cloud API key, or a self-hosted API key. |
| Self-hosted | Site origin, such as |
| Self-hosted login | Used together when you do not have an API key. A 401 fetches a new token once. |
| No |
|
| No |
|
| No | Default timezone. |
| No |
|
| HTTP only | Bearer token clients must send. The server will not listen without it. |
| No | Bind address. |
| No | HTTP port. Default |
| No | Comma-separated |
| No | Comma-separated |
Auth rules:
Umami Cloud: set
UMAMI_API_KEY. LeaveUMAMI_URLempty unless you need a specific base. Cloud does not accept username and password.Self-hosted API key: set
UMAMI_URLandUMAMI_API_KEY.Self-hosted login: set
UMAMI_URL,UMAMI_USERNAME, andUMAMI_PASSWORD. If the account has two-factor authentication, create an API key instead. This server does not complete the second factor.If both an API key and a password are set, the API key is used.
UMAMI_URL for a self-hosted site is the origin (https://analytics.example.com). Requests go to {origin}/api/.... If the URL already ends in /api or /v1, that suffix is kept and /api is not added again. Cloud calls go to https://api.umami.is/v1/... with no extra /api.
Run locally with uv
Install uv, then:
uv sync
export UMAMI_API_KEY="your-cloud-key"
uv run umami-mcpThat is stdio. The process waits on stdin; a client has to speak first. Nothing is printed on stdout, because stdout is the MCP stream.
HTTP, for a client that connects by URL:
export UMAMI_API_KEY="your-cloud-key"
export MCP_TRANSPORT=http
export MCP_AUTH_TOKEN="$(openssl rand -hex 32)"
uv run umami-mcpOr uv run umami-mcp http. The MCP endpoint is http://127.0.0.1:8787/mcp. GET /health is open so a process supervisor can probe it. GET / tells a browser where to connect. Everything under /mcp requires Authorization: Bearer $MCP_AUTH_TOKEN.
Self-hosted example:
export UMAMI_URL="https://analytics.example.com"
export UMAMI_USERNAME="admin"
export UMAMI_PASSWORD="..."
uv run umami-mcpConnect a client
Hosted (streamable HTTP)
Cursor, Claude, and other clients that accept a remote MCP URL:
{
"mcpServers": {
"umami": {
"url": "https://umami-mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}Put the server's public HTTPS URL in url. The token is MCP_AUTH_TOKEN, not the Umami API key. The Umami key stays on the server.
Local stdio
{
"mcpServers": {
"umami": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/this/repo", "umami-mcp"],
"env": {
"UMAMI_API_KEY": "your-cloud-key"
}
}
}
}For a self-hosted Umami, set UMAMI_URL plus either UMAMI_API_KEY or UMAMI_USERNAME and UMAMI_PASSWORD in env.
Deploy
The container listens on 0.0.0.0 and $PORT (default 8787) with MCP_TRANSPORT=http. Build it from this directory:
docker build -t umami-mcp .
docker run --rm -p 8787:8787 \
-e UMAMI_API_KEY \
-e MCP_AUTH_TOKEN \
umami-mcpPass Umami credentials and MCP_AUTH_TOKEN at run time. Do not bake them into the image. /health returns {"status":"ok"} without a token.
HTTP mode is stateless and answers each MCP POST with a single JSON body, so more than one replica does not need sticky sessions.
Dokploy
Create an application from this repo (Dockerfile build) or from the image.
Set the container port to
8787, or setPORTto the port Dokploy routes to and use that.Add environment variables:
UMAMI_API_KEY(orUMAMI_URLplus username and password), andMCP_AUTH_TOKEN.Point the health check at
GET /health.Attach a domain and HTTPS. Give clients
https://<that-domain>/mcpand the bearer token.
Cloudflare (container, not a Worker)
This is a long-running Python process. Run it as a Cloudflare Container, or any other host that runs a Docker image. A Worker cannot host this process. Route public HTTPS to the container port (PORT, default 8787). Keep MCP_AUTH_TOKEN as the application secret; Cloudflare Access can sit in front as a second gate, but the MCP client still has to send the bearer token unless you strip that check yourself.
Leave MCP_ALLOWED_HOSTS empty when a proxy rewrites Host to your public name. Setting it turns on DNS-rebinding checks, and the proxy's Host has to be on the list. Binding MCP_HOST=127.0.0.1 also turns those checks on for localhost only, which is what you want on a laptop and the wrong choice inside a container.
Development
uv sync --group dev
uv run pytestTests mock Umami with respx. One test starts the real server over stdio and checks tools/list. Another starts HTTP, checks that /health is open, that /mcp returns 401 without the bearer token, and that a client with the token can list the tools.
API notes
Checked against the Umami docs on docs.umami.is (the current reference) and the older v2 reference on v2.umami.is. No live Cloud or self-hosted instance was called from this repo, so a few shapes are handled defensively rather than confirmed against production.
Auth headers. The current Cloud and self-hosted docs say to send an API key as Authorization: Bearer <key>. Older Cloud reports, and Umami's own Cloud MCP page, also describe x-umami-api-key. The default sends both the same key. Set UMAMI_API_KEY_HEADER=bearer or UMAMI_API_KEY_HEADER=x-umami-api-key to send only one. Which header a given Cloud gateway requires was not verified with a live key.
Paths. Self-hosted: POST {UMAMI_URL}/api/auth/login, then GET {UMAMI_URL}/api/websites, GET /api/websites/{id}/stats, /pageviews, /metrics, /active, /events. Cloud: the same paths under https://api.umami.is/v1 with no /api prefix. Optional region prefix: /v1/us or /v1/eu.
Stats comparison. Current docs return flat numbers plus a comparison object, and accept compare=prev (or yoy). Older v2 responses nest { "value", "prev" } on each stat and include the previous period without that parameter. This server sends compare=prev and understands both bodies. compare=yoy is not requested. The previous window printed in the text is an equal-length range immediately before the one you asked for, which matches the documented comparison. The exact millisecond boundary on a live server was not rechecked.
Numbers. Stats sometimes arrive as strings or null (reported against the current API). Those are coerced. totaltime is treated as seconds. The average shown is total time divided by visits. Umami's dashboard has used other formulas (for example excluding bounces). Treat the average as a reading of the API field, not a pixel-perfect copy of the dashboard card.
Metrics. Current docs use type=path. Older v2 docs use type=url. A request for pages sends path, and on HTTP 400 retries once with url.
Active visitors. The common-endpoints page says the count covers the last 5 minutes. The active-endpoint page says "the last few minutes." The tool uses the latter wording and does not invent a window the payload does not include.
Events. eventType 1 is a pageview and 2 is a custom event, from the current reference. The default asks for custom events only.
Rate limit. Cloud docs say 50 calls per API key every 15 seconds. A 429 is returned as a tool error. This was not measured.
Login. POST /api/auth/login with { "username", "password" } returns { "token", "user" }. A body with requiresTwoFactor and no token stops with a message to use an API key. The /api/2fa/verify step is not implemented.
License
Copyright 2026 Kenneth Reitz.
umami-mcp is licensed under the Apache License, Version 2.0. The full text is in LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read-only website analytics, AI referrals, crawlers, goals, revenue, and funnels.
Privacy-first, cookie-free web analytics. Read stats and manage sites from your AI.
Your website analytics as read-only tools: traffic, pages, errors, speed and AI-assistant visits.
Read-only Google Search Console, Bing, Google Analytics and privacy-friendly analytics for your AI.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn unofficial server that allows AI assistants to access Fathom Analytics data, enabling users to retrieve account information, site statistics, events, aggregated reports, and real-time visitor tracking.540 npm4MIT
- AlicenseNot gradedqualityBmaintenanceSelf-hosted web analytics platform that exposes analytics data via the Model Context Protocol, enabling natural language queries about traffic, page views, web vitals, and custom events.12MIT
- AlicenseNot gradedqualityDmaintenanceA read-only Model Context Protocol server for self-hosted Umami analytics. Enables querying website analytics data such as pageviews, visitors, and metrics through natural language.1MIT
- AlicenseAqualityDmaintenanceFirst-party web analytics MCP server for AI agents, providing 42 tools to query traffic, events, funnels, conversions, sources, and performance data.4040 npmMIT