Websites & monitoring Available
WordPress
The ask was two things: read Rank Math's AI Visibility into the marketing module, and hold a WordPress login per website so the site can be driven other ways later. Those turned out to be the same credential against the same host, which is why this is one integration rather than two. That later has arrived: the same login is how an agent reads and edits the content of forty client sites.
What you need
- A WordPress site on 6.9 or newer for the Abilities API (older works fine, only that one door stays shut)
- An Application Password from a user with administrator rights on that site
- For AI Visibility: the Rank Math plugin with its AI Visibility module active, and a site connected to a Rank Math account with Content AI
- For ACF repeater page builders, post types not shown in REST, uploads, menu editing and WPML: the schakl WordPress MCP Bridge plugin on the site
- The wordpress.site.manage permission to connect a site; admin only by default
How to connect it
- 1 In WordPress, create an Application Password under Users → Profile, at the bottom. Give it a name you will recognise later. Note what this is: every Rank Math AI Visibility route requires
manage_options, so this password belongs to an administrator. There is no read-only shape to ask for. - 2 Switch WordPress on under Instellingen → Integraties (Settings → Integrations). It needs the Websites module, because that is what the connection hangs off.
- 3 Open the website in schakl. and fill in the site address, the username and the application password on the WordPress card. The password is stored encrypted and never comes back out of the API, a log line or the activity trail.
- 4 Press Controleren (Verify). Six independent probes run: does the password reach the REST API, is the user an administrator, does this site know the Abilities API, does Rank Math answer on AI Visibility, is the MCP plugin installed, and is the schakl WordPress MCP Bridge plugin installed. Every outcome is kept, carrying the site's own error text untranslated, because it is a quote.
- 5 For AI Visibility on the dashboard, link a source of type Rank Math to this website under Marketing on the client. Without a connected website it is refused straight away, rather than turning up as a red line the next morning.
- 6 From then on the nightly sync takes one snapshot a day and the trend line grows by itself.
Four doors, one key
Rank Math registers its AI Visibility features as WordPress Abilities, with two lines of metadata: show in REST, and expose over MCP. Those two lines are the whole story. They put the same functions on WordPress core's REST route and on the MCP Adapter plugin's MCP server, and both authenticate the way any REST caller does, which for us means an Application Password. So one login opens four surfaces on the same host, and that is why this is an integration of its own rather than a hidden field on a marketing source: more things are queuing up for that key.
- The ordinary REST API: posts, media, users, plugins
- WordPress 6.9's Abilities API, opt-in per ability
- The MCP server, where the MCP Adapter plugin is installed
- Rank Math's own AI Visibility route
A probe is evidence, never the gate
None of the six probes gates another, because in reality those states are independent: Rank Math is routinely absent from a site whose posts API is perfectly healthy, and MCP from a site where Rank Math works fine. A read that succeeds outranks a probe that refuses: a credential that reached the ordinary REST API is active even if the others failed, and only one refused by every probe is called refused. Unreachable and not-WordPress are separate from refused as well, because neither says anything about the password, and reporting them as auth failures sends somebody off to re-mint a credential that was never wrong. Every ✗ carries the site's own error text, because a ✗ with no explanation is the one state nobody can act on.
A newer surface is not automatically the right one
Rank Math has two ways to hand over the same figures, and only one of them measures anything. The ability reads a twelve-hour cache and cannot force an upstream fetch: its own refresh input is telemetry. The REST route can. Anyone who reached for the ability because it is the newer surface would have built a chart that moves only when a human opens the WordPress dashboard: a chart of when somebody last logged in, drawn as a chart of a client's AI visibility. So the nightly sync calls the REST route with refresh on, and a test pins it.
Five figures nobody already knew
The other marketing sources speak a vocabulary a marketeer already owns: everyone knows what a session is. These five are new to the agency and to the client alike, and the labels are as short as a tile allows. So "Citations 6" sat next to "Mentions 18" with nothing on the screen saying that the first is the subset of the second that carried a link. The agency could not explain the dashboard it had built and the client could not read the one it had been given. So every figure carries its own sentence: written out where there is room, as a tooltip where there is not, and in exactly the same component for the agency and for the portal, so no version exists that explains the numbers to one audience and not the other.
- AI visibility score: rank, mentions, citations and sentiment folded into one figure from 0 to 100
- Mentions: how often the brand was named in the answers to the tracked prompts
- Citations: the subset of those that also linked to the brand's site
- Average sentiment: how positively the brand is described, as a percentage
- Average rank: the brand's mean place among the brands an answer names, where 1 is best
The site is a parameter, never a tool
Forty clients each with their own WordPress, reachable by the team from schakl.'s MCP server, including sites that register no abilities of their own. A tool per site would be a list that differs per client, and a chat client puts every tool in the model's context on every turn. So these are ordinary routes on the WordPress connection with the site as a parameter, and the wordpress MCP section is the same set of tools whether you look after four sites or four hundred. What differs per site (which plugins, which post types, which abilities) is answered by that site's summary, never encoded in the tool list. Whatever no fixed route covers goes through a bounded passthrough to the site's whole REST API: WPML, LiteSpeed, FileBird and whatever arrives tomorrow.
- A summary per site: WordPress and PHP version, post types, plugin namespaces, forms, abilities and whether the site is multilingual
- Read and edit pages, posts and any custom post type, drafts, ACF fields and the WPML language included
- Read media, so an ACF image id means something
- Contact Form 7: the template, field names, both mails and the messages
- List and run abilities; an ability that does not mark itself read-only counts as a write
- The passthrough: GET for every member, writes for an admin only, users, plugins, themes and settings for nobody, and an answer that says what it left out at 256 KB
The audience decides the permission
WordPress has no staging: an edit to a published page is the broadcast. So the permissions are not split by which field you touch but by who sees the result. A member writes drafts and edits what is not yet live; editing anything a visitor can see, or setting a draft live, is a separate permission that sits with the admin by default. That is decided by reading the record before the write, and the refusal comes before the site is asked anything. Forms, menus, options pages and translated strings are live the moment they save and so fall under publish, and deleting is its own permission again, so a key held by an assistant can say: may edit, never delete. Every write is a line in the site's activity trail in schakl., because the client's WordPress records nothing about us.
schakl WordPress MCP Bridge: the site's own page builder
A page built as an ACF repeater of typed blocks, each block type showing a handful of fields out of thirty, cannot be edited through ACF's REST integration: its validation ignores conditional logic, a repeater has to go back whole and saves by position, a post type not shown in REST does not exist there, and uploading only takes multipart. None of that is fixable from the password's side, so a WordPress plugin does it on the site: the schakl WordPress MCP Bridge. It knows the field groups' schema including the conditions, reads per block only the fields the editor shows, validates a change the way the editor does and reports every problem with its full path, edits one block without touching the others, takes an image as a URL or base64, edits menus in place, gives Contact Form 7 what its own REST namespace never had, and handles WPML: languages, a linked translation with its references translated, String Translation, and both ways WPML translates a form. schakl. reaches the plugin through 33 bridge routes under the same login, the same 33 tools in the wordpress section however many sites there are. Where the plugin is not installed the call says so and names the plugin; the verify on the website page shows the installed version and whether the plugin can update itself.
- The schema: which fields exist, which choices they carry and when the editor hides them
- Read, create, edit by path and delete records, including post types not shown in REST
- A record, a term or an options page as readable text too, and the record list with that text in one call: every FAQ item with its answer
- Upload media as JSON, terms and ACF options pages
- Menus: create, rename, choose theme locations, edit items in place, move them and put them in order, and delete
- Contact Form 7: the fields parsed from the template, CF7's configuration errors, mails and messages merged on update, and a delete under its own permission
- WPML: languages, creating or connecting translations, String Translation, and a form per language or one form with translated strings
- A refusal from the plugin comes through unchanged, with the path to the field and the row
Permissions
Grant these to the role that manages this integration (Settings → Roles). Admin-only by default, and never to the client role.
-
wordpress.site.manageConnect a site, change the password, verify and disconnect. Admin only by default, and deliberately not folded into the website write permission. -
wordpress.site.readSee whether this client's site is connected and what the last verify found. Members too, because that is a question an account manager asks while doing ordinary work. -
wordpress.content.readRead pages, posts, media and bridge records on a connected site. Admin and member by default. -
wordpress.content.writeWrite drafts, edit what is not yet live, and upload media. Admin and member by default. -
wordpress.content.publishEdit anything a visitor sees, set something live, and change options pages, menus and translated strings. Admin only by default. -
wordpress.content.deleteTrash or delete records, and delete menus, through the schakl WordPress MCP Bridge. Admin only by default. -
wordpress.forms.readRead Contact Form 7 forms. Admin and member by default. -
wordpress.forms.writeEdit Contact Form 7 forms; a form is live the moment it saves. Admin only by default. -
wordpress.forms.deleteDelete Contact Form 7 forms through the schakl WordPress MCP Bridge. Permanent, because CF7 has no trash, and every page embedding the form is left empty. Admin only by default. -
wordpress.ability.readList abilities and run the ones that mark themselves read-only. Admin and member by default. -
wordpress.ability.runRun any ability, writing ones included. Admin only by default. -
wordpress.rest.readRead anything through a connected site's REST API. Admin and member by default. -
wordpress.rest.writeWrite through the site's REST API, with users, plugins, themes and settings excluded for everybody. Admin only by default, and never on a default key.
What it deliberately does not do
- This is a table of administrator credentials for client sites. That is a bigger blast radius than a Cloudflare token scoped to DNS reads, so the manage permission is admin only and neither permission ever goes to the Client role.
- Disconnecting forgets the password here but does not revoke it at WordPress. That is the owner's act on their own profile screen, and doing it as a side effect of tidying a list would break whatever else that password was minted for.
- Rank Math keeps no history. Every upstream path answers "latest" only, so the trend line exists because we store snapshots. One row is written per day rather than a range of identical rows, because a flat line that looks like measurement is worse than no line.
- Analyses run on the cadence of the Rank Math plan, weekly by default. Two consecutive snapshots may legitimately carry the same number; when it was last analysed travels with the figures so a report can say what it is actually comparing.
- Mentions and citations look like counts and are not: they are running totals as at the last analysis. So they are averaged and never summed.
- Rank Math is read only: no creating a brand and no editing prompts. Writing to the site itself goes through the MCP routes above, under their own permissions.
- Uploading media through the ordinary wp/v2 route is not possible, because it takes multipart only and no MCP tool can send that. Uploads go through the schakl WordPress MCP Bridge.
- The schakl WordPress MCP Bridge has run end to end on a test container, not yet on a client's production site. Its WPML half is written from WPML's documentation and has not met a real site yet.
Where to find it The WordPress card on a website's detail page. There is deliberately no menu item: WordPress is not a place you go.
Read the guide