umami-compass 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,17 +2,18 @@
2
2
 
3
3
  **Open-source MCP server for Umami Analytics — Cloud and self-hosted.**
4
4
 
5
- ![Umami Compass MCP server for Umami Analytics: Cloud and self-hosted](https://raw.githubusercontent.com/webcredo/umami-compass/main/docs/assets/umami-compass-hero-v3.png)
5
+ ![Umami Compass MCP server for Umami Analytics: Cloud and self-hosted decision-ready analytics](https://raw.githubusercontent.com/webcredo/umami-compass/main/docs/assets/umami-compass-hero-v4.png)
6
6
 
7
7
  [![CI](https://github.com/webcredo/umami-compass/actions/workflows/ci.yml/badge.svg)](https://github.com/webcredo/umami-compass/actions/workflows/ci.yml)
8
8
  [![npm version](https://img.shields.io/npm/v/umami-compass?logo=npm&color=CB3837)](https://www.npmjs.com/package/umami-compass)
9
9
  [![license](https://img.shields.io/github/license/webcredo/umami-compass)](LICENSE)
10
+ [![Buy me a coffee on Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/P5Z8234QNW)
10
11
 
11
12
  **Distribution:** [`umami-compass` on npm](https://www.npmjs.com/package/umami-compass) · [`io.github.webcredo/umami-compass` in the official MCP Registry](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.webcredo%2Fumami-compass)
12
13
 
13
14
  Umami Compass is a secure, read-only [Model Context Protocol](https://modelcontextprotocol.io/) server for [Umami Analytics](https://umami.is/). It gives MCP clients accurate Umami 3.2 analytics without exposing a database or allowing arbitrary network requests.
14
15
 
15
- Version `0.2.0` is the current source release. See [Compatibility](#compatibility) before using it with older Umami versions.
16
+ Version `0.3.1` is the current source release. See [Compatibility](#compatibility) before using it with older Umami versions.
16
17
 
17
18
  > The `npx` examples follow the stable npm release channel and check it whenever the MCP process starts. For source-based evaluation, clone this repository, run `pnpm install --frozen-lockfile && pnpm build`, and use `node /absolute/path/to/umami-compass/dist/cli.js` as the MCP command.
18
19
 
@@ -42,7 +43,7 @@ npx --yes --prefer-online umami-compass@latest
42
43
 
43
44
  `@latest` selects the stable npm channel and `--prefer-online` makes npm check the registry even when package metadata is cached. npm still reuses the cached package when that exact release is already present. Updates take effect the next time the MCP process starts; an already running local server cannot replace itself.
44
45
 
45
- Use `umami-compass@next` instead to opt into preview releases. For reproducible CI or centrally managed environments, pin an exact release and omit the online check, for example `npx --yes umami-compass@0.2.0`. Never use the preview channel for an unattended production setup.
46
+ Use `umami-compass@next` instead to opt into preview releases. For reproducible CI or centrally managed environments, pin an exact release and omit the online check, for example `npx --yes umami-compass@0.3.1`. Never use the preview channel for an unattended production setup.
46
47
 
47
48
  ### Umami Cloud
48
49
 
@@ -91,12 +92,12 @@ Do not commit real credentials. Prefer a dedicated view-only Umami account and t
91
92
 
92
93
  ## Tools
93
94
 
94
- The least-privilege default enables `core,insights`: seven primitive aggregate tools plus five decision-ready aggregate workflows. Row-level events, sessions, replay, heatmaps, and other more sensitive modules remain opt-in.
95
+ The least-privilege default enables `core,insights`: eight primitive aggregate tools plus six decision-ready aggregate workflows. Row-level events, sessions, replay, heatmaps, and other more sensitive modules remain opt-in.
95
96
 
96
97
  | Toolset | Tools | Default |
97
98
  | --- | --- | --- |
98
- | `core` | `list_websites`, `get_website`, `get_website_stats`, `get_pageviews`, `get_metrics`, `get_active_visitors`, `get_website_date_range` | Yes |
99
- | `insights` | `resolve_website`, `get_portfolio_overview`, `explain_traffic_change`, `analyze_release_impact`, `tracking_health_check` | Yes |
99
+ | `core` | `get_server_info`, `list_websites`, `get_website`, `get_website_stats`, `get_pageviews`, `get_metrics`, `get_active_visitors`, `get_website_date_range` | Yes |
100
+ | `insights` | `resolve_website`, `get_portfolio_overview`, `explain_traffic_change`, `compare_traffic_series`, `analyze_release_impact`, `tracking_health_check` | Yes |
100
101
  | `events` | `list_events`, `get_event_stats`, `get_event_series` | No |
101
102
  | `sessions` | `list_sessions`, `get_session_stats`, `get_session`, `get_session_activity` | No |
102
103
  | `performance` | `get_web_vitals`, `get_performance_breakdown` for LCP, INP, CLS, FCP, and TTFB | No |
@@ -105,11 +106,34 @@ The least-privilege default enables `core,insights`: seven primitive aggregate t
105
106
  | `replay` | `list_replays` (metadata only; never raw rrweb payloads) | No |
106
107
  | `heatmaps` | `get_heatmap` (click/scroll pages and bounded detail points) | No |
107
108
 
108
- Set `UMAMI_TOOLSETS=all` or a comma-separated subset. The default has 12 aggregate tools; `all` has 35. Multi-website insights are bounded to 50 websites with four concurrent website workers. High-cardinality report, performance, heatmap, and activity results carry explicit limits and truncation metadata.
109
+ Set `UMAMI_TOOLSETS=all` or a comma-separated subset. The default has 14 aggregate tools; `all` has 37. Multi-website insights are bounded to 50 websites with four concurrent website workers. High-cardinality report, performance, heatmap, channel fan-out, and activity results carry explicit limits and truncation metadata.
109
110
 
110
111
  Successful tool responses preserve the existing `data` field and add a common `meta` envelope. Depending on the request it includes `dataStatus`, `emptyReason`, `websiteId`, `requestedRange`, `timezone`, and `truncated`, allowing clients to distinguish a valid empty range from a disabled feature or a truncated result.
111
112
 
112
- The server exposes `umami://websites` and the sanitized `umami://capabilities` resource. Guided prompts cover an analytics report, weekly portfolio briefing, traffic investigation, release impact, tracking health, and conversion audit; each prompt is registered only when its required toolset is enabled. Scheduling a recurring briefing remains the MCP client's responsibility; the local stdio server does not run a background scheduler or send messages.
113
+ The server exposes `umami://websites` and the sanitized `umami://capabilities` resource. `get_server_info` returns the same local version, enabled toolsets, limits, and feature flags as a tool. Guided prompts cover an analytics report, weekly portfolio briefing, traffic investigation, release impact, tracking health, and conversion audit; each prompt is registered only when its required toolset is enabled. Scheduling a recurring briefing remains the MCP client's responsibility; the local stdio server does not run a background scheduler or send messages.
114
+
115
+ ### Filters, direct traffic, channels, and traffic quality
116
+
117
+ Plain string filters remain compatible. Structured filters add `equals`, `not_equals`, `contains`, `not_contains`, `regex`, `not_regex`, `is_empty`, and `is_not_empty`. Equality operators accept an array for native `IN` or `NOT IN` behavior:
118
+
119
+ ```json
120
+ {
121
+ "filters": {
122
+ "referrer": { "operator": "is_empty" },
123
+ "path": { "operator": "not_equals", "value": ["/admin", "/internal"] }
124
+ }
125
+ }
126
+ ```
127
+
128
+ For compatibility, `{"referrer": ""}` also isolates rows whose referrer domain is empty. This is not always the same as Umami's `direct` channel: a no-referrer visit with campaign parameters can be attributed to affiliate, email, paid, or another channel. Use `filters.channel: "direct"` when exact Umami channel attribution matters. Compass uses Umami's neutral referrer-domain column for structured and empty-referrer filters so internal/no-referrer traffic is not accidentally removed by Umami's external-referrer behavior.
129
+
130
+ `explain_traffic_change`, `analyze_release_impact`, and `run_breakdown_report` accept `filters.channel`, including `direct`. `run_breakdown_report` also accepts `channel` as a field, so requests such as `channel × device` work. Umami 3.2 does not natively expose channel as a filter or breakdown field; Compass derives these results through bounded expanded-metric fan-out and reports candidate coverage, omitted rows, request count, and truncation under `dataQuality`. Channel cross-tabs cannot be combined with custom events or with `filters.match: "any"`, because Umami cannot express the required candidate predicate outside that OR group; Compass rejects these requests instead of returning overlapping totals.
131
+
132
+ Traffic-change, release-impact, comparison-series, and breakdown results conservatively flag referral-spam candidates using the combined pattern of a generated-looking domain, very high bounce rate, near-zero visit duration, and minimum traffic. Set `trafficSegment` to `human` to exclude only those candidates with native negative filters. The preset fails closed when both periods cannot be assessed or when mandatory exclusions would be weakened by `filters.match: "any"`. Findings remain heuristics, not a definitive bot classification, and include their evidence and thresholds.
133
+
134
+ `compare_traffic_series` fills sparse rows against real buckets in the requested timezone, including DST transitions. If current and comparison periods contain different numbers of local-time buckets, it returns the raw series with `alignedChangesAvailable: false` and omits derived bucket deltas instead of shifting the comparison.
135
+
136
+ Structured filters retain field-specific length limits, at most 20 values per condition, 30 conditions and 100 values across one request, and a 16 KiB serialized-query budget.
113
137
 
114
138
  ## Configuration
115
139
 
@@ -317,6 +341,12 @@ Analytics, session metadata, revenue, and replay metadata can be sensitive. Use
317
341
 
318
342
  Umami Compass is an independent community project and is not affiliated with Umami Software.
319
343
 
344
+ ## Support the project
345
+
346
+ Umami Compass is free and open source. If it saves you time or improves your analytics workflow, you can support the project by buying me a coffee on Ko-fi.
347
+
348
+ [![Buy me a coffee on Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/P5Z8234QNW)
349
+
320
350
  ## License
321
351
 
322
352
  [MIT](LICENSE) © 2026 webcredo and Umami Compass contributors.
@@ -3,6 +3,7 @@ import type { UmamiClient } from "../api/client.js";
3
3
  import type { Website } from "../api/types.js";
4
4
  import type { TimeInput } from "../time.js";
5
5
  import { type filtersSchema } from "./schemas.js";
6
+ import { type TrafficChannel } from "./traffic-segmentation.js";
6
7
  export declare const TRAFFIC_DIMENSIONS: readonly ["path", "referrer", "country", "device", "channel", "event"];
7
8
  export type TrafficDimension = (typeof TRAFFIC_DIMENSIONS)[number];
8
9
  export interface TimePeriod {
@@ -35,12 +36,50 @@ export declare function isoPeriod(period: TimePeriod): {
35
36
  };
36
37
  export declare function normalizePeriod(start: TimeInput, end: TimeInput, maxRangeDays: number): TimePeriod;
37
38
  export declare function comparisonPeriod(current: TimePeriod, mode: "previous" | "year_over_year"): TimePeriod;
39
+ export type TrafficSeriesUnit = "minute" | "hour" | "day" | "month" | "year";
40
+ interface TrafficSeriesPoint {
41
+ x: number | string;
42
+ y: number;
43
+ }
44
+ interface TrafficSeriesData {
45
+ pageviews: TrafficSeriesPoint[];
46
+ sessions: TrafficSeriesPoint[];
47
+ }
48
+ export declare function alignTrafficSeries(currentPeriod: TimePeriod, currentSeries: TrafficSeriesData, comparisonPeriod: TimePeriod, comparisonSeries: TrafficSeriesData, unit: TrafficSeriesUnit, timezone: string): {
49
+ buckets: {
50
+ index: number;
51
+ current: {
52
+ x: string;
53
+ pageviews: number;
54
+ sessions: number;
55
+ } | null;
56
+ comparison: {
57
+ x: string;
58
+ pageviews: number;
59
+ sessions: number;
60
+ } | null;
61
+ pageviewChange: {
62
+ absolute: number;
63
+ percent: number | null;
64
+ };
65
+ }[];
66
+ dataQuality: {
67
+ sparseBucketsFilled: boolean;
68
+ currentBucketCount: number;
69
+ comparisonBucketCount: number;
70
+ equalBucketCount: boolean;
71
+ alignedChangesAvailable: boolean;
72
+ alignmentIssue?: string | undefined;
73
+ };
74
+ };
38
75
  export declare function mapConcurrent<T, R>(values: readonly T[], concurrency: number, operation: (value: T, index: number) => Promise<R>): Promise<R[]>;
39
- export declare function fetchWebsiteStats(client: UmamiClient, websiteId: string, period: TimePeriod, maxRangeDays: number, filters: Filters, signal?: AbortSignal): Promise<WebsiteStats>;
76
+ export declare function fetchWebsiteStats(client: UmamiClient, websiteId: string, period: TimePeriod, maxRangeDays: number, filters: Filters, signal?: AbortSignal, excludedReferrers?: readonly string[]): Promise<WebsiteStats>;
40
77
  export interface TrafficComparisonInput {
78
+ channel?: TrafficChannel;
41
79
  comparison: TimePeriod;
42
80
  current: TimePeriod;
43
81
  dimensions: readonly TrafficDimension[];
82
+ excludedReferrers?: readonly string[];
44
83
  filters?: Filters;
45
84
  limit: number;
46
85
  maxRangeDays: number;
@@ -50,6 +89,11 @@ export interface TrafficComparisonInput {
50
89
  export declare function compareTraffic(client: UmamiClient, input: TrafficComparisonInput): Promise<{
51
90
  dataStatus: "available" | "empty";
52
91
  website: Pick<Website, "domain" | "id" | "name">;
92
+ channel?: "affiliate" | "direct" | "email" | "llm" | "organicSearch" | "organicShopping" | "organicSocial" | "organicVideo" | "paidAds" | "paidSearch" | "paidShopping" | "paidSocial" | "paidVideo" | "referral" | "sms" | undefined;
93
+ scope: {
94
+ channel: string;
95
+ excludedReferrers: string[];
96
+ };
53
97
  currentPeriod: {
54
98
  start: string;
55
99
  end: string;
@@ -70,7 +114,47 @@ export declare function compareTraffic(client: UmamiClient, input: TrafficCompar
70
114
  explanation: string;
71
115
  breakdownMeasure: string;
72
116
  breakdowns: ({
73
- dimension: "channel" | "country" | "device" | "event" | "path" | "referrer";
117
+ dimension: "channel";
118
+ status: "available";
119
+ measure: "visitors";
120
+ rows: {
121
+ name: string;
122
+ current: number;
123
+ comparison: number;
124
+ delta: number;
125
+ percent: number | null;
126
+ direction: string;
127
+ }[];
128
+ dataQuality: {
129
+ currentRowsTruncated: boolean;
130
+ comparisonRowsTruncated: boolean;
131
+ omittedUncertainRows: number;
132
+ };
133
+ error?: undefined;
134
+ } | {
135
+ dimension: "country" | "device" | "event" | "path" | "referrer";
136
+ status: "available";
137
+ measure: "visitors";
138
+ rows: {
139
+ name: string;
140
+ current: number;
141
+ comparison: number;
142
+ delta: number;
143
+ percent: number | null;
144
+ direction: string;
145
+ }[];
146
+ dataQuality: {
147
+ currentRowsTruncated: boolean;
148
+ comparisonRowsTruncated: boolean;
149
+ omittedUncertainRows: number;
150
+ candidateRowsTruncated: boolean;
151
+ candidateRows: number;
152
+ omittedUnsupportedRows: number;
153
+ fanoutRequests: number;
154
+ };
155
+ error?: undefined;
156
+ } | {
157
+ dimension: "country" | "device" | "event" | "path" | "referrer";
74
158
  status: "available";
75
159
  measure: "visitors";
76
160
  rows: {
@@ -121,6 +205,7 @@ export declare function compareTraffic(client: UmamiClient, input: TrafficCompar
121
205
  export declare function comparePerformance(client: UmamiClient, input: {
122
206
  comparison: TimePeriod;
123
207
  current: TimePeriod;
208
+ excludedReferrers?: readonly string[];
124
209
  filters?: Filters;
125
210
  signal?: AbortSignal;
126
211
  timezone: string;
@@ -128,6 +213,10 @@ export declare function comparePerformance(client: UmamiClient, input: {
128
213
  }): Promise<{
129
214
  error?: undefined;
130
215
  status: "available" | "empty";
216
+ scope: {
217
+ channel: "all";
218
+ excludedReferrers: string[];
219
+ };
131
220
  currentSampleCount: number;
132
221
  comparisonSampleCount: number;
133
222
  minimumSampleCount: number;
@@ -151,6 +240,10 @@ export declare function comparePerformance(client: UmamiClient, input: {
151
240
  sampleSufficient?: undefined;
152
241
  changes?: undefined;
153
242
  status: string;
243
+ scope: {
244
+ channel: "all";
245
+ excludedReferrers: string[];
246
+ };
154
247
  error: {
155
248
  code: import("../api/errors.js").UmamiErrorCode;
156
249
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"insights-utils.d.ts","sourceRoot":"","sources":["../../src/mcp/insights-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"insights-utils.d.ts","sourceRoot":"","sources":["../../src/mcp/insights-utils.ts"],"names":[],"mappings":"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"}