# Tools

Source: https://docs.mirafive.io/mcp/tools

> Every tool of the MIRA FIVE MCP server, with its arguments, what it returns, and which ones write.

The MIRA FIVE MCP server offers 41 tools: 29 for every account, and 12 for feature flags and experiments. Most only read. The setup tools write, and only with **May change setup** on the connection (see [Permissions](https://docs.mirafive.io/mcp#permissions)). An agent learns all of this from the server itself; this page is the reference for you.

The flag and experiment tools only appear when feature flags are enabled for one of your organizations.

## Shared behaviour

### Projects

Almost every tool takes `project_id`: the UUID `list_projects` returns, never a name or a slug. An unknown id, or a project outside your organizations, answers `No project with that id is yours to see. Call list_projects for the ids you can use.`

### Periods

Tools that report over time take the same three arguments:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `period` | string | no | `1h`, `24h`, `7d`, `30d`, `90d` or `12m`, ending now, in the project's timezone. Default `30d`. Ignored when `from` and `to` are given. |
| `from` | string | no | First day of a custom range, `YYYY-MM-DD`. Needs `to`. |
| `to` | string | no | Last day, inclusive. Needs `from`. |

The same rules as the [REST API](https://docs.mirafive.io/rest-api#periods) apply: a range reaching back past what the plan keeps is shortened, and a range with no day inside it is refused. Answers carry `period`: `from`, `to` (exclusive), `timezone`, `label`, `clampedToRetention`, and on tools that compare, `comparison` (`null` when there is no previous period to show).

### Filters

Report tools take `filters`: up to 20 objects `{ "field", "op", "value" }`, all of which must hold. Fields, operators and values are those of the [REST API filters](https://docs.mirafive.io/rest-api#filters). `value` is always a string, also for `gt` and `lt` (`"49"`), and is left out for `set` and `not_set`. `list_people` takes person filters instead, as in the [People list](https://docs.mirafive.io/rest-api/people#person-filters).

### Answers and errors

A successful call returns structured content that matches the tool's output schema. Revenue stays per currency and is never added across currencies. Ratios are 0–1.

A failed call is a tool result with `isError: true` and a message the agent can act on, never a protocol error:

| Message | Cause |
| --- | --- |
| `project_id: project_id is required: the id of a project from list_projects.` | A required argument is missing. Each validation message starts with the argument it is about. |
| `This tool does not take X. It takes: …` | An argument the tool does not know. Tools accept no extra arguments. |
| `This connection may read but not change setup. …` | A setup tool without **May change setup**. The message names the switch and where to turn it on. |
| `That question reads more data than one call may. Ask over a shorter period or with filters.` | The question passed the read budget. |
| `MIRA FIVE’s analytics store did not answer. Try again in a minute.` | The warehouse did not answer. |
| `Too many setup changes in a minute. Try again in N seconds.` | More than 30 setup calls in a minute. |

### Setup tools

Setup tools are idempotent by name or key: asking again for what is already there changes nothing. Every setup answer has `change`: `created`, `updated` or `unchanged`. A retry after a timeout is safe.

Markers below: **Read-only** tools never change anything. **Writes** tools need **May change setup** and a role that allows the change. **Writes, destructive** tools can change what existing reports or live traffic show.

## Account and projects

### whoami

Whose account the connection acts as, how it signed in, and the organizations it reaches. **Read-only.**

Takes no arguments.

Returns `account` (`name`, `email`), `credential` (`kind`: `oauth_app` or `api_key`, `name`, `mayChangeSetup`, `mayChangeLiveFlags`; `null` without an agent credential) and `organizations` (`name`, `slug`, `role`).

### list_projects

The projects you may work in, across your organizations. Start here. **Read-only.**

Takes no arguments.

Returns `organizations` (`slug`, `name`, `role`, `plan`, `retentionDays`, `canCreateProjects`) and `projects` (`id`, `name`, `organization` slug, `timezone`, `currency`, `url`, `archived`, `sources`, `lastEventAt`).

### project_overview

One project at a glance, as its Overview shows it. The first call for a project the agent has not seen. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `filters` | array | no | See [Filters](#filters). |

Returns `project`, `period` (with `comparison`), `availability` (`ready`, `consentless_only` or `no_sources`), `sources` (each with `status`: `waiting`, `receiving`, `silent` or `archived`), `waitingForFirstEvent`, `numbers` (key numbers with `previous`), `comparedWith`, `coverage`, `channels` (up to 8), `campaigns` (up to 5), `pages` (up to 10), `events` (up to 10), `goals`, `search` (Google Search Console), `bingSearch` (Bing Webmaster Tools, counted its own way, never to be added to `search`), `ads`, `highIntent` (up to 5 people) and `nextStep` (what to do before numbers can exist).

## People

### list_people

The people of a project, as the People list shows them, 50 at a time. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `view` | string | no | `everyone` (default), `customers`, `known` or `high-intent`. |
| `segment_id` | string | no | Only the people of a saved segment (`list_segments`). |
| `filters` | array | no | Up to 12 person filters: `stage`, `first_channel`, `last_channel`, `first_campaign`, `last_campaign`, `first_landing`, `last_landing`, `first_ad_platform`, `last_ad_platform`, `country`, `device`, `goal`, `action`, `segment`, `funnel`. |
| `sort` | string | no | `last_seen` (default), `first_seen`, `value` or `visits`. |
| `new_only` | boolean | no | Only people first seen in the period. |
| `all_time` | boolean | no | Everyone with retained history instead of the period. Slower. |
| `cursor` | string | no | `nextCursor` of the previous page, with the same other arguments. |

Returns `project`, `period`, `availability`, `total` (on the first page only), `coverage`, `people` (`ref`, `name`, `known`, `stage`, `firstTouch`, `firstSeen`, `lastSeen`, `visits`, `value` per currency, `country`, `device`, `lastPath`, `url`) and `nextCursor`.

### find_person

Finds people by what you already hold. A lookup, not a list. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `query` | string | yes | 2–200 characters: a user id or browser id (exact), or part of an email or name. |

Returns `matches`: up to 8, most recently active first, each with `ref`, `name`, `detail` (the email, or the id that matched), `known`, `stage`, `lastSeen` and `url`.

### get_person

One person over their whole retained history, as their page in MIRA FIVE shows them. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `ref` | string | yes | The person's ref, from `list_people` or `find_person`. |

Returns `ref` (current; it changes when a browser signs in), `url`, `profile` (name, email, user id, stage, counts, revenue per currency, first touch, client, traits), `journey` (visits, the channel of each of the latest 30, purchases, last touch), `intent` (key pages, visits this week, searches, lifecycle, goals reached), `signals` and `recentVisits`.

### list_segments

The saved segments of a project, with their rules in words and their size now. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |

Returns `project` and `segments`: `id`, `name`, `description`, `kind` (`rules` or `list`), `definition`, `summary` and `people` in it now.

## Reports

### journeys

How people move through the site, as the Journeys screens show it. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `report` | string | yes | `pages`, `map`, `flows`, `paths`, `transitions` or `conversions`. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `filters` | array | no | See [Filters](#filters). |
| `around` | string | no | `flows` only: the page path to centre on, e.g. `/checkout`. Defaults to the busiest page. At most 2,048 characters. |

Returns `project`, `period`, `report`, `availability`, `coverage` and `data` (the report's rows or paths, at most 25, and its totals). `map`, `flows`, `paths` and `conversions` follow visits and are `null` without consented traffic.

### acquisition

Where people come from, as the Acquisition screens show it. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `report` | string | yes | `channels`, `campaigns` or `landing_pages`. |
| `attribution` | string | no | `first` (default) or `last` touch. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `filters` | array | no | See [Filters](#filters). |

Returns `project`, `period`, `report`, `attribution`, `availability`, `rows` (at most 25, busiest first, with visits and `people`: people, new people, buyers, conversion) and `coverage`.

### search_performance

How the site shows up in a search engine: Google from the Search Console import, or Bing from Bing Webmaster Tools. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). Filters do not apply. |
| `engine` | string | no | `google` (the default) or `bing`. |

Returns `project`, `engine`, `period` (with `comparison`), `status` (`state` and `reconnect`), `totals` (clicks, impressions, ctr and position, each with `value` and `previous`, and `through`, the last day the engine published), `queries` and `pages` (top 25 each), `weeks` and `brand` (brand queries against the rest, and what Google withheld). The numbers are `null` until the engine is imported. Engines count differently, so never add them up.

Bing's totals count every Bing surface, Copilot included, and its position comes from its pages. Its queries and pages are web search alone, its top ones only, and come a week at a time: `weeks` names the weeks counted (`from`, `to`, `count`), those whose last day falls in the period, and is `null` for Google. Bing's query rows are its top queries alone, so what it left out cannot be told apart: `brand.withheld` is `null` for Bing.

### ads_performance

Google Ads and Meta Ads spend beside what the site saw from it, per campaign. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `attribution` | string | no | `last` (default) credits a purchase to the latest paid click before it; `first` to the click that first brought the buyer. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). Read in whole days, and from the site's first event at the earliest. |
| `filters` | array | no | Event filters on the site's side (visits, buyers, revenue). The platforms' numbers are not filtered. |

Returns `project`, `period`, `attribution`, `status` per platform, `totals` (spend and revenue per currency, impressions, clicks, conversions, visits, buyers, ROAS per currency), `platforms`, `campaigns` (up to 25, with cost per visit, cost per buyer and ROAS), `tracking` (how many paid visits joined a campaign, and `issues` such as `untagged` or `unknown_campaign`), `revenueTracked` and `coverage`.

## Goals, funnels and events

### list_goals

What a project counts as success, and how often it happened. Also its plain actions and saved funnels. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |

Returns `project`, `period`, `perVisit`, `coverage`, `goals` (`id`, `name`, `role`, `revenueProperty`, `definition`, `summary`, conversions, people, rate, revenue per currency), `actions` (without a role) and `funnels` (steps, window, basis).

### goal_report

One goal in depth, as its page shows it. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `goal_id` | string | yes | The goal, from `list_goals`. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |

Returns `project`, `period` (with `comparison`), `goal`, `totals` (conversions, people, active, visits, rate, revenue, coverage, `previous`), `conversionsPerBucket`, `conversionTime` (median seconds from first visit), `channels` (first touch) and `people` (the latest ten who reached it; `null` if you may not see people).

### run_funnel

How many reached each step of an ordered journey, and where they dropped off. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `funnel_id` | string | no | A saved funnel from `list_goals`. Or give `steps`. |
| `steps` | array | no | 2–6 action or goal ids, in order, when there is no `funnel_id`. |
| `window` | integer | no | Days from the first step within which the others count: `1`, `7` (default), `14` or `30`. |
| `basis` | string | no | `person` (default) follows people across visits; `visit` counts within one visit. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `filters` | array | no | See [Filters](#filters). |

Returns `project`, `period`, `definition`, `report` (`steps`: `id`, `name`, `count`, `conversion` of the first step, `dropoff` since the step before) and `note`.

### list_events

A project's vocabulary: the event names it collected, their custom properties, and the fields every event has. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `event_name` | string | no | Only the properties this event carried. At most 128 characters. |

Returns `project`, `period`, `events` (names with counts, at most 100), `properties` (keys as filter fields, e.g. `properties.plan`, with how many recent events carried each; sampled) and `fields`.

### event_feed

The latest events a project received, newest first, as **Data → Live** shows them. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `period` | string | no | `1h`, `24h` (default) or `7d`, ending now. No `from` or `to`. |
| `filters` | array | no | See [Filters](#filters). |
| `limit` | integer | no | Events per page, 1–50. Default 25. |
| `cursor` | string | no | `nextCursor` of the previous page, with the same other arguments. |

Returns `project`, `period`, `events` (`id`, `at`, `name`, `kind`, `label`, `path`, `host`, `title`, `country`, `device`, `browser`, `referrer`, `sourceType`, `consented`, `visit`, `revenue`, `person`) and `nextCursor`.

## Insights and dashboards

### list_insights

The questions somebody at the business saved, with their definitions and the dashboards they sit on. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |

Returns `project` and `insights`: `id`, `name`, `description`, `kind`, `definition`, `needsRepair`, `url` and the dashboards showing it.

### run_insight

Answers a question over a period with the same runner as the dashboard, so the numbers match. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `insight_id` | string | no | A saved insight. Or give `definition`. |
| `definition` | object | no | A question to ask without saving it. See below. |
| `period`, `from`, `to` | string | no | See [Periods](#periods). |
| `compare` | boolean | no | For a trend, also the series of the period before. A number always carries its previous value. |
| `filters` | array | no | Filters laid over the insight's own. |

`definition`:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | string | yes | `trend` (a series per bucket), `number` (one total against the period before), `breakdown` (split by one or two fields) or `funnel`. |
| `measure.metric` | string | yes, except for a funnel | `events`, `pageviews`, `visits`, `people`, `conversion_rate` (needs `action`) or `revenue` (needs `currency`). |
| `measure.action` | string | no | Count only this action's or goal's events. |
| `measure.currency` | string | no | For revenue: the one currency to add up, e.g. `EUR`. |
| `breakdowns` | array | no | `breakdown` only: up to 2 fields, e.g. `utm_source`, `country`, `properties.plan`. |
| `filters` | array | no | Up to 20 event filters every counted event meets. |
| `segment` | string | no | Only the people of this saved segment. |
| `funnel` | object | no | `funnel` only: `steps` (2–6 action or goal ids), `window` (`1`, `7`, `14` or `30`) and `basis` (`person` or `visit`), all required. |

Returns `project`, `period` (with `comparison`), `insight`, `definition` and `result`: `kind`, `format`, `currency`, then `number` (value, previous), `trend` (series of `t`/`v` points), `breakdown` (rows) or `funnel` (steps), plus `otherCurrencies`, `coverage`, `countsPeople`, `incomplete` and `empty`.

### list_dashboards

A project's dashboards and their tiles in reading order. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |

Returns `project`, `dashboards` (`id`, `name`, `description`, `url`, `tiles`: an insight or a built-in report, and `width`) and `builtinTiles`.

## Setup

Every tool in this group needs **May change setup**. See [Setup tools](#setup-tools) for idempotency.

### create_project

Creates a project. A project of the same name in that organization is returned as it is. **Writes.** Needs a role that may create projects (owner or admin).

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organization` | string | no | The organization's slug (`list_projects`). Needed when you may create projects in more than one. |
| `name` | string | yes | At most 120 characters, e.g. `Nordlicht Shop`. |
| `timezone` | string | no | An IANA timezone, e.g. `Europe/Berlin`. Default `UTC`. |
| `reporting_currency` | string | no | `EUR` (default), `USD`, `GBP` or `CHF`. |

Returns `change`, `project` (`id`, `name`, `organization`, `timezone`, `currency`, `url`) and `next`.

### setup_source

Connects where a project's events come from and issues its first key (a website key or a secret key) with the snippet to install. **Writes.** Needs a role that may manage sources (owner or admin).

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `type` | string | yes | `web` for a website, `server` for a backend. |
| `name` | string | yes | At most 120 characters, e.g. the site's domain or `Backend`. |
| `allowed_origins` | array | no | `web` only: up to 50 origins, e.g. `["https://shop.nordlicht.example"]`. |
| `collection_mode` | string | no | `web` only: `consentless` (default) or `full`. See [Consent](https://docs.mirafive.io/guides/consent). |

Returns `change`, `source` (`id`, `name`, `type`, `allowedOrigins`, `collectionMode`, `url`), `key`, `install` (for `web`: where, the tag, and the consent call for full mode; for `server`: install, env and code) and `next`. A server source's secret key is returned only when the source is created.

### create_action

Names an event that matters, so reports can say "Signed up" instead of a raw event. It counts history too. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `name` | string | yes | At most 80 characters, e.g. `Viewed pricing`. |
| `description` | string | no | At most 500 characters. |
| `definition` | object | yes | `events` (1–10 event names, any of which counts), `conditions` (up to 20 filters) and `match` (`all`, the default, or `any` of the conditions). |

Returns `change` and `action` (`id`, `name`, `definition`, `summary`, `url`).

### update_action

Renames an action or goal, changes what it counts, or where a goal reads its revenue. Every report reads the new definition from then on, history included. **Writes, destructive.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `action_id` | string | yes | The action or goal (`list_goals`). |
| `name` | string | no | At most 80 characters. |
| `description` | string | no | At most 500 characters. |
| `definition` | object | no | As in `create_action`. |
| `revenue_property` | string or null | no | Goals only: the event property that carries the amount when an event sends no `revenue`, e.g. `value`. Past revenue is re-read within a minute or two. |

Returns `change` and `action`. A goal keeps its role.

### create_goal

Names an outcome the business counts: `purchase`, `conversion` or `intent`. It counts history too. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `role` | string | yes | `purchase` (one per project; decides who is a customer), `conversion` or `intent`. |
| `name` | string | no | At most 80 characters, e.g. `Order completed`. Needed with `definition`. |
| `description` | string | no | At most 500 characters. |
| `definition` | object | no | As in `create_action`. Or give `action_id`. |
| `action_id` | string | no | An existing action to make a goal, instead of `name` and `definition`. |
| `revenue_property` | string or null | no | As in `update_action`. |

Returns `change` and `goal` (`id`, `name`, `role`, `revenueProperty`, `definition`, `summary`, `url`). A goal's role is changed in MIRA FIVE, not here.

### create_funnel

Saves an ordered journey, so it opens on the Funnel screen and runs with `run_funnel`. The same name for other steps is refused. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `name` | string | yes | At most 80 characters, e.g. `Product to purchase`. |
| `steps` | array | yes | 2–6 action or goal ids, in order. |
| `window` | integer | no | `1`, `7` (default), `14` or `30` days. |
| `basis` | string | no | `person` (default) or `visit`. |

Returns `change` and `funnel` (`id`, `name`, `definition`, `url`).

### create_segment

Saves a group of people by rules. Membership is worked out when asked, so it stays current. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `name` | string | yes | At most 80 characters, e.g. `Signed up, not bought`. |
| `description` | string | no | At most 500 characters. |
| `definition` | object | yes | `match` (`all` or `any`) and `rules` (1–10). |

Each rule has `kind`: `did` or `did_not` (an `action` id, or a raw `event` name; with `frequency` `at_least` or `at_most`, `times` 1–1,000, and `within_days` 1–730), or `person` (a `field`: `stage`, `first_channel`, `last_channel`, `country`, `device` or `traits.<key>`, with `op` and `value`).

Returns `change` and `segment` (`id`, `name`, `definition`, `summary`, `url`).

### create_insight

Saves a question for dashboards and the insight studio, in the definition `run_insight` takes. The same name for another question is refused. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `name` | string | yes | At most 80 characters, e.g. `Revenue by utm_source`. |
| `description` | string | no | At most 500 characters. |
| `definition` | object | yes | As in [`run_insight`](#run_insight). The period is not saved. |

Returns `change` and `insight` (`id`, `name`, `kind`, `definition`, `url`).

### create_dashboard

Makes a dashboard with its tiles. A dashboard of the same name is returned with any tiles it lacks added. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `name` | string | yes | At most 80 characters, e.g. `Weekly review`. |
| `description` | string | no | At most 500 characters. |
| `tiles` | array | no | 1–24 tiles in reading order, each `insight_id` or `builtin` (`key_numbers`, `search` or `ads`), with an optional `width` (`third`, `half` or `full`). |

Returns `change` and `dashboard` (`id`, `name`, `description`, `url`, `tiles`).

### add_dashboard_tiles

Puts saved insights or built-in reports at the end of a dashboard. A tile the dashboard already has stays where it is. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `dashboard_id` | string | yes | The dashboard (`list_dashboards` or `create_dashboard`). |
| `tiles` | array | yes | As in `create_dashboard`. A dashboard holds at most 24 tiles. |

Returns `change`, `added` (how many tiles were new) and `dashboard`.

## Feature flags

These tools only appear when feature flags are enabled for one of your organizations. See [Feature flags](https://docs.mirafive.io/guides/feature-flags) for how flags work.

### list_flags

A project's feature flags, those that serve first. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `show` | string | no | `in_use` (default), `ready_to_remove` or `archived`. |

Returns `flags` (`id`, `key`, `name`, `kind`, `state`, `summary`, `readIn`, `owner`, `readyToRemove`, `experimentId`, `changedAt`, `url`) and `counts` (`inUse`, `readyToRemove`, `archived`). `state` is `on`, `off`, `always_on` (remote config with one value), `retiring` or `archived`.

### get_flag

One feature flag in full: its definition in the shape `update_flag` takes, and the `version` it asks for. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `flag_id` | string | yes | The flag's id from `list_flags`, not its key. |

Returns `flag` (definition, `version`, `rules`, `state`, …), `serving` (what it serves now and once on, in sentences), `segments` its rules name and how fresh they are, `health` (when each kind of reader last fetched flags, and secret keys a browser used), `changes` (the last 10) and `snippets` (how each runtime reads it).

### explain_flag

What one person gets from a flag, on your servers and in their browser, and why. **Read-only.** Needs a role that may see people.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `flag_id` | string | yes | The flag. |
| `person` | string | no | A person's ref, from `find_person` or `list_people`. Or give `user_id`. |
| `user_id` | string | no | The user id your code signs people in with, e.g. a test user. At most 256 characters. |

Returns `flag`, `runtimes` (for `servers` and `browser`: whether code there reads it, the `variant`, and the `reason`: `STATIC`, `TARGETING_MATCH`, `SPLIT`, `DEFAULT`, `DISABLED` or `ERROR`, with a sentence), `basis` and `notes`. It never returns an identifier.

### create_flag

Creates a feature flag, always off: until someone turns it on, everyone gets its default. A key is never reused, archived flags included. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `key` | string | yes | What code reads it by: 2–64 lower-case letters, digits and hyphens, starting with a letter, e.g. `new-checkout`. Never changes. |
| `name` | string | yes | At most 80 characters. |
| `description` | string or null | no | At most 500 characters. |
| `kind` | string | yes | `boolean` (on/off), `variant` (named variants) or `config` (values the code reads). |
| `value_type` | string | no | `config` only: `text`, `number`, `boolean` or `json`. |
| `lifetime` | string | no | `temporary` (default) or `permanent`. |
| `variants` | array | no | `variant` and `config` only: `{ key, value }` in order. |
| `default_variant` | string | no | Served while off and to whoever no rule gives anything. On/off flags: `off`. |
| `rules` | array | yes | Who gets what once on, first match wins: `{"x": "<variant>"}`, or a share `{"sh": 1000, "w": [["on", 10000]]}` (basis points), each with an optional `"if"` list of trait or segment conditions. |
| `bucket_by` | string | yes | `browser` or `person` (the signed-in user id). |
| `read_in` | string | yes | `website` (values are public), `servers` or `both`. |
| `affects_prices` | boolean | no | It changes prices or offers, which limits the segments its rules may name. |
| `source_ids` | array or null | no | The sources it is served to. Left out: every source of the project. |
| `owner_id` | string | no | A member who owns it. Default: you. |
| `notice_confirmed` | boolean | no | Needed once per project before the first share assigned by browser or by segment: you confirmed that your banner and privacy notice name gradual releases and personalisation. |
| `price_notice_confirmed` | boolean | no | Needed once per project before the first flag that affects prices or offers. |

Returns `change`, `flag`, `snippets` (the code that reads it in each runtime) and `next`.

### update_flag

Changes a feature flag: give its `version` and only what changes. Key, kind and value type never change. On a flag that is on, the change reaches live traffic within about a minute and needs **May turn flags on and off**. **Writes, destructive.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `flag_id` | string | yes | The flag. |
| `version` | integer | yes | The version `get_flag` or the last write gave. If someone saved the flag since, nothing changes. |
| `name`, `description`, `lifetime`, `variants`, `default_variant`, `rules`, `bucket_by`, `read_in`, `affects_prices`, `source_ids`, `owner_id`, `notice_confirmed`, `price_notice_confirmed` | | no | As in `create_flag`. |

Returns `change`, `flag`, `live` (whether the change reached live traffic), `serving` and `propagation`.

### set_flag_state

Turns a feature flag on or off. Off is the kill switch: everyone gets the default. Turning off an experiment's flag ends the experiment. **Writes, destructive.** Always needs **May turn flags on and off**.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `flag_id` | string | yes | The flag. |
| `enabled` | boolean | yes | `true` turns it on, `false` off. |

Returns `change`, `flag`, `state` (`on` or `off`), `reach` (when turned on: whom it reaches and about how many people) and `propagation`.

## Experiments

These tools only appear when feature flags are enabled for one of your organizations. See [Experiments](https://docs.mirafive.io/guides/experiments) for how experiments work.

### list_experiments

A project's experiments, those needing attention first. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `show` | string | no | `active` (default) or `archived`. |

Returns `experiments` (`id`, `key`, `name`, `kind`, `status`, `basis`, `attention`, `people` so far per variant, `dueAt`, `resultLabel`, `archived`, `url`) and `counts`. Counts of 1 to 4 read `"<5"`.

### plan_experiment

What an experiment could find before you create it: the people seen where it is tested, the goal's rate, and for 2, 3, 4, 6 or 8 weeks the smallest change it can detect. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `kind` | string | yes | `page` or `code`. |
| `key` | string | no | `page` with `goal: button`: the key it will have, which names its button. |
| `source_id`, `page_paths`, `anchor`, `affects_prices`, `assign_by`, `read_in`, `counted_in`, `conditions`, `traffic_bp`, `source_ids`, `before_consent`, `goal_id`, `goal`, `window_days`, `planned_weeks` | | no | As in [`create_experiment`](#create_experiment). Where people see it and the deciding goal are needed for an estimate. |

Report filters are not read.

Returns `estimate`, `reason`, `seen` (people over the last 7, 14 and 28 days), `scale`, `baseline` (the goal's rate), `lengths` (per length: `weeks`, `people`, `perVariant`, `detectableRate`, `change`, `allowed`, `chosen`) and `warnings`.

### experiment_report

One experiment where it stands: a draft's install and whether it may start, provisional numbers while counting, or the final result. **Read-only.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `experiment_id` | string | yes | The experiment's id, not its key. |

Returns `experiment`, `summary`, `provisional`, `basis`, `dueAt`, `nextCheckAt` (call again no sooner), `health`, `draft` (install, sightings, whether it may start), `soFar` (provisional numbers per variant and `noise`; never a result), `result` (once final: verdict, headline, the deciding goal's range, buyers, revenue), `decision` and `next`.

### create_experiment

Creates a draft experiment and its flag, off: everyone gets the original (`a`) and nobody is counted until `start_experiment`. A key is never reused. **Writes.**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `key` | string | yes | 2–64 lower-case letters, digits and hyphens, starting with a letter, e.g. `checkout-copy`. |
| `name` | string | yes | At most 80 characters. |
| `description`, `hypothesis` | string or null | no | What you test, and what you expect B to change. |
| `kind` | string | yes | `page` (both variants in one page's HTML, shown by a head snippet) or `code` (your code reads the experiment's flag). |
| `source_id` | string | no | `page` only: the website source. |
| `page_paths` | array | no | `page` only: up to 5 tested paths, e.g. `/pricing` and `/de/preise`. |
| `anchor` | object | no | `code` only: where people see it, as `paths` (up to 5) or an `event`. |
| `values` | object | no | `code` only: the value each variant serves, `{"a": …, "b": …}`. |
| `assign_by` | string | no | `code` only: `browser` (default) or `person`. |
| `read_in` | string | no | `code` only: `website` (default), `servers` or `both`. |
| `counted_in` | string | no | `code` assigned by person only: `browser` or `server`. |
| `conditions` | array | no | `code` only: who is in it, as a flag rule's `if`. |
| `traffic_bp` | integer | no | `code` only: the share of those covered who are in it, 1–10,000 basis points. Default 10,000. |
| `source_ids` | array or null | no | `code` only: the sources it is served to. |
| `before_consent` | string | no | `original` or `random`: what people see before they answer the banner. Needed to start wherever it is read in browsers. |
| `affects_prices` | boolean | no | It changes prices or offers. |
| `goal_id` | string | no | The goal or action that decides it. Never a view of the tested page. |
| `goal` | string | no | `page` only, instead of `goal_id`: `button`, decided by clicks on its own call to action. |
| `window_days` | integer | no | Days after first seeing a variant in which the goal counts: `1`, `7` (default), `14` or `30`. |
| `planned_weeks` | integer | yes | `2`, `3`, `4`, `6` or `8`. Take it from `plan_experiment`. |
| `consent_text_confirmed` | boolean | yes | `true` once you confirmed that your notice covers experiments. |
| `price_notice_confirmed` | boolean | no | Needed once per project before the first experiment that affects prices or offers. |
| `owner_id` | string | no | A member who owns it. Default: you. |

Returns `change`, `experiment`, `acknowledged`, `install` (the page snippet and markup, or the code snippets) and `next`.

### start_experiment

Starts counting. Variants, goal, split and length are then fixed, and a code experiment's flag starts giving people B. Refused, with the reason, until the install is seen. **Writes, destructive.** Needs **May turn flags on and off**.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `experiment_id` | string | yes | The experiment. |
| `consent_text_confirmed` | boolean | no | Only for an experiment created in MIRA FIVE without it. |

Returns `change`, `experiment`, `propagation`, `nextCheckAt` and `next`.

### end_experiment

Ends an experiment early, records its decision, or both. An agent may keep B only with a final result. **Writes, destructive.** Needs **May turn flags on and off** when it changes what people get.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project_id` | string | yes | The project. |
| `experiment_id` | string | yes | The experiment. |
| `end_early` | boolean | no | `true` ends it before its result. Everyone gets the original, and the result can only be "No clear winner". |
| `keep` | string | no | The decision once the result is final or it ended early: `a` (the original) or `b`. `b` with `end_early` is refused. |
| `note` | string | no | Why, in your words. At most 2,000 characters. |
| `audience` | string | no | Code experiments keeping `b`: `covered` (default), `everyone` or `none`. |

Returns `change`, `experiment`, `ended` (`ended_early`, `original_while_waiting` or `null`), `decision`, `live`, `propagation` and `next`.
