---
title: 'AI Access'
description: 'Every MilliCache Pro operation as a WordPress ability: what an assistant can read, what it can change, what it can never do, and how rule writing is kept safe.'
menu_order: 10
---

# AI Access

WordPress 7.0 ships the Abilities API, a register of the things a site can do, described well enough that software can pick the right one. MilliCache Pro registers its operations there, so the cache can be inspected and steered from a REST client, a script, or an AI assistant.

Everything on this page is also available from the [WP-CLI commands](/docs/millicache-pro/03-wp-cli/01-commands) and the [command palette](/docs/millicache-pro/04-command-palette/01-commands). Abilities are a third door to the same rooms, not a separate set of powers.

## Two doors, and they are not the same

Every ability is reachable over REST at `/wp-json/wp-abilities/v1/`, guarded by the same capability as the settings screen. Nothing is exposed to a visitor.

A **subset** is additionally offered to AI assistants over MCP, which needs the [MCP Adapter](https://github.com/WordPress/mcp-adapter) plugin. That subset is deliberately smaller: REST exposure means *you* can call it, MCP means *a model may decide to call it on your behalf*. Those are different questions, so they have different answers.

## What you can do

| Ability | What it does | Assistant |
|---|---|---|
| `cache-status` | Cache state, entry count, size | ✅ |
| `cache-clear` | Clear the whole cache, or by URL or flag | ✅ |
| `cache-entries-list` | List cached pages as metadata | ✅ |
| `cache-entry-get` | One page in detail, including why it has several copies | ✅ |
| `rules-list` | Every caching rule in full | ✅ |
| `rules-schema` | The building blocks a rule may use | ✅ |
| `rules-create` | Add a rule, always switched off | ✅ |
| `rules-update` | Change part of a rule | ✅ |
| `rules-toggle` | Switch a rule on or off | ✅ |
| `rules-delete` | Remove a rule that is switched off | ✅ |
| `preload-status` | What the preload queue is doing | ✅ |
| `preload` | Queue the sitemap URLs for preloading | ✅ |
| `edge-status` | Provider, zone, credentials, active state | ✅ |
| `edge-test` | Verify the stored credentials against the provider | ✅ |
| `edge-purge` | Empty the whole zone at your CDN | ❌ |
| `object-cache-status` | Drop-in state and connection | ✅ |
| `object-cache-flush` | Empty the object cache | ❌ |
| `settings-export` | Settings without any secrets | ✅ |
| `settings-backup` | Snapshot the current settings | ❌ |
| `settings-reset` | Back to defaults | ❌ |
| `settings-restore` | Return to the snapshot | ❌ |

`cache-status`, `cache-clear` and the settings abilities come from MilliCache and are there without a license. The rest arrive with their module, so an ability exists only while its module is switched on and your license is active.

### Why some are closed to assistants

The pattern is not "read is safe, write is dangerous". `cache-clear` is a write and is open, because a cleared cache costs a little server time and rebuilds itself. What stays closed is what a person should be choosing:

- **`edge-purge` and `object-cache-flush`** empty everything at once, on every site of a network, and the cost lands at your CDN or your storage server rather than here.
- **`settings-reset` and `settings-restore`** replace your configuration. `settings-backup` is closed too, because there is no import ability to pair it with: on its own it would guard against a risk that does not exist over this route.

`settings-export` never returns your storage password or API keys, whichever route it is called from. Anything an ability returns can end up in a conversation with a third party, so secrets are decided per field, not per caller.

## Writing rules safely

Caching rules are the one place where an assistant could quietly break a site. A rule that switches caching off matches silently: no error appears, the pages simply stop being cached. Three guarantees hold that in check.

**A new rule always arrives switched off.** There is no way to ask for anything else, so nothing an assistant adds takes effect until you turn it on. Read what it proposes, then decide.

**Only a switched-off rule can be removed.** That closes the loop: a rule just added can always be taken back, while one you deliberately turned on cannot vanish without a separate, visible step.

**A rule cannot be renamed or switched on through an update.** Changing what a rule does and changing whether it runs stay separate acts.

Two more things get refused before anything is stored:

- A **condition type nothing answers to**. Both `is_frontpage` (a near miss for `is_front_page`) and an invented name are rejected, rather than becoming a rule that quietly never matches.
- A **placeholder that will never resolve**, such as `{request.param.utm_source}` where `{param.utm_source}` was meant. An unresolved placeholder stays in the value as literal text, which would put every visitor into the same bucket. See below.

When a change leaves a rule with no conditions at all, the answer says so in a `warning`, because such a rule applies to every request on the site. That is occasionally what you want, which is why it is a warning and not an error.

### Placeholders

A rule value can carry a placeholder, written `{category.key}`, which is filled in per request:

| Category | Example |
|---|---|
| `param` | `{param.utm_source}` |
| `cookie` | `{cookie.geo_country}` |
| `header` | `{header.accept}` |
| `request` | `{request.host}`, `{request.headers.accept}` |
| `post` | `{post.id}`, `{post.type}` |
| `term`, `user`, `query` | `{term.slug}`, `{user.roles}`, `{query.paged}` |

`rules-schema` lists them with the keys each one accepts, and a plugin that registers its own category appears there too. Categories such as `param` and `cookie` take any key, since you choose the name. Others accept a fixed set, and a key outside it is refused: `{post.idd}` does not get stored.

## Reading why a page has several copies

`cache-entry-get` answers the question the counters cannot. When one URL holds four entries, the cache split it along one of five dimensions, and `split_by` names the one that actually differs: `url` (a query string), `cookies`, `unique`, `buckets`, `method` or `https`. Each copy then carries a `variant` object with all its values.

The cached HTML itself is never returned. An entry for a signed-in visitor holds personalised markup, which has no business in a chat transcript.

Note that `cache-entries-list` counts URLs while `cache-status` counts stored entries, so the two disagree whenever any page has more than one copy. That is normal.

## Multisite

Abilities for network-wide settings carry a `network-` prefix, for example `millicache/network-rules-list`, and sit alongside their per-site counterparts. Modules owned by the network (Edge Cache, Object Cache) appear only in the network form.

One difference is worth knowing: `cache-clear` is open to an assistant for a single site but `network-cache-clear` is not, because clearing every site of a network at once is a decision that should be yours.

## Related

- [WP-CLI Commands](/docs/millicache-pro/03-wp-cli/01-commands): the same operations for scripts and deploys
- [Command Palette](/docs/millicache-pro/04-command-palette/01-commands): the same operations by keyboard
- [Rules Builder](/docs/millicache-pro/02-modules/03-rules-builder): writing the same rules by hand
- [Cache Entries](/docs/millicache-pro/02-modules/02-cache-entries): the browser behind the entry abilities
