> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fixaeo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools reference

> All fourteen FixAEO MCP tools, their parameters, and what they return.

Every tool is a read. None of them write, and all of them are scoped to the account the API key belongs to.

## Conventions

A few things hold across the whole surface, so they're stated once here.

**`slug`** is a brand's `brand_slug`, from `list_brands`. Call that first.

**`range`** accepts `7d`, `30d`, or `90d`, and `365d` also resolves. Anything else, including an empty value, falls back to 30 days.

**`region`** is a lowercase ISO 3166-1 alpha-2 country code — `us`, `gb`, `de`, `in`. See [Managing brands](/managing-brands) for how a brand's scan region is set.

**Engine slugs** are `chatgpt`, `claude`, `gemini`, `perplexity`, `copilot`, `deepseek`, `grok`, `ai_overviews`, and `ai_mode`. Your plan decides which of them are actually scanned, so a filter on an engine you don't scan returns nothing.

<Note>
  Five tools take no brand parameter and read your newest brand: `list_citations`, `list_topics`, `get_model_channels`, `get_industry_metrics`, and `get_industry_gap`. If you track more than one brand and the numbers look like the wrong company, that's why. Use `get_visibility` and `list_mentions`, which take a slug, when you need a specific brand. The REST twins accept a `brand_slug` parameter to pick another brand; the MCP tools don't expose it.
</Note>

Each tool below names the REST endpoint it mirrors. Those endpoints live under the [Customer API](/api/introduction) tab and return byte-identical JSON.

## Account-level tools

### list\_brands

Which brands does this account track, and what are their slugs?

No parameters.

Returns `brands` — one record per tracked brand with `id`, `brand_slug`, `brand_name`, `domain`, `vertical`, `site_id`, `scan_frequency_hours`, `next_scan_at`, and `added_at` — plus `count` and your plan's brand `limit`. Newest brand first. Mirrors `GET /api/public/v1/brands`.

<Note>
  No visibility numbers here — this is the brand record only. For scores call `get_visibility` with the slug, or `get_model_channels` for the per-engine split.
</Note>

### get\_portfolio

How is every brand in the account doing, side by side?

| Parameter | Type   | Required | Notes                                |
| --------- | ------ | -------- | ------------------------------------ |
| `range`   | string | No       | Defaults to 30 days                  |
| `region`  | string | No       | Defaults to `us`, with language `en` |

Returns `totals`: brand count, brands with data, average visibility and its delta (both percentage points), total mentions and responses, and the sentiment split. Then `top` and `bottom` — your five best and five worst brands, ordered to match the percentages the app prints — plus `per_engine` averages across the portfolio. A `brands` array carries each brand's latest snapshot, and `regions` lists the locales your brands are tracked in. Brands with no snapshot yet appear with `has_data: false`. Mirrors `GET /api/public/v1/portfolio`.

<Note>
  `totals.avg_citation_rate` and `totals.avg_citation_delta` are both in percentage points, and both are weighted by how much data each brand has. A brand with far more responses moves them further, so neither is a plain average across brands.
</Note>

### list\_citations

Which sources do AI engines cite when they answer questions in your space?

| Parameter | Type   | Required | Notes                                         |
| --------- | ------ | -------- | --------------------------------------------- |
| `range`   | string | No       | Defaults to 30 days                           |
| `region`  | string | No       | Bare region code, such as `us`                |
| `engines` | string | No       | Comma-separated, such as `chatgpt,perplexity` |
| `q`       | string | No       | Substring match on the domain, lowercase      |

