> For the complete documentation index, see [llms.txt](https://docs.millimetric.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.millimetric.ai/mcp-for-ai-agents/overview.md).

# MCP server

Millimetric ships a first-class **Model Context Protocol** server at `/mcp`. Any MCP client (Claude Code, Claude Desktop, MCP Inspector, custom agents) can connect and use the same five operations a developer would.

## Endpoints

Millimetric exposes two MCP servers. Pick the one that matches the credential you have:

| Endpoint            | Auth                       | Scope                                                                            | Plan     |
| ------------------- | -------------------------- | -------------------------------------------------------------------------------- | -------- |
| `POST /mcp`         | `sk_live_…` or `rk_live_…` | One project per key.                                                             | Pro+     |
| `POST /mcp/account` | `ak_live_…`                | Every project the account owns. Includes `list_projects` and `compare_projects`. | Business |

```
POST https://api.millimetric.ai/mcp
Authorization: Bearer {key}
```

The transport is **JSON-RPC 2.0 over HTTP** (the latest MCP HTTP transport — no SSE needed for stateless calls).

For multi-project setups (agencies, multi-product teams), jump to [Account MCP](#account-mcp) below.

## Auth

`/mcp` accepts **only server-side keys**: `rk_live_…` (read-only) and `sk_live_…` (read + ingest).

`pk_live_…` keys are **rejected** at `/mcp` with `403 key_kind_not_allowed`. `pk_` keys are designed to ship in browser JS for the tracking SDK, which means anyone with view-source on a customer's site can read them — they must never grant access to query a project's events. Generate `rk_` / `sk_` keys from the dashboard and paste them into your agent's config server-side.

| You give the agent | It can call                                                         |
| ------------------ | ------------------------------------------------------------------- |
| `rk_live_…`        | `query_events`, `get_stats`, `top_sources`, `funnel`, all resources |
| `sk_live_…`        | the read tools above **and** `track_event`                          |
| `pk_live_…`        | **rejected** — `pk_` is browser-only                                |

Use `rk_*` by default. Only hand the agent an `sk_*` key if it needs to emit events on its own behalf.

## Tools

### `track_event` — emit an event (requires `ingest`)

```json
{
  "name": "track_event",
  "arguments": {
    "event": "agent_task_completed",
    "anonymous_id": "agent_001",
    "user_id": "user_42",
    "properties": { "task": "refactor_billing", "duration_ms": 12_400 }
  }
}
```

### `query_events` — raw events (requires `read`)

```json
{
  "name": "query_events",
  "arguments": {
    "from": "2026-05-01T00:00:00Z",
    "to":   "2026-05-17T00:00:00Z",
    "event": "signup",
    "source": "facebook",
    "limit": 50
  }
}
```

### `get_stats` — aggregations (requires `read`)

```json
{
  "name": "get_stats",
  "arguments": {
    "metric": "uniques",
    "from": "2026-05-01T00:00:00Z",
    "to":   "2026-05-17T00:00:00Z",
    "group_by": "source,medium",
    "interval": "day"
  }
}
```

### `top_sources` — the FB social-vs-paid split (requires `read`)

```json
{
  "name": "top_sources",
  "arguments": {
    "from": "2026-05-01T00:00:00Z",
    "to":   "2026-06-01T00:00:00Z",
    "breakdown": "source_medium",
    "limit": 20
  }
}
```

## Resources

* **`events://recent`** — last 100 events for the authenticated project.
* **`schema://events`** — distinct event names observed in the last 30 days. Useful for agents that want to discover what they can query before guessing.

## Connecting from Claude Code

Add this to your MCP config (`~/.claude/config.json` or via the UI):

```json
{
  "mcpServers": {
    "millimetric": {
      "url": "https://api.millimetric.ai/mcp",
      "transport": "http",
      "headers": {
        "Authorization": "Bearer rk_live_…"
      }
    }
  }
}
```

After restart, ask Claude:

> "Use millimetric.top\_sources to show me the Facebook social-vs-paid split for the last 7 days."

## Connecting from MCP Inspector

```bash
npx @modelcontextprotocol/inspector
# point it at http://localhost:8787/mcp
# add an Authorization header: Bearer rk_live_…
```

You'll see the tools and resources listed and can call them interactively.

## Why MCP?

For AI-native products, telemetry is two-way: the agent does work and the agent answers questions about the work. Both sides talk to the same analytics surface, on the same protocol, with no SDK to bundle.

For non-AI products, MCP is still useful — it's a clean way to give a read-only consumer access to the data without exposing the database, and the same JSON-RPC handler can be wrapped in any UI you care to build.

## Response shape

Tool results return as MCP `content[]`:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      { "type": "text", "text": "[{\"source\":\"facebook\",\"medium\":\"paid\",\"events\":6,...}]" }
    ]
  }
}
```

The `text` is JSON-stringified — agents parse it back to data. (MCP doesn't yet have a first-class structured-result type for tools.)

## Errors

Standard JSON-RPC error envelope:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": { "code": -32000, "message": "insufficient_scope",
             "data": { "required": "ingest", "got": "read" } }
}
```

