Matomo MCP
by luskan
README.md
# Matomo MCP — read-only analytics with local configuration
A local Node.js MCP server for Matomo Reporting API. Supports optional HTTP Basic
Auth, project-local credentials, User ID reports, visit details and bounded report
batches. No Matomo MCP plugin, reverse proxy, Python, keyring or listening port is
required. Licensed under MIT. Version **0.3.0**; Node.js **24 or later**.
## Install and configure
From the project where analytics will be used:
```sh
npx -y @martin4455/matomo-mcp-ro@0.3.0 configure
npx -y @martin4455/matomo-mcp-ro@0.3.0 check
```
Alternatively, install from source:
```sh
git clone https://github.com/luskan/matomo-mcp-ro.git
cd matomo-mcp-ro
npm ci --ignore-scripts
```
Then configure from the project where analytics will be used:
```sh
node "/absolute/path/to/matomo-mcp-ro/cli.mjs" configure
node "/absolute/path/to/matomo-mcp-ro/cli.mjs" check
```
Use `npm.cmd`/`npx.cmd` in PowerShell if script execution policy blocks `.ps1`.
Configuration runs in your own terminal: enter the HTTPS Matomo URL, choose whether
Basic Auth is required, and enter the API token and optional username/password.
Credential input is hidden. Configuration is saved only after a successful
read-only site-list request. Existing configurations from 0.2.1 remain valid.
Enter retains saved credentials; changing the URL requires new credentials.
The file `.matomo-mcp.json` lives in the exact current directory, or at an explicit
`--config /project/.matomo-mcp.json` path. No home/parent/environment fallback is
used. It is plaintext protected by mode 0600 on Unix or a private Windows ACL.
The same OS account can read it. Keep it out of archives and version control;
`configure` adds Git/search exclusions. Never paste credentials into AI chats,
CLI arguments, URLs or MCP client settings. `status` and `check` do not print them.
## Connect a client
Use `client-config codex`, `client-config claude-code` or
`client-config claude-desktop` to print settings with absolute paths and no secrets.
For desktop clients install to a stable local path and launch Node directly,
rather than using a shell or an ephemeral npx cache:
```sh
npm install --prefix .mcp/matomo --ignore-scripts @martin4455/matomo-mcp-ro@0.3.0
node .mcp/matomo/node_modules/@martin4455/matomo-mcp-ro/cli.mjs client-config codex
```
Exclude `.mcp/matomo/` from version control. This project-local installation needs
no sudo. A supplied npm tarball can be used instead by replacing the package name
with its local path.
- Codex CLI/Desktop: merge generated TOML into the trusted project's
`.codex/config.toml` for project scope.
- Claude Code: register from that project with `claude mcp add --scope local matomo
-- node /absolute/path/cli.mjs serve --config /project/.matomo-mcp.json`, quoting
paths as required by your shell.
- Claude Desktop chat: merge generated JSON into `claude_desktop_config.json`.
This is application scope; selecting a credential file does not create project
isolation for ordinary chats.
With no command the CLI starts `serve`. Stdout is reserved for MCP messages.
The process exits when the client closes stdin. Serving does not spawn shell
helpers. Windows configuration and permission checks use hidden system utilities.
## Tools
| Tool | Purpose |
| --- | --- |
| `matomo_list_sites` | Available sites and time zones |
| `matomo_site_info` | Site settings |
| `matomo_report_catalog` | Report metadata; filter by `query`/`module`, paginate, use `detailed=false` for a compact index |
| `matomo_goals` | Configured goals |
| `matomo_segments` | Saved segments |
| `matomo_segments_metadata` | Available segment fields |
| `matomo_dimensions` | Configured custom dimensions, active state and visit/action scope |
| `matomo_report` | 53 explicitly allowed reporting methods, including `UserId.getUsers` |
| `matomo_visits` | `Live.getLastVisitsDetails`, with action details, paging and a maximum 31-day date window |
| `matomo_report_batch` | 1–10 reports with ordered per-item results/errors; concurrency 1 by default, at most 2 |
Example tool arguments (synthetic identifiers):
```json
{
"method": "UserId.getUsers",
"idSite": 1,
"period": "day",
"date": "2026-09-01,2026-09-10",
"segment": "dimension2==trial",
"filter_limit": 1000,
"filter_offset": 0
}
```
Confirm the actual dimension ID/value using metadata before querying. A daily
series has one pagination entry per date. `period=range` instead returns the
aggregate for the window. All dates are explicit `YYYY-MM-DD` values; metrics are
requested as numbers (`format_metrics=0`).
```json
{
"idSite": 1,
"period": "day",
"date": "2026-09-10",
"segment": "userId==example-user",
"includeActions": true,
"filter_limit": 20,
"filter_offset": 0
}
```
Visits support at most 100 rows per page and `filter_sort_order`, not arbitrary
sort columns. `includeActions=false` reduces payload. Dedupe visits by site and
visit ID when collecting pages. A full page means another page may exist; inspect
`pagination.mayHaveMore`/`nextOffset`. Choose closed dates where possible.
Batch takes `{ "requests": [REPORT_ARGUMENTS, ...], "concurrency": 1 }`. Every
request is validated before any network access. Results preserve request indexes;
errors never become zero counts. Batch response budgets are 2 MiB per result and
8 MiB total; fetch oversized results individually with a smaller page size.
## Read-only boundaries and completeness
Write methods, arbitrary API URLs, `API.getBulkRequest`, credential overrides and
unlisted parameters are blocked before network requests. Redirects are rejected;
TLS validation stays enabled. API credentials are sent as a POST body token and
optional Basic Authorization header. Boolean API flags use PHP-safe 0/1 values.
Requests have a 60-second timeout and 10 MiB response limit. Report page limit is
1000. Cancellation stops queued batch work.
Metadata does not automatically allow new executable methods. The server does
not create saved segments, configure archiving, or change retention. Reading a
report can trigger Matomo's normal archive/cache generation.
Responses preserve `method`, `parameters`, `data` and add `fetchedAt`, `pagination`
and `completeness`. `Others` summary rows and unfetched subtables produce warnings.
Finishing pagination does not prove complete telemetry: archive row limits can
remove identities, raw data can expire, and tracking can be absent. Visitor-log
access may also be disabled. Action lists are server-returned, not guaranteed
complete. Visit-scoped dimensions do not establish a state for every individual
historical action in that visit.
## Use from a local Node script
The generic client export uses the same MCP transport and policy as an AI client.
It never reads the credential file itself:
```js
import { connectMatomo } from '@martin4455/matomo-mcp-ro/client';
const client = await connectMatomo({ configPath: '/project/.matomo-mcp.json' });
try {
const sites = await client.call('matomo_list_sites', {});
console.log(sites.data.map(site => site.name));
} finally {
await client.close();
}
```
Domain identity conversions, license/business rules, input lists, caching and
analysis outputs belong in separate private project skills/scripts. They are not
part of this public package. No persistent job service or output-file tool is
exposed over MCP.
## Development
```sh
npm ci --ignore-scripts
npm test
npm run release:check
npm pack --ignore-scripts
```
Tests use synthetic credentials and mocked HTTP with real MCP transports. CI
runs on Windows, Ubuntu and macOS. `release:check` verifies an explicit source
and npm file list. Keep this list current when adding code; the npm package
contains runtime files, README and LICENSE, not tests or private data.
- [Matomo Reporting API](https://developer.matomo.org/guides/reporting-api)
- [Matomo API tokens](https://matomo.org/faq/general/faq_114/)
- [Codex MCP](https://learn.chatgpt.com/docs/extend/mcp)
- [Claude Code MCP](https://code.claude.com/docs/en/mcp)
- [MIT license](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues