Your agent gets hands on WordPress.It does not get the publish button.
Point Claude Code, Cursor or Codex at one URL. It edits the site through whichever page builder it was actually built with — and everything it does lands as a draft, waiting on one tap from the person who owns it.
- publish: false, on every instruction
- Snapshot before, rollback after
- The site pulls — nothing opens a port
Ten builders, one adapter each.Point at a mark to see the file that handles it.
Your editor. Us. Their WordPress.
Three things, in that order. No SSH key to hand over, no cron to configure, no port to open — the site does the reaching.
Point your client at it
One streamable-HTTP endpoint and a per-site bearer key, minted once and shown once. Anything that speaks MCP can drive it.
claude mcp add --transport http kepteo
Ask in your own words
Intake turns the sentence into one of 22 typed instruction kinds, validates it against a contract, and signs it. If no kind fits, it answers cannot_do instead of improvising.
The site pulls it and drafts it
The plugin polls, verifies the Ed25519 signature, writes a WordPress revision first, then applies the change unpublished. Your client's visitors see nothing until a human approves.
Say it the way you would say it to a person.
Every sentence below maps to exactly one tool. If a sentence maps to none, it says so instead of improvising.
One typed tool, validated against its contract before it is signed.
cannot_doThe last one is the important one. An agent with a gap in what it can do does not stop — it reaches for the nearest tool and tells you it is done. This one says it cannot, and names what it would need.
Your client never sees any of that.
They get a link. They see what changed, in their own words, side by side. They tap yes. That is the entire surface they touch — no login to remember, no dashboard to learn, no way to break anything.
- 1A link, not an accountIt opens straight to the change. Nothing to remember.
- 2Before and after, side by sideThe old wording and the new one, on the real page.
- 3Nothing is live until they say soUntil they tap approve, their visitors see the old page.
- Contact page · opening hours
You asked for Saturdays to be included. This is the line visitors read.
now on the siteMon–Fri, 9am–5pmafter you approveMon–Sat, 8am–6pm - Treatments page · Invisalign price
The price on the treatments table, and the same figure in the FAQ below it.
now on the site£2,200after you approve£2,400
Nothing here is live. Until you tap approve, visitors see the old page.
Two things a generic WordPress MCP cannot do
Ten builders. Each one gets its own adapter.
It does not paste HTML into a page and hope. It reads how the page is actually built, then edits it through that builder's own elements — so the page still opens in the editor your client uses.
One class-adapter-*.php per builder, in the plugin
The half of a retainer nobody enjoys.
Plugin versions, known vulnerabilities, broken links, missing meta, weak logins. It finds them on its own and brings you the list — it does not fix them behind your back.
- Booking form plugin2.4.1 → 2.4.6 · advisoryNeeds you
- Legacy sliderabandoned upstreamYours to decide
- Core + 14 pluginscurrentNothing to do
A depiction of the list, not live telemetry.
Real requests, start to finish
A few jobs from client sites, anonymised — the sentence that came in, and what the pipeline did with it.
You ask
Change our opening hours
We do
AI found the hours in 3 places
Result
Updated everywhere & published
Two ways in. One signed pipeline.
Drive it from the MCP client you already have open, or from the Kepteo portal when the person asking is not a developer. Both produce the same signed instruction and the same draft.
> make the pricing page say $79 ✓ read_page pricing (Elementor) ✓ edit_text 1 block ✓ snapshot rev #1480 → draft ready, not published
Your MCP clientClaude Code, Claude Desktop, claude.ai, Cursor, Codex — same URL, same key, same tool surface.
The Kepteo portalA plain chat and an approval queue, so the person who owns the site can ask and approve without touching a terminal.
It reads your codebase. It cannot write to it.
The site search greps the whole WordPress install to find where something actually lives. It does not hold a write handle, and it refuses your credentials by filename before it opens anything.
- brightsmile.example/
- wp-config.phpblocked by filename
- .envblocked by filename
- .htpasswdblocked by filename
- wp-content/
- themes/read-only
- plugins/read-only
- uploads/read-only
- wp-includes/read-only
No write handle anywhere in this tree.
- No code runs on your hostNo AI call is ever made from PHP, and there is no eval path. The plugin reads instructions and applies typed changes.
- It never writes a fileThe site search reads your codebase. It does not hold a single write handle to the filesystem.
- Credentials are unreadablewp-config.php, wp-config-sample.php, .env, .env.local and .htpasswd are refused by filename, before anything opens them.
- Nothing listensThe plugin pulls over outbound HTTPS. There is no inbound port, no webhook to leak, nothing to expose.
Priced per site. Not per seat, not per token.
The plans differ in one thing only: how much of the work a human on our team picks up when the agent will not guess.
- 58 typed tools
- 10 builder adapters
- Ed25519-signed instructions
- Snapshot before every change
- Client approval links
- Full activity log
Care
One site you look after yourself
The agent, on its own
- Every one of the 58 tools
- Draft + approve on every change
- Rollback on every change
- Email support
Care+
Sites that change most weeks
The agent, and a human when it says cannot_do
- Everything in Care
- A human picks up what the agent refuses
- Vulnerability hardening
- Priority queue
- Monthly health report
Agency
A portfolio, not a site
The agent, a human, and your name on it
- Unlimited sites
- Team seats & roles
- White-label client portal
- SLA & dedicated ops
The questions a developer asks first
- 01Can the agent publish something by itself?
- No. Every change instruction carries publish: false and lands as a draft or an unpublished revision — there is a test in the suite that fails the build if any instruction kind ever comes out otherwise. Publishing is a separate, explicit act by a human.
- 02What happens when I ask for something it has no tool for?
- It says cannot_do. That is the point of a typed surface: an agent with a gap in its capabilities will otherwise reach for the nearest tool and report success. Every tool ships with the list of what it cannot do.
- 03Which page builders does it actually edit natively?
- Gutenberg, Elementor, Divi, Bricks, Oxygen, Beaver Builder, WPBakery, Avada/Fusion, SiteOrigin and the classic editor each have their own adapter file in the plugin — ten of them. A builder without an adapter is read, not guessed at, and the answer comes back as cannot_do rather than as a change to the wrong thing.
- 04What does it need from my host?
- Outbound HTTPS. That is the whole requirement — shared, managed or a VPS. No inbound port, no cron you have to configure, no SSH key handed over.
Give your agent the site. Keep the publish button.
Connect one site, point your MCP client at it, and ask for something it has no tool for. The answer you get back is the whole product.