# MCP tool reference

The FreshlyCited MCP server at `https://freshlycited.com/mcp` exposes **49 tools**. This page is generated from the server's own tool definitions, so it always matches what your client sees in `tools/list`. API names stay technical: a *push* is an index job, a *visibility check* is an index check.

Every tool works with the permissions of the API key or OAuth connection: tools above your role are listed but return 403. Read-only connections (scope `mcp:read`) can only call read-only tools. Each call counts against your [rate limits](https://freshlycited.com/docs/rate-limits) (60 calls a minute per key; MCP is included on Agency Pro and Scale); tools that spend credits weigh 5 units and ask for `confirm_spend: true` above 1,000 credits.

| Tool | What it does |
| --- | --- |
| [`get_started`](https://freshlycited.com/docs/tools#get_started) | Get started |
| [`whoami`](https://freshlycited.com/docs/tools#whoami) | Who am I |
| [`get_pricing`](https://freshlycited.com/docs/tools#get_pricing) | Pricing and limits |
| [`validate_urls`](https://freshlycited.com/docs/tools#validate_urls) | Validate URLs |
| [`preflight_urls`](https://freshlycited.com/docs/tools#preflight_urls) | Pre-flight URLs before pushing |
| [`submit_index_job`](https://freshlycited.com/docs/tools#submit_index_job) | Push links to Google (index job) |
| [`get_job_status`](https://freshlycited.com/docs/tools#get_job_status) | Get push or check |
| [`list_jobs`](https://freshlycited.com/docs/tools#list_jobs) | List pushes and checks |
| [`list_job_urls`](https://freshlycited.com/docs/tools#list_job_urls) | List a job's links |
| [`update_job`](https://freshlycited.com/docs/tools#update_job) | Rename a job |
| [`cancel_job`](https://freshlycited.com/docs/tools#cancel_job) | Cancel a job |
| [`retry_job`](https://freshlycited.com/docs/tools#retry_job) | Push failed links again |
| [`send_unindexed_to_indexer`](https://freshlycited.com/docs/tools#send_unindexed_to_indexer) | Push the invisible links again |
| [`delete_job`](https://freshlycited.com/docs/tools#delete_job) | Delete a job |
| [`delete_job_url`](https://freshlycited.com/docs/tools#delete_job_url) | Remove one link |
| [`check_index`](https://freshlycited.com/docs/tools#check_index) | Visibility check (index check) |
| [`get_check_results`](https://freshlycited.com/docs/tools#get_check_results) | Stored search results |
| [`share_job_report`](https://freshlycited.com/docs/tools#share_job_report) | Share a client report |
| [`export_job_csv`](https://freshlycited.com/docs/tools#export_job_csv) | Export CSV |
| [`list_indexnow_sites`](https://freshlycited.com/docs/tools#list_indexnow_sites) | List IndexNow sites |
| [`add_indexnow_site`](https://freshlycited.com/docs/tools#add_indexnow_site) | Add a site for IndexNow |
| [`verify_indexnow_site`](https://freshlycited.com/docs/tools#verify_indexnow_site) | Verify an IndexNow site |
| [`update_indexnow_site`](https://freshlycited.com/docs/tools#update_indexnow_site) | Turn a site on/off or move its key file |
| [`delete_indexnow_site`](https://freshlycited.com/docs/tools#delete_indexnow_site) | Remove an IndexNow site |
| [`get_job_indexnow`](https://freshlycited.com/docs/tools#get_job_indexnow) | IndexNow status of a push |
| [`list_tenants`](https://freshlycited.com/docs/tools#list_tenants) | List workspaces |
| [`list_sub_tenants`](https://freshlycited.com/docs/tools#list_sub_tenants) | List direct sub-workspaces |
| [`get_tenant`](https://freshlycited.com/docs/tools#get_tenant) | Get a workspace |
| [`create_sub_tenant`](https://freshlycited.com/docs/tools#create_sub_tenant) | Create a client workspace |
| [`update_tenant`](https://freshlycited.com/docs/tools#update_tenant) | Update a workspace |
| [`delete_tenant`](https://freshlycited.com/docs/tools#delete_tenant) | Delete or archive a workspace |
| [`list_members`](https://freshlycited.com/docs/tools#list_members) | List members |
| [`add_member`](https://freshlycited.com/docs/tools#add_member) | Add a member |
| [`update_member_role`](https://freshlycited.com/docs/tools#update_member_role) | Change a member's role |
| [`remove_member`](https://freshlycited.com/docs/tools#remove_member) | Remove a member |
| [`get_credits`](https://freshlycited.com/docs/tools#get_credits) | Credit balance |
| [`list_ledger`](https://freshlycited.com/docs/tools#list_ledger) | Credit ledger |
| [`allocate_credits`](https://freshlycited.com/docs/tools#allocate_credits) | Give credits to a client |
| [`reverse_ledger_entry`](https://freshlycited.com/docs/tools#reverse_ledger_entry) | Reverse a transfer |
| [`list_api_keys`](https://freshlycited.com/docs/tools#list_api_keys) | List API keys |
| [`create_api_key`](https://freshlycited.com/docs/tools#create_api_key) | Create an API key |
| [`update_api_key`](https://freshlycited.com/docs/tools#update_api_key) | Update an API key |
| [`revoke_api_key`](https://freshlycited.com/docs/tools#revoke_api_key) | Revoke an API key |
| [`delete_api_key`](https://freshlycited.com/docs/tools#delete_api_key) | Delete an API key |
| [`list_users`](https://freshlycited.com/docs/tools#list_users) | List users |
| [`get_user`](https://freshlycited.com/docs/tools#get_user) | Get a user |
| [`list_errors`](https://freshlycited.com/docs/tools#list_errors) | List tracked errors |
| [`resolve_error`](https://freshlycited.com/docs/tools#resolve_error) | Resolve an error |
| [`list_audit_log`](https://freshlycited.com/docs/tools#list_audit_log) | Audit log |

## Getting started

Who you are, what things cost, what to do next.

### `get_started`

**Get started.** Start here. Returns who you are (role, workspace, plan, index and check credit balances), what you've done so far, rate limits, pricing and the next steps that fit this account (first check, smart push, IndexNow setup, sharing a report), with links to the docs.

> Role: any role · read-only · rate weight 1 · idempotent

No parameters.

First call in a new session:

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

### `whoami`

**Who am I.** Identity behind this key or connection: kind (user/apikey), id, workspace (tenantId), role, plan rate limits and, for OAuth connections, the app and scope.

> Role: any role · read-only · rate weight 1 · idempotent

No parameters.

Identity:

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

### `get_pricing`

**Pricing and limits.** Prices and limits. Two credit kinds: index credits (1 per URL pushed, reserved at submission, used only if Google indexes it; not indexed after 7 days → the credit comes back automatically; re-checks on day 1, 3, 7 are free) and check credits (1 per Standard check, 5 per Live check). IndexNow (Bing) submissions are free. Returns pricing (credits per action: { index, priority, check, liveCheck }; the priority lane is not sold yet), the packs and plans in USD, the guarantee rules, URLs per job (Free 50, paid 10,000) and API rate limits.

> Role: any role · read-only · rate weight 1 · idempotent

No parameters.

Pricing:

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

## Pushes (index jobs)

Send links to Google (and to Bing via IndexNow for verified sites), track them, push again.

### `validate_urls`

**Validate URLs.** Validate and de-duplicate a URL list without spending credits. Returns how many are accepted, invalid and duplicated, with up to 10 invalid samples. Use before submit_index_job or check_index when the list came from a user paste or a file.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `urls` | array of string | yes | URLs to validate |

Clean a pasted list:

```json
{
  "name": "validate_urls",
  "arguments": {
    "urls": [
      "https://example.com/blog/new-post",
      "https://example.com/pricing",
      "example.com/no-scheme",
      "https://example.com/blog/new-post"
    ]
  }
}
```

### `preflight_urls`

**Pre-flight URLs before pushing.** Free pre-flight for up to 1,000 URLs: fetches each page (as a crawler would) and flags ones Google can't index at that address: HTTP 4xx/5xx or unreachable, noindex (meta or X-Robots-Tag), blocked by robots.txt for Googlebot, redirects, canonical pointing elsewhere. submit_index_job skips flagged URLs for free by default (push_anyway overrides; then their credit is used). Results are cached for 6 hours, so a push right after reuses them.

> Role: member or higher · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `urls` | array of string | yes |  |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |

Check a list before pushing:

```json
{
  "name": "preflight_urls",
  "arguments": {
    "urls": [
      "https://example.com/blog/new-post",
      "https://example.com/pricing"
    ]
  }
}
```

### `submit_index_job`

**Push links to Google (index job).** Push up to 10,000 URLs so Google crawls them (an "index job"). Each URL reserves 1 index credit, used only if Google indexes it: FreshlyCited re-checks on day 1, 3, 7 (free) and gives the credit back automatically if the link still isn't indexed after day 7. Not covered (credit used): pages that return 404/410/5xx, are noindex, blocked by robots.txt, redirect, have a canonical pointing elsewhere, or that you remove. A free pre-flight runs first and skips flagged URLs (see preflight_urls; response field preflight). Recommended: smart=true checks every URL first (1 check credit/URL) and only pushes the ones Google doesn't show yet; their reserved index credit comes straight back. drip_days spreads the push over 1-30 days. URLs on a site you verified for IndexNow are ALSO sent to Bing and the other IndexNow engines for free (not to Google, ChatGPT or Perplexity); a URL sent to IndexNow in the last 24 h isn't resent unless indexnow_force=true. Returns the job with an outcome headline, credits { index: { reserved, consumed, released, excluded } } and the guarantee's next re-check. Spends credits: calls above the confirmation threshold need confirm_spend=true.

> Role: member or higher · writes · spends credits (rate weight 5)

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `urls` | array of string | yes | Full http(s) URLs, up to 10,000 (Free plan: 50). Duplicates and invalid entries are dropped and reported. |
| `mode` | `standard` | no | Lane. Only standard exists: 1 index credit per link, used only if the link gets indexed (credit back after 7 days if not). A faster priority lane is not available yet. |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `name` | string (≤200 chars) | no | Label shown in lists, emails and client reports |
| `drip_days` | integer (≥0, ≤30) | no | Spread the push over this many days (0 = all now) |
| `recheck_days` | integer (≥0, ≤5) | no | Deprecated, kept for compatibility: re-checks now follow the guarantee schedule (day 1, 3, 7) automatically |
| `pre_check` | boolean | no | Take a 'before' snapshot first (1 check credit/URL); every link is still pushed |
| `smart` | boolean | no | Recommended: check first and only push what Google can't see (their index credit comes back) |
| `preflight` | boolean | no | Run the free pre-flight (default true) |
| `skip_flagged` | boolean | no | Skip URLs the pre-flight flags, for free (default true) |
| `push_anyway` | boolean \| array of string | no | Push flagged URLs anyway (true = all, or a list). They aren't covered by the guarantee: their index credit is used |
| `force_refresh` | boolean | no | Refresh anyway (needs smart=true): links Google already has are sent too and use 1 index credit each when sent. No credit back: we can't see when Google re-crawls a page it already has, so the guarantee doesn't apply. IndexNow pings stay free |
| `indexnow_force` | boolean | no | Resend to IndexNow even if sent in the last 24 h (only when the content changed again) |
| `confirm_spend` | boolean | no | Set true to confirm a call that spends more than the confirmation threshold (default 1,000 credits). Ask the user first. |

Smart push:

```json
{
  "name": "submit_index_job",
  "arguments": {
    "urls": [
      "https://example.com/blog/new-post",
      "https://example.com/pricing"
    ],
    "smart": true,
    "name": "October posts"
  }
}
```

Drip 500 backlinks over 7 days:

```json
{
  "name": "submit_index_job",
  "arguments": {
    "urls": [
      "https://guest-blog.example.net/post-about-you"
    ],
    "drip_days": 7
  }
}
```

### `get_job_status`

**Get push or check.** Full status of one push or visibility check: outcome headline (e.g. '11 of 12 links seen by Google (+2)'), stage, drip progress, before/after comparison, credits (index: reserved / consumed / released / excluded; check credits used), the guarantee's next re-check, pre-flight counts, ledger lines, IndexNow (Bing) summary and the first URLs (each with credit_state). sync=true refreshes crawl status from the network first (cheap, no credits).

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes | Job id (job_…) |
| `url_limit` | integer (≥0, ≤1000) | no | How many URLs to include (default 50) |
| `sync` | boolean | no | Refresh status from the crawl network first |

Status with 10 URLs:

```json
{
  "name": "get_job_status",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "url_limit": 10
  }
}
```

### `list_jobs`

**List pushes and checks.** List pushes (type=index) and visibility checks (type=check) in scope, newest first, each with its outcome and index credits reserved / consumed / released. Paginated: returns { items, total, page, page_size }.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `status` | string | no | Filter: checking, submitting, dripping, queued, processing, approval_pending, completed, partial, failed, cancelled |
| `type` | `index` \| `check` | no |  |
| `page` | integer (≥1, ≤9007199254740991) | no | Page number, 1-based (default 1) |
| `page_size` | integer (≥1, ≤200) | no | Items per page, 1-200 (default 25) |
| `q` | string | no | Free-text search |
| `sort` | string | no | Sort column |
| `dir` | `asc` \| `desc` | no | Sort direction (default desc) |

Last 10 pushes:

```json
{
  "name": "list_jobs",
  "arguments": {
    "type": "index",
    "page_size": 10
  }
}
```

### `list_job_urls`

**List a job's links.** List the links of one push or check with filters: state (pending, queued, completed, failed, skipped, …), indexed (yes = seen by Google, no = invisible, unknown = not checked) and credit (reserved, consumed, released, excluded). Each row includes the latest Google position/title, the guarantee fields (credit_state, sent_at, next_recheck_at, recheck_n, excluded_reason), the pre-flight flag, the IndexNow state and the Bing check result.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `state` | string | no |  |
| `indexed` | `yes` \| `no` \| `unknown` | no |  |
| `credit` | `reserved` \| `consumed` \| `released` \| `excluded` | no |  |
| `page` | integer (≥1, ≤9007199254740991) | no | Page number, 1-based (default 1) |
| `page_size` | integer (≥1, ≤200) | no | Items per page, 1-200 (default 25) |
| `q` | string | no | Free-text search |
| `sort` | string | no | Sort column |
| `dir` | `asc` \| `desc` | no | Sort direction (default desc) |

Links Google still can't see:

```json
{
  "name": "list_job_urls",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "indexed": "no"
  }
}
```

Credits returned:

```json
{
  "name": "list_job_urls",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "credit": "released"
  }
}
```

### `update_job`

**Rename a job.** Rename a push or check. (recheck_days is accepted for compatibility; guarantee re-checks on day 1, 3 and 7 are automatic.)

> Role: member or higher · writes · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `name` | string (≤200 chars) | no |  |
| `recheck_days` | integer (≥0, ≤5) | no |  |

Rename:

```json
{
  "name": "update_job",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "name": "October citations"
  }
}
```

### `cancel_job`

**Cancel a job.** Cancel a running or dripping push/check. Links not sent yet get their index credit back; links already pushed can't be recalled and keep their 7-day guarantee.

> Role: member or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |

Cancel:

```json
{
  "name": "cancel_job",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

### `retry_job`

**Push failed links again.** Re-push a job's failed or cancelled links as a new push (1 index credit reserved per link, same guarantee). Counts as an explicit re-push for IndexNow.

> Role: member or higher · writes · spends credits (rate weight 5)

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `mode` | `standard` | no | Lane. Only standard exists: 1 index credit per link, used only if the link gets indexed (credit back after 7 days if not). A faster priority lane is not available yet. |
| `confirm_spend` | boolean | no | Set true to confirm a call that spends more than the confirmation threshold (default 1,000 credits). Ask the user first. |

Retry:

```json
{
  "name": "retry_job",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

### `send_unindexed_to_indexer`

**Push the invisible links again.** One step: start a new push with only the links Google can't see in this job's latest check (indexed=no). 1 index credit reserved per link, same guarantee. The latest check becomes the 'before' for the visibility lift. Counts as an explicit re-push for IndexNow.

> Role: member or higher · writes · spends credits (rate weight 5)

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `mode` | `standard` | no | Lane. Only standard exists: 1 index credit per link, used only if the link gets indexed (credit back after 7 days if not). A faster priority lane is not available yet. |
| `drip_days` | integer (≥0, ≤30) | no |  |
| `recheck_days` | integer (≥0, ≤5) | no | Deprecated: guarantee re-checks are automatic |
| `confirm_spend` | boolean | no | Set true to confirm a call that spends more than the confirmation threshold (default 1,000 credits). Ask the user first. |

Push again:

```json
{
  "name": "send_unindexed_to_indexer",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

### `delete_job`

**Delete a job.** Permanently delete a finished or cancelled push/check, its link results and any shared report link. Credits are not refunded; links still inside their 7-day guarantee count as removed by you (credit used).

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |

Delete:

```json
{
  "name": "delete_job",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

### `delete_job_url`

**Remove one link.** Remove one link (by its numeric url id from list_job_urls) from a finished job. A link still inside its guarantee counts as removed by you (credit used).

> Role: member or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `url_id` | integer (≥-9007199254740991, ≤9007199254740991) | yes |  |

Remove:

```json
{
  "name": "delete_job_url",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "url_id": 42
  }
}
```

## Visibility checks (index checks)

Ask Google (and Bing) whether links are indexed, and read the stored results.

### `check_index`

**Visibility check (index check).** Check whether URLs are indexed (1 check credit/URL with Pilot Scan: Standard, 5 with Live; up to 10,000, Free plan 50). Pass urls to create a new check, or job_id to re-check an existing push/check (manual re-checks are charged; the guarantee's own re-checks are free). engine: scan_standard (default queue, may take minutes; poll get_job_status), scan_live (seconds; monthly Live quota on Agency plans), scan_bing (positive-only "Seen by Bing" for an existing job: confirms links Bing shows, misses are returned and read "not confirmed"; off unless the platform enabled it). A check that finds a pushed link indexed uses its reserved index credit. Returns the job; results land on each link as indexed / bing_indexed.

> Role: member or higher · writes · spends credits (rate weight 5)

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `urls` | array of string | no |  |
| `job_id` | string | no |  |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `name` | string (≤200 chars) | no |  |
| `engine` | `scan_standard` \| `scan_live` \| `scan_bing` \| `upstream` | no |  |
| `confirm_spend` | boolean | no | Set true to confirm a call that spends more than the confirmation threshold (default 1,000 credits). Ask the user first. |

Check two pages:

```json
{
  "name": "check_index",
  "arguments": {
    "urls": [
      "https://example.com/blog/new-post",
      "https://example.com/pricing"
    ]
  }
}
```

Is a push in Bing yet?:

```json
{
  "name": "check_index",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "engine": "scan_bing"
  }
}
```

### `get_check_results`

**Stored search results.** Stored search data for a job's links: indexed, position, title, snippet, displayed URL, SERP features, match type, query, total results and the engine (Google or Bing). Pass url for one link's full history.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `url` | string | no |  |

All results:

```json
{
  "name": "get_check_results",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

One link's history:

```json
{
  "name": "get_check_results",
  "arguments": {
    "job_id": "job_0123456789abcdef",
    "url": "https://example.com/blog/new-post"
  }
}
```

### `share_job_report`

**Share a client report.** Create (or return the existing) read-only client report link for a job: before/after visibility, per-link status, no login needed. Your branding on Agency plans; FreshlyCited-branded on Free. revoke=true stops sharing.

> Role: member or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |
| `revoke` | boolean | no |  |

Share:

```json
{
  "name": "share_job_report",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

### `export_job_csv`

**Export CSV.** Export a job's links with submission state, before/after index status, index credit state and the latest search data as CSV text ({ filename, csv }).

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |

Export:

```json
{
  "name": "export_job_csv",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

## Bing & Copilot (IndexNow)

Verify your sites for IndexNow so pushes also notify Bing and the other IndexNow engines. Free.

### `list_indexnow_sites`

**List IndexNow sites.** List the sites (hosts) registered for IndexNow in scope, with verification state, the key, where the key file must be hosted (key_file_url) and how many links went to IndexNow in the last 30 days. A site pings IndexNow only when verified=true and enabled=true (active).

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |

All sites:

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

### `add_indexnow_site`

**Add a site for IndexNow.** Register a host (e.g. example.com or www.example.com; one entry per exact hostname) for IndexNow. Returns a generated key and key_file_url: the site owner must publish a plain-text file at that URL containing only the key (or set key_location to a .txt file elsewhere on the same host; it then only covers URLs under that folder). Then call verify_indexnow_site. Free.

> Role: admin or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `host` | string | yes | Domain or any URL on it, e.g. https://www.example.com/blog |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `key_location` | string | no | Optional full URL of the key file on the same host, e.g. https://example.com/keys/indexnow.txt |

Add a domain:

```json
{
  "name": "add_indexnow_site",
  "arguments": {
    "host": "www.example.com"
  }
}
```

### `verify_indexnow_site`

**Verify an IndexNow site.** Fetch the site's key file now and mark the site verified if it contains exactly the key. Returns verification { ok, url, detail } in plain language (e.g. 'The key file isn't there yet (HTTP 404 …)'). Verified sites are re-checked daily; two failures in a row pause pings with a notice.

> Role: member or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `site_id` | string | yes |  |

Verify:

```json
{
  "name": "verify_indexnow_site",
  "arguments": {
    "site_id": "site_0123456789abcdef"
  }
}
```

### `update_indexnow_site`

**Turn a site on/off or move its key file.** Switch IndexNow pings for a site on or off (enabled), or change key_location (null = the root /<key>.txt). Changing the key location requires verifying again.

> Role: admin or higher · writes · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `site_id` | string | yes |  |
| `enabled` | boolean | no |  |
| `key_location` | string \| null | no |  |

Pause pings:

```json
{
  "name": "update_indexnow_site",
  "arguments": {
    "site_id": "site_0123456789abcdef",
    "enabled": false
  }
}
```

### `delete_indexnow_site`

**Remove an IndexNow site.** Remove a site from IndexNow. Pushes stop notifying IndexNow for that host; past submission records stay on the jobs.

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `site_id` | string | yes |  |

Remove:

```json
{
  "name": "delete_indexnow_site",
  "arguments": {
    "site_id": "site_0123456789abcdef"
  }
}
```

### `get_job_indexnow`

**IndexNow status of a push.** What a push sent to IndexNow: summary { sent, accepted (HTTP 200), pending (HTTP 202, key still being validated), errors, skipped_recent (sent < 24 h ago, not resent), bing_seen, bing_not, hosts, http_codes } and per-link rows (indexnow_state, indexnow_http, indexnow_at, bing_indexed). Links on hosts that aren't verified are never sent to IndexNow.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `job_id` | string | yes |  |

Status:

```json
{
  "name": "get_job_indexnow",
  "arguments": {
    "job_id": "job_0123456789abcdef"
  }
}
```

## Clients & members

Your agency, client workspaces and who can access them.

### `list_tenants`

**List workspaces.** List your workspace and every client/team under it in tree order (depth, path) with credits, member and job counts.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `q` | string | no |  |
| `kind` | `agency` \| `team` \| `client` | no |  |
| `include_archived` | boolean | no |  |

Clients only:

```json
{
  "name": "list_tenants",
  "arguments": {
    "kind": "client"
  }
}
```

### `list_sub_tenants`

**List direct sub-workspaces.** List the direct children of one workspace.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `parent_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |

Children of mine:

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

### `get_tenant`

**Get a workspace.** One workspace with credits, counts, parent and whether it's your root.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | yes |  |

Get:

```json
{
  "name": "get_tenant",
  "arguments": {
    "tenant_id": "ten_0123456789abcdef"
  }
}
```

### `create_sub_tenant`

**Create a client workspace.** Create a client (default) or team workspace under yours (or under parent_id). It starts with 0 credits: use allocate_credits.

> Role: admin or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string (≤120 chars) | yes |  |
| `kind` | `team` \| `client` | no |  |
| `parent_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `notes` | string | no |  |

New client:

```json
{
  "name": "create_sub_tenant",
  "arguments": {
    "name": "<client name>",
    "kind": "client"
  }
}
```

### `update_tenant`

**Update a workspace.** Rename, change kind or notes, set the default re-check days (0-5), move under another parent, or archive/restore a workspace.

> Role: admin or higher · writes · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | yes |  |
| `name` | string | no |  |
| `kind` | `team` \| `client` | no |  |
| `notes` | string | no |  |
| `default_recheck_days` | integer (≥0, ≤5) | no |  |
| `parent_id` | string | no |  |
| `archived` | boolean | no |  |

Default re-check 3 days:

```json
{
  "name": "update_tenant",
  "arguments": {
    "tenant_id": "ten_0123456789abcdef",
    "default_recheck_days": 3
  }
}
```

### `delete_tenant`

**Delete or archive a workspace.** Delete an EMPTY workspace (confirm must equal its exact name) or archive it (mode=archive). Workspaces with jobs, credits or children can only be archived.

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | yes |  |
| `confirm` | string | no |  |
| `mode` | `delete` \| `archive` | no |  |

Archive:

```json
{
  "name": "delete_tenant",
  "arguments": {
    "tenant_id": "ten_0123456789abcdef",
    "mode": "archive"
  }
}
```

### `list_members`

**List members.** People with access to a workspace and their roles.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |

Members:

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

### `add_member`

**Add a member.** Give a person access to a workspace with a role (owner, admin, member, client_viewer = read-only). Creates and invites the account if the email is new.

> Role: admin or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `email` | string | yes |  |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `role` | `owner` \| `admin` \| `member` \| `client_viewer` | yes |  |
| `name` | string | no |  |

Read-only client login:

```json
{
  "name": "add_member",
  "arguments": {
    "email": "client@acme.example",
    "tenant_id": "ten_0123456789abcdef",
    "role": "client_viewer"
  }
}
```

### `update_member_role`

**Change a member's role.** Change a member's role (never above your own).

> Role: admin or higher · writes · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | yes |  |
| `user_id` | string | yes |  |
| `role` | `owner` \| `admin` \| `member` \| `client_viewer` | yes |  |

Make admin:

```json
{
  "name": "update_member_role",
  "arguments": {
    "tenant_id": "ten_0123456789abcdef",
    "user_id": "usr_0123456789abcdef",
    "role": "admin"
  }
}
```

### `remove_member`

**Remove a member.** Remove a person's access to a workspace (the last owner can't be removed).

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | yes |  |
| `user_id` | string | yes |  |

Remove:

```json
{
  "name": "remove_member",
  "arguments": {
    "tenant_id": "ten_0123456789abcdef",
    "user_id": "usr_0123456789abcdef"
  }
}
```

## Credits

Balances, the ledger and moving credits to clients.

### `get_credits`

**Credit balance.** A workspace's balances { index, check, reservedIndex } (index credits reserved by pushes are waiting for the guarantee), the plan with its limits and what's used, usage this period, credits expiring in the next 30 days, pricing and the 20 most recent ledger lines.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |

My balance:

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

### `list_ledger`

**Credit ledger.** Paginated, append-only credit ledger in scope: grants (purchase, plan_grant, admin), reserve / consume / release / excluded for pushes, check usage, expiries and transfers (allocate). kind=index|check filters the credit kind; direction=in|out filters credits received or spent.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `kind` | `index` \| `check` | no |  |
| `direction` | `in` \| `out` | no |  |
| `page` | integer (≥1, ≤9007199254740991) | no | Page number, 1-based (default 1) |
| `page_size` | integer (≥1, ≤200) | no | Items per page, 1-200 (default 25) |
| `q` | string | no | Free-text search |
| `sort` | string | no | Sort column |
| `dir` | `asc` \| `desc` | no | Sort direction (default desc) |

Check spending:

```json
{
  "name": "list_ledger",
  "arguments": {
    "kind": "check",
    "direction": "out"
  }
}
```

### `allocate_credits`

**Give credits to a client.** Move index or check credits from a parent workspace to a sub-workspace (negative amount pulls credits back). Each moved credit keeps its expiry. Platform admins may also grant to a root workspace.

> Role: admin or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | yes |  |
| `amount` | integer (≥-9007199254740991, ≤9007199254740991) | yes |  |
| `kind` | `index` \| `check` | no | Which credits to move (default index) |
| `note` | string | no |  |

Give 500 index credits:

```json
{
  "name": "allocate_credits",
  "arguments": {
    "tenant_id": "ten_0123456789abcdef",
    "amount": 500,
    "kind": "index",
    "note": "October"
  }
}
```

### `reverse_ledger_entry`

**Reverse a transfer.** Reverse a transfer to a client (while those credits are unspent) or a platform-admin adjustment. Push and check credits settle automatically and can't be reversed.

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `entry_id` | integer (≥-9007199254740991, ≤9007199254740991) | yes |  |

Reverse:

```json
{
  "name": "reverse_ledger_entry",
  "arguments": {
    "entry_id": 1234
  }
}
```

## API keys

Create, limit and revoke API keys.

### `list_api_keys`

**List API keys.** API keys in scope (prefix only, never the secret) with role, rate limits, last use and status.

> Role: any role · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `status` | `active` \| `revoked` | no |  |

Active keys:

```json
{
  "name": "list_api_keys",
  "arguments": {
    "status": "active"
  }
}
```

### `create_api_key`

**Create an API key.** Create an API key for a workspace. The secret (ipk_…) is returned once. Optional per-key limits: rate_per_min, rate_per_day (requests) and daily_credit_cap (credits per UTC day).

> Role: admin or higher · writes · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | no |  |
| `tenant_id` | string | no | Workspace (tenant) id. Defaults to the workspace of the key or connection; use list_tenants to find client ids. |
| `role` | `owner` \| `admin` \| `member` \| `client_viewer` | no |  |
| `rate_per_min` | integer (≥1, ≤600) | no |  |
| `rate_per_day` | integer (≥1, ≤100000) | no |  |
| `daily_credit_cap` | integer (≥1, ≤9007199254740991) \| null | no |  |

Read-only key for a client dashboard:

```json
{
  "name": "create_api_key",
  "arguments": {
    "name": "Looker",
    "role": "client_viewer",
    "rate_per_min": 30
  }
}
```

### `update_api_key`

**Update an API key.** Rename, change role or change the key's rate limits / daily credit cap (null = default).

> Role: admin or higher · writes · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `key_id` | string | yes |  |
| `name` | string | no |  |
| `role` | `owner` \| `admin` \| `member` \| `client_viewer` | no |  |
| `rate_per_min` | integer (≥1, ≤600) \| null | no |  |
| `rate_per_day` | integer (≥1, ≤100000) \| null | no |  |
| `daily_credit_cap` | integer (≥1, ≤9007199254740991) \| null | no |  |

Cap spend:

```json
{
  "name": "update_api_key",
  "arguments": {
    "key_id": "key_0123456789abcdef",
    "daily_credit_cap": 2000
  }
}
```

### `revoke_api_key`

**Revoke an API key.** Revoke a key immediately (it stays listed for audit). A key can't revoke itself.

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `key_id` | string | yes |  |

Revoke:

```json
{
  "name": "revoke_api_key",
  "arguments": {
    "key_id": "key_0123456789abcdef"
  }
}
```

### `delete_api_key`

**Delete an API key.** Permanently delete a key.

> Role: admin or higher · destructive · rate weight 1

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `key_id` | string | yes |  |

Delete:

```json
{
  "name": "delete_api_key",
  "arguments": {
    "key_id": "key_0123456789abcdef"
  }
}
```

## Platform admin

Only for FreshlyCited platform administrators.

### `list_users`

**List users.** Platform admin: list user accounts.

> Role: platform admin · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | `active` \| `suspended` \| `admin` | no |  |
| `page` | integer (≥1, ≤9007199254740991) | no | Page number, 1-based (default 1) |
| `page_size` | integer (≥1, ≤200) | no | Items per page, 1-200 (default 25) |
| `q` | string | no | Free-text search |
| `sort` | string | no | Sort column |
| `dir` | `asc` \| `desc` | no | Sort direction (default desc) |

Suspended:

```json
{
  "name": "list_users",
  "arguments": {
    "status": "suspended"
  }
}
```

### `get_user`

**Get a user.** Platform admin: one user's memberships, sessions, activity and keys.

> Role: platform admin · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `user_id` | string | yes |  |

Get:

```json
{
  "name": "get_user",
  "arguments": {
    "user_id": "usr_0123456789abcdef"
  }
}
```

### `list_errors`

**List tracked errors.** Platform admin: tracked server/API/MCP errors.

> Role: platform admin · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `source` | string | no |  |
| `level` | `error` \| `warning` | no |  |
| `status` | `open` \| `resolved` | no |  |
| `page` | integer (≥1, ≤9007199254740991) | no | Page number, 1-based (default 1) |
| `page_size` | integer (≥1, ≤200) | no | Items per page, 1-200 (default 25) |
| `q` | string | no | Free-text search |
| `sort` | string | no | Sort column |
| `dir` | `asc` \| `desc` | no | Sort direction (default desc) |

Open errors:

```json
{
  "name": "list_errors",
  "arguments": {
    "status": "open"
  }
}
```

### `resolve_error`

**Resolve an error.** Platform admin: mark an error resolved or open again.

> Role: platform admin · writes · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `error_id` | string | yes |  |
| `resolved` | boolean | yes |  |

Resolve:

```json
{
  "name": "resolve_error",
  "arguments": {
    "error_id": "err_0123456789abcdef",
    "resolved": true
  }
}
```

### `list_audit_log`

**Audit log.** Platform admin: the audit trail.

> Role: platform admin · read-only · rate weight 1 · idempotent

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `action` | string | no |  |
| `page` | integer (≥1, ≤9007199254740991) | no | Page number, 1-based (default 1) |
| `page_size` | integer (≥1, ≤200) | no | Items per page, 1-200 (default 25) |
| `q` | string | no | Free-text search |
| `sort` | string | no | Sort column |
| `dir` | `asc` \| `desc` | no | Sort direction (default desc) |

IndexNow events:

```json
{
  "name": "list_audit_log",
  "arguments": {
    "action": "indexnow.site_paused"
  }
}
```

---
Source: https://freshlycited.com/docs/tools