| Code   | Meaning                                                                 |
| ------ | ----------------------------------------------------------------------- |
| -32600 | invalid\_request — body not a valid JSON-RPC envelope.                  |
| -32601 | method\_not\_found — unknown method.                                    |
| -32602 | unknown\_tool / unknown\_resource / unhandled\_tool.                    |
| -32000 | tool\_failed (server error) / insufficient\_scope.                      |
| -32002 | plan\_limit — feature requires a higher tier (e.g. account-MCP on Pro). |
| -32004 | unknown\_project\_id / unknown\_project\_slug — account-MCP only.       |
| -32005 | no\_projects\_visible — account-MCP only.                               |

## Account MCP

`/mcp/account` is the multi-project endpoint. One `ak_live_…` key authenticates an agent against every project in the account — built for agencies and teams running multiple products on one Millimetric workspace.

It speaks the same JSON-RPC dialect as `/mcp`, so any MCP client can talk to both with the same code path. The only differences are:

* **Auth**: `ak_` keys only. `pk_/sk_/rk_` are rejected with `403 account_key_required`.
* **Plan**: Business tier (`account_mcp_access`). Pro accounts get `402` with `error: "plan_limit"`.
* **Tools**: every read tool gains optional `project_id` / `project_slug` / `project_ids` arguments. Omit them and the query spans every project the key can see.

### Tools

#### `list_projects`

Returns every project the key can read.

```json
{ "name": "list_projects", "arguments": {} }
```

#### `query_events` (multi-project)

```json
{
  "name": "query_events",
  "arguments": {
    "from": "2026-05-01T00:00:00Z",
    "to":   "2026-05-17T00:00:00Z",
    "project_slug": "acme-storefront",
    "limit": 50
  }
}
```

Omit `project_slug` / `project_id` / `project_ids` to scan every project. Rows include a `project_id` column when the query spans more than one so the agent can attribute them.

#### `get_stats` (group by project)

```json
{
  "name": "get_stats",
  "arguments": {
    "metric": "count",
    "from": "2026-05-10T00:00:00Z",
    "to":   "2026-05-17T00:00:00Z",
    "group_by": "project_id,source"
  }
}
```

#### `top_sources`

Same shape as `/mcp`, plus the optional project-selection args.

#### `compare_projects`

Ranks every project the key can see by a single metric — perfect for "which app had the most traffic this week?".

```json
{
  "name": "compare_projects",
  "arguments": {
    "from": "2026-05-10T00:00:00Z",
    "to":   "2026-05-17T00:00:00Z",
    "metric": "uniques"
  }
}
```

Returns one row per project, decorated with `slug` and `name`.

### Resources

* **`projects://all`** — every project the key can read.
* **`schema://events`** — distinct event names from the last 30 days **across every accessible project**.

### Connecting from Claude Code

```json
{
  "mcpServers": {
    "millimetric-account": {
      "url": "https://api.millimetric.ai/mcp/account",
      "transport": "http",
      "headers": {
        "Authorization": "Bearer ak_live_…"
      }
    }
  }
}
```

Then:

> "Use millimetric-account.compare\_projects to rank my apps by unique visitors over the last 7 days."


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.millimetric.ai/mcp-for-ai-agents/overview.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