Returns `domains`, ranked by citation count, each with `rank`, `domain`, `count`, `share`, `category`, the `engines` that cited it, `latest_date`, `is_owned`, `is_competitor`, and — when FixAEO has them — domain authority, top content type, sentiment counts, and a seven-day `series_7d` sparkline. Alongside that: `total_citations`, `categories`, `bucket_counts`, a `time_series`, the available engine and region facets, and `rank`, which is your own highest-placed domain and its position (`0` when you're not cited at all). Mirrors `GET /api/public/v1/citations`.

<Note>
  `q` matches the domain string only, not full URLs. Searching for a path or a page title returns nothing.
</Note>

### list\_topics

Which themes do your tracked prompts cluster into?

No parameters.

Returns `themes` — each with `theme`, `count`, and a `tier` of 20, 30, 50, or 70 that drives the size of the chip in the app — plus `total_keywords`. Scoped to your newest brand. Mirrors `GET /api/public/v1/topics`. Background on how clusters are built is in [Topics and labels](/topics-and-labels).

### get\_model\_channels

Which engines mention you most, and which ignore you?

No parameters.

Returns `engines`, one row per engine with `engine`, `score`, and `delta`, plus a fixed `range` of `30d`. `delta` is the movement across that window. Mirrors `GET /api/public/v1/model`.

<Note>
  `score` here runs from 0 to 100. The `citation_rate` in `get_visibility` is a fraction from 0 to 1. Convert before you compare the two.
</Note>

### get\_industry\_metrics

Where do you sit against competitors, and who's gaining?

| Parameter | Type   | Required | Notes                                  |
| --------- | ------ | -------- | -------------------------------------- |
| `range`   | string | No       | Defaults to 30 days                    |
| `engine`  | string | No       | One engine slug, not a list            |
| `region`  | string | No       | Defaults to the brand's primary region |

Returns `ranking`: every brand mentioned in your space, with `name`, `mentions`, `share` as a percentage, `delta` in percentage points, `is_own`, `is_pinned`, and a `sentiment` split. Alongside it, a daily `time_series` carries per-competitor counts. An `own` block gives your total mentions, total responses, and average position. You also get `tracked_competitors`, `last_refreshed`, and a `methodology` block that spells out the denominator and the share formula. Mirrors `GET /api/public/v1/industry/metrics`. See [Industry benchmarks](/industry) for how to read it.

### get\_industry\_gap

Which sites cite your competitors but never you?

| Parameter | Type   | Required | Notes                   |
| --------- | ------ | -------- | ----------------------- |
| `range`   | string | No       | Defaults to 30 days     |
| `region`  | string | No       | Empty means all regions |

Returns up to 50 `gaps`, each with `domain`, `citations`, `competitor_chats`, `distinct_competitors`, the `competitors` named, the `engines` involved, a `gap_score`, and `latest_date`. Your own domains are excluded, as are the websites of competitors you pinned yourself. Mirrors `GET /api/public/v1/industry/gap`.

<Note>
  Pinning a competitor puts its domain on file, which is what lets the gap list exclude it. Pin the rivals you care about and the results get sharper. See [Competitors](/competitors).
</Note>

## Brand-scoped tools

### get\_brand

What's on file for one brand?

| Parameter | Type   | Required | Notes              |
| --------- | ------ | -------- | ------------------ |
| `slug`    | string | Yes      | From `list_brands` |

Returns a single `brand` object with the same fields one `list_brands` row carries. It's the brand record, not a scorecard — there are no scores in this response. Errors with "brand not found" when the slug isn't one of yours. Mirrors `GET /api/public/v1/brands/{slug}`.

### get\_visibility

How has this brand's visibility moved over time?

| Parameter | Type   | Required | Notes               |
| --------- | ------ | -------- | ------------------- |
| `slug`    | string | Yes      | From `list_brands`  |
| `range`   | string | No       | Defaults to 30 days |

Returns `snapshots`, one row per day, each with `date`, `citation_rate`, `brand_mentions`, `total_responses`, the sentiment split, `per_engine` rates, a `ranking` map, `ranking_per_engine`, and `sentiment_per_competitor`. The window is echoed back as `range`, `from`, and `to`. A brand with no scans yet returns an empty array, not an error. Mirrors `GET /api/public/v1/brands/{slug}/snapshots`.

<Tip>
  `citation_rate` is a 0..1 fraction. The app derives the headline percentage from the counts instead — `brand_mentions / total_responses × 100` — so do the same if you want a number that matches the dashboard. [Visibility score](/metrics/visibility-score) explains why.
</Tip>

There's no region parameter here. The tool reads the brand's primary active region, which is the same scope the dashboard uses.

### list\_mentions

Which answers actually named this brand?

| Parameter   | Type   | Required | Notes                                |
| ----------- | ------ | -------- | ------------------------------------ |
| `slug`      | string | Yes      | From `list_brands`                   |
| `sentiment` | string | No       | `pos`, `neu`, or `neg`               |
| `region`    | string | No       | Overrides the brand's primary region |

Returns up to 100 `mentions`, newest first, each with `id`, `engine`, `date`, `sentiment`, `confidence`, the `prompt` that produced it, a `snippet` of the answer, and `source_url` when the engine cited one. Any `sentiment` value outside the three listed is rejected as an error rather than ignored. Mirrors `GET /api/public/v1/brands/{slug}/mentions`. [Understanding answers](/understanding-answers) covers how these are classified.

### list\_prompts

What is FixAEO asking on this brand's behalf?

| Parameter | Type   | Required | Notes              |
| --------- | ------ | -------- | ------------------ |
| `slug`    | string | Yes      | From `list_brands` |

Returns `prompts` with `id`, `prompt_text`, `is_active`, `intent` (informational, commercial, or transactional), `created_at`, `last_snapshot_date`, and — for prompts accepted from a Search Console suggestion — `source` and `source_query`. Also `count` for this brand, `used_total` across the whole account, and your plan `limit`. The prompt pool is shared account-wide, which is why the last two differ. Mirrors `GET /api/public/v1/brands/{slug}/prompts`.

<Note>
  There's no per-prompt visibility figure in this response. `last_snapshot_date` tells you when a prompt was last scanned; use `list_mentions` to see which answers named you.
</Note>

## Integration-dependent tools

All fourteen tools appear in your client's list on `api.fixaeo.com`. These last three still need a per-brand integration to have anything to return. Without one they answer with an empty result rather than an error, which reads as "no data" instead of "not connected".

### get\_search\_performance

How does this brand do on Google organic search?

| Parameter | Type   | Required | Notes              |
| --------- | ------ | -------- | ------------------ |
| `slug`    | string | Yes      | From `list_brands` |

Returns a daily `metrics` series with `clicks`, `impressions`, `ctr`, and `position`, window `totals` where position is impression-weighted, the top 25 `top_queries` and `top_pages`, and up to 25 `countries` with their click share. The window is fixed at 30 days — this tool takes no range. Needs [Google Search Console](/integrations/google-search-console) connected for that brand; without it you get an empty series rather than an error. Mirrors `GET /api/public/v1/brands/{slug}/search-performance`.

### get\_seo\_aeo\_gap

Which Google queries do you rank for but get no AI mentions on?

| Parameter | Type   | Required | Notes              |
| --------- | ------ | -------- | ------------------ |
| `slug`    | string | Yes      | From `list_brands` |

Takes your top 50 organic queries by clicks over the last 30 days and classifies each one. Returns `rows` with `query`, `seo_clicks`, `seo_impressions`, `seo_position`, `matched_prompt_id`, `gap_score`, and `ai_state`, which is one of:

| `ai_state`          | Meaning                                            |
| ------------------- | -------------------------------------------------- |
| `untracked`         | No tracked prompt matches this query               |
| `tracked_cited`     | A prompt matches, and AI engines mention you       |
| `tracked_not_cited` | A prompt matches, and AI engines don't mention you |

Rows come back sorted by `gap_score`, highest first, so the biggest opportunity is at the top. Needs Search Console connected. This one has no REST twin — it's only on MCP and on the app's [Search performance](/seo) page.

### get\_agent\_traffic

Which AI crawlers are visiting the site, and what are they reading?

| Parameter | Type   | Required | Notes              |
| --------- | ------ | -------- | ------------------ |
| `slug`    | string | Yes      | From `list_brands` |

Returns a 30-day view. `totals` covers `hits`, `unique_visitors`, `active_bots`, pages crawled, and a `failure_rate`. Breakdowns arrive as `by_bot`, `by_vendor`, `by_kind`, `by_folder`, `by_country`, and `by_status`, with `per_engine_hits` beside them. You also get `top_page` — the single most-crawled URL — `series_by_bot` trend lines, and `previous` for the prior equal-length window. `channels` splits hits between the JavaScript tag and server-log ingestion. Needs the tracking tag or a server-log connector; see [Agent analytics](/agent-analytics). Mirrors `GET /api/public/v1/brands/{slug}/agents`.

## Related pages

* [Use cases](/mcp/use-cases) — questions that map onto these tools
* [Setup](/mcp/setup) — client configuration and troubleshooting
* [Metrics overview](/metrics-overview) — what each returned field means
