Revised Plan — Iterate, Don't Rewrite

AIOSEO × WP Abilities API & MCP

The concrete plan for shipping agent integration in 4.9.8/4.9.9 by iterating on PR #8004 — not by replacing it.

For: Adam Pickering, AIOSEO product+engineering Date: 2026-05-21 PR under review: #8004 Target release: 4.9.8 or 4.9.9

1. TL;DR & verdict

Do we build a new MCP server?

No. The Abilities API ships in WP 6.9 core. wordpress/mcp-adapter v0.5.0 (April 2026) is the canonical bridge. Building another server is reinventing solved infra.

Where does the code live?

Main plugin, alongside the existing Pro module split. No new aioseo-mcp addon. Lite + Pro both ship abilities. Addons get to declare their own in Phase 3 once WP ecosystem patterns settle.

Iterate or rewrite PR #8004?

Iterate. The PR's basic structure (direct wp_register_ability() calls in a Common\Abilities\Abilities class extended by Pro) already matches what Yoast and Jetpack ship. Fix the bugs and selection issues; don't rebuild the chassis.

Timeline

~2 weeks of focused work paired with Benjamin, landing in 4.9.8 or 4.9.9. Phase 2 (writes + list-posts-with-issues) ships ~6 weeks later once the issue taxonomy is locked.

Strategic frame

Yoast shipped 3 read-only abilities April 28, 2026. Aggregator plugins are already exposing AIOSEO via uncontrolled third-party shims. The competitive window is months, not quarters. The fastest path to "AIOSEO works in Claude Desktop" is to fix PR #8004 in place, not stand up parallel infrastructure that will sit in review for another 10 weeks.

2. Recommendation: iterate on PR #8004

Keep Benjamin's PR open. Pair-review it line by line. Land it in 4.9.8 with the concrete fixes in §3. The PR's structure is correct — correct hooks, correct WP-version gate, sensible Common/Pro split, reuse of existing models. The problems are real but additive: missing MCP flag, one functional bug (getRobotsTxt), generic permissions used where AIOSEO caps belong, loose output schemas, an over-narrow update ability, and an ability selection that needs a couple of swaps.

Why this beats the "fresh PR" alternative:

3. The concrete plan

Pair-review PR #8004 with Benjamin. Land the changes below before merge. All changes are additive or in-place; no structural rewrite of the existing class hierarchy.

3.1 Must-fix before merge (blockers)

FixWhereEffort
Add MCP exposure flag to each ability's meta: 'mcp' => ['public' => true]. Without this, abilities are reachable only via /wp-abilities/v1/ REST — not as MCP tools to Claude Desktop or Cursor. The PR title promises agent integration; this flag delivers it. All 9 wp_register_ability() calls in both Common and Pro Abilities classes. 9 lines
Fix the getRobotsTxt() bug. Currently returns getDefaultRobotsTxtContent() not the active rules — the method name lies. Build the active rules via the existing aioseo()->robotsTxt service. Common/Abilities/Abilities.php::getRobotsTxt() ~5 lines
Replace generic capabilities with AIOSEO caps. canManageOptions() currently uses manage_options. Editors with delegated AIOSEO access (the actual users of AIOSEO) get locked out. Map to aioseo_seo_analysis_settings for analyze-site, aioseo_tools_settings for get-robots-txt, aioseo_general_settings for site-wide reads. Common/Abilities/Abilities.php permission callbacks. ~10 lines
Project getRedirects() through a normalizer. Currently returns raw DB rows with internal snake_case columns. Add a small toAbilityArray() method on the Redirect model or a private mapper in the Pro Abilities class. Stable agent contract; future column renames don't break callers. Pro/Abilities/Abilities.php::getRedirects() ~15 lines
Tighten output schemas in place. Every type: object/type: array in the current PR gives agents nothing to reason about. Name the actual properties inline. Don't extract a Schemas.php namespace — inline is fine for 9 abilities and matches Yoast's pattern. All output_schema blocks. ~80 lines, mechanical.
Drop additionalProperties: false on output schemas. Locks forward compatibility — adding a response field becomes a breaking change. Keep additionalProperties: false on inputs (rejects garbage from agents), drop it on outputs. All output_schema blocks. Trivial
Add EOF newlines. Both new PHP files are missing the trailing newline. PHPCS will fail. Common/Abilities/Abilities.php, Pro/Abilities/Abilities.php Trivial

3.2 Ability-selection swaps (same PR)

ChangeWhy
drop aioseo/get-seo-checklistUI artifact, not an agent primitive. Agents compose checklists themselves from health + post lists.
fold aioseo/analyze-post-seo into aioseo/get-post-seo-data via include=analysis paramRemoves redundant ability returning overlapping data. One get-post-seo-data call covers both reads.
add aioseo/get-sitemap-statusTop-3 day-one question ("is my sitemap working?"). Cheap to ship; covers the sitemap surface that the PR omits entirely.
add aioseo/update-post-seo-with-ai (atomic, dry_run default true)Hooks into the existing Common\Ai\Ai service. One ability that returns generated options (dry_run) and persists when called again with dry_run=false. Atomic op, no state-handle bugs.
fix keep aioseo/get-robots-txt (don't drop)Cheap, frequently asked, useful as a read alongside get-sitemap-status.
fix keep aioseo/analyze-site but reshape outputReplace the opaque 'results' => ['type' => 'array'] with a named issue-summary shape (counts by severity, top issue codes). Still useful as a one-shot "is anything broken" read.

End result: 9 abilities, same count as the original PR, picked by user journey and named consistently. List in §4.

3.3 Medium-priority fixes (same PR if cheap, follow-up if not)

FixNotes
Add Post::getSaveShape() helper on the Post model. Replaces the 40-field hand-rolled array in updatePostSeoData(). 3–5 days — round-tripping in the Post model is lossy (JSON fields decoded asymmetrically, schema graph merging, boolean coercion). This is the real cliff in the PR; don't underestimate it. If the model archaeology balloons, split into a follow-up PR but get a one-pager on the shape before merging the current ability surface.
Expand aioseo/update-post-seo-data's input schema to include robots flags, canonical URL, pillar, social meta. Currently only title/description/keyphrases — agents will be surprised. Needs getSaveShape() first. Same PR if that lands; otherwise follow-up.
Improve aioseo/create-redirect: validate URL format, enum: [301, 302, 307, 308] on type, collision pre-check (return WP_Error('redirect_exists', ...) before save). ~30 lines, same PR.
aioseo/get-search-statistics: return WP_Error('search_statistics_not_connected', ...) when GSC isn't connected, rather than empty stdClass. Agent gets a useful signal instead of confusing empty data. ~10 lines.
Telemetry: log writes via existing AIOSEO usage tracking. A simple aioseo()->usage->log('ability:write', ['id' => $id]) call inside each write callback. No new DB table. ~5 lines per write. Aggregated server-side via the existing pipeline.

3.4 Tests (must land in the same PR)

3.5 QA (same PR)

3.6 Realistic effort

WorkstreamEffort
Blocker fixes (3.1)2–3 days
Ability swaps (3.2)1–2 days
Post::getSaveShape() + expanded update schema3–5 days (the real cliff)
Medium-priority fixes (3.3)1–2 days
Tests2–3 days
QA on 2 clients2 days
Total~2 weeks for one engineer paired with Benjamin

4. Revised Phase 1 abilities

9 abilities. 6 reads, 3 writes. Picked by user journey, not feature surface.

Ability IDEditionStatus vs #8004What it does
aioseo/get-post-seo-data read Lite in PR, reshape Full SEO snapshot for one post. Accepts include=analysis,schema,social param to opt in to richer payloads. Folds in what the original PR had as a separate analyze-post-seo.
aioseo/update-post-seo-data write Lite in PR, expand Set title, description, keyphrases, robots, canonical, pillar, social meta. Expanded from the original 3-field version once Post::getSaveShape() lands.
aioseo/analyze-site read Lite in PR, reshape output Site-wide audit summary: counts by severity, top issue codes. Replaces the opaque results: array output with a named shape.
aioseo/get-robots-txt read Lite in PR, fix bug Active robots.txt content (not default). Cheap, frequently asked.
aioseo/get-sitemap-status read Lite new Sitemap state: enabled types, URLs per index, last generation, validation errors. Top-3 day-one question.
aioseo/update-post-seo-with-ai write Lite new One ability, atomic. With dry_run: true (default) returns generated meta options. With dry_run: false persists. Hooks into existing Common\Ai\Ai service; consumes credits; returns credits_remaining.
aioseo/get-redirects read Pro in PR, normalize output List redirects projected through a stable shape. Filterable + paginated.
aioseo/create-redirect write Pro in PR, harden inputs Create 301/302/307/308 redirect. Validated, type-enum'd, collision-checked.
aioseo/get-search-statistics read Pro in PR, fix not-connected error GSC summary: clicks, impressions, CTR, avg position, top keywords, top pages. Returns WP_Error('search_statistics_not_connected') when GSC isn't connected.

Dropped from #8004:

5. What we're NOT building (and why)

The original draft of this report recommended building these. The 5-reviewer stress test surfaced that each is either premature, idiomatically wrong, or about to be obsoleted by WP core. They are deliberately deferred.

ComponentWhy not now
aioseo()->abilities Registrar service (queue + flush) Yoast and Jetpack both call wp_register_ability() directly on wp_abilities_api_init. No major project uses a queue-and-flush wrapper. The Registrar solves a Phase 3 problem (addon participation) at Phase 1 cost. Revisit when the first addon actually needs to declare an ability and the WP ecosystem has settled patterns.
Middleware wrapping execute_callback Breaks the Abilities API contract (callback introspection via WP_Ability::get_execute_callback() stops returning the actual callback). No project in the ecosystem does this. Rate limiting belongs in permission_callback; activity logging belongs in WP/REST request hooks. Wrapping is anti-idiomatic.
Schemas.php shared primitives namespace Inline schemas are fine for 9 abilities and match Yoast's pattern. Break-even for extraction is ~25 abilities. Extract in Phase 3 when the count justifies it.
Permissions.php helper namespace current_user_can('aioseo_*') inline is shorter, greppable, and matches the rest of AIOSEO. A wrapper class adds a layer that hides one line behind one line.
Definitions/ subdirectory split (PostSeo.php, Site.php, Ai.php) One Abilities.php file is the right shape for 9 abilities. The split helps around 20–25.
Custom aioseo_register_abilities action hook Proprietary indirection. Addons should hook wp_abilities_api_init directly like every other plugin in the ecosystem.
aioseo_abilities_log custom DB table Per-plugin telemetry table is a GDPR/storage burden (multisite, data-export, retention, deletion). Jetpack ships the central activity-log UI; WP 7.0 will absorb the central record. Log writes via AIOSEO's existing usage-tracking pipeline instead.
Bundling wordpress/mcp-adapter via Composer 0.x means minor = breaking. Bundling commits AIOSEO to forced 2–3 upgrades/year across 3M+ installs, plus Jetpack-Autoloader conflict-matrix QA every time. Soft-require with class_exists(McpAdapter::class) guard. Add a one-screen admin notice prompting install when missing. Revisit bundling when the adapter hits 1.0.
"Connect AI agent" Vue admin page Jetpack 15.8 ships the central MCP allowlist + activity-log UI. WP 7.0 absorbs client onboarding. Building a per-plugin "paste this into Claude Desktop" walkthrough now is code AIOSEO will rip out in two minor WP releases. Link out to Jetpack/core's UI instead. If we want any UI in Phase 1, it's a one-screen pointer that says "AIOSEO abilities are live — manage agent access in Jetpack/Tools."
The deeper lesson

The original draft tried to build an AIOSEO-flavored framework on top of an API that already is the framework. Every custom layer adds maintenance cost, idiom drift, and brittleness against a moving WP core target. The discipline is to register abilities, ship them, and let the WP ecosystem evolve its own conventions for the surrounding scaffolding. Then adopt those conventions when they exist.

6. The two-layer stack (context)

LayerWhat it isWho owns it
Abilities API
WP 6.9 core
A WP-native registry of typed, discoverable functions ("abilities") with JSON-Schema'd inputs/outputs and a permission_callback. Exposed via wp-abilities/v1 REST namespace. WordPress core. github.com/WordPress/abilities-api
MCP Adapter
composer plugin
Bridges abilities to the Model Context Protocol. Any ability flagged meta.mcp.public => true appears as an MCP tool. Supports HTTP and STDIO transports. WordPress org. github.com/WordPress/mcp-adapter — v0.5.0 (April 15, 2026)

Minimal registration:

// Categories first (different hook).
add_action( 'wp_abilities_api_categories_init', function() {
    wp_register_ability_category( 'aioseo', [
        'label'       => __( 'All in One SEO', 'all-in-one-seo-pack' ),
        'description' => __( 'SEO management abilities.', 'all-in-one-seo-pack' ),
    ] );
} );

// Abilities second.
add_action( 'wp_abilities_api_init', function() {
    wp_register_ability( 'aioseo/get-post-seo-data', [
        'label'               => __( 'Get post SEO snapshot', 'all-in-one-seo-pack' ),
        'description'         => __( 'Returns titles, meta description, robots, canonical, focus keyphrase, schema, and SEO score for a post.', 'all-in-one-seo-pack' ),
        'category'            => 'aioseo',
        'input_schema'        => [...],
        'output_schema'       => [...],
        'execute_callback'    => [ aioseo()->abilities, 'getPostSeoData' ],
        'permission_callback' => [ aioseo()->abilities, 'canReadPostSeo' ],
        'meta'                => [
            'show_in_rest'   => true,
            'mcp'            => [ 'public' => true ],
            'annotations'    => [ 'readonly' => true ],
        ],
    ] );
} );

No Registrar, no Middleware, no Schemas namespace. Direct calls in the existing Common\Abilities\Abilities class. This is what's in PR #8004 plus the MCP flag and the inline-schema tightening.

7. Current AIOSEO surface area

AIOSEO already exposes most of what an agent would want via the aioseo/v1 REST namespace. Phase 1 is largely wrapping, not building.

8. Competitive landscape

ProjectStatus (May 2026)What they expose
Yoast SEOShipped Apr 28, 20263 read-only abilities: SEO scores, readability scores, inclusive-language scores. No writes yet.
Rank Math (official)Nothing shipped
Rank Math (community shim)Third-party (bjornfix/mcp-abilities-rankmath)Get/update meta description, title, focus keyword.
Easy MCP AI / MCP Content Manager LiteOn wordpress.orgAggregator plugins exposing AIOSEO via uncontrolled third-party adapters. Currently the default agent surface for AIOSEO data.
Jetpack 15.8ShippedCentral MCP allowlist UI + activity log.
WP-CLI wp aiv1.0.0, May 20, 2026Natural-language WP queries; orchestrates abilities via MCP.

Yoast set the precedent (read-only baseline, direct wp_register_ability(), no custom infra) on April 28. AIOSEO can match the surface, exceed it with the AI-meta-generation write, and ship in 4.9.8/4.9.9.

9. PR #8004 detailed audit

For reference, the existing PR's state and what changes per §3.

What PR #8004 ships today

What stays as-is

What changes per §3

Refer to §3.1–3.5 for the line-item edits. Summary: add MCP flag, fix getRobotsTxt, swap capabilities, normalize getRedirects output, tighten output schemas inline, swap 2 abilities (drop seo-checklist, fold analyze-post-seo), add 2 abilities (sitemap-status, update-with-ai), add Post::getSaveShape(), harden create-redirect inputs, add tests.

10. Permission & capability model

Reuse AIOSEO's existing capabilities. Don't invent new ones. The agent inherits the calling user's permissions.

AbilityCapability
get-post-seo-data / update-post-seo-data / update-post-seo-with-aiedit_posts at registration + edit_post($id) in execute
analyze-siteaioseo_seo_analysis_settings
get-robots-txtaioseo_tools_settings
get-sitemap-statusaioseo_sitemap_settings
get-redirects / create-redirectaioseo_redirects_manage
get-search-statisticsaioseo_search_statistics_settings

Inline these via current_user_can(...) in each permission_callback. No Permissions.php helper class — a wrapper that hides one line behind one line is noise.

11. Remote-agent authentication

For Phase 1: Application Passwords. It's the lowest-friction path, supported everywhere, and is what @automattic/mcp-wordpress-remote expects by default. The user generates an App Password in their WP profile and pastes it into Claude Desktop's MCP config.

Future: OAuth 2.1 with PKCE will become standard once a canonical OAuth provider ships with WP core (WordPress.com already supports this for hosted sites). Defer until WP provides the provider; bring-your-own OAuth plugins are not a portable v1 story.

UX in Phase 1: do not build a per-plugin admin page for this. The user generates an App Password in Users → Profile following WP's existing UX. Add at most a short doc page on aioseo.com with a copyable Claude Desktop config snippet. Link out to Jetpack's MCP allowlist UI for site-wide management.

12. Phase 2 (next) and Phase 3 (later)

Phase 2 — 4.10 or 4.11, ~6 weeks after Phase 1 ships

  1. aioseo/list-posts-with-issues — the highest-leverage ability ("show me what to fix"). Requires a one-pager first that defines:
    • Issue codes (e.g. missing_meta_description, title_too_long, no_focus_keyphrase, low_readability_score).
    • Severity taxonomy (critical | warning | suggestion).
    • Pagination shape (cursor, not offset).
    • Filter parameters (post_type, severity, issue_code).
    Don't ship the ability until the taxonomy is locked — the ID becomes public API.
  2. Schema editor readsaioseo/get-schema-templates, aioseo/get-post-schema.
  3. More writesaioseo/update-redirect, aioseo/delete-redirect (with confirm: true), aioseo/update-post-schema.
  4. Run-on-demandaioseo/run-seo-audit to trigger a fresh audit.

Phase 3 — addon participation, months out

By the time Local Business, Link Assistant, BLC, Index Now, E-E-A-T, Image SEO, and the sitemap addons need to declare abilities, the WP ecosystem will likely have settled patterns we can copy (composable registrars, addon-aware admin UIs, central activity logs). Wait for that and adopt the convention. Do not invent it preemptively.

When ready, the addon pattern will be the simplest possible: each addon hooks wp_abilities_api_init with its own wp_register_ability() calls — exactly like Jetpack Forms, Sensei, and others already do.

13. Roadblocks, risks, open questions

#RiskMitigation
1 Post::getSaveShape() archaeology. The Post model has lossy round-tripping (JSON fields decoded asymmetrically, schema graph merging, boolean coercion, null vs empty-string semantics). The "current state in savePost()-compatible form" helper is 3–5 days, not 1. Spike the helper before the rest of the PR work. If the model archaeology balloons past a week, ship the helper as its own PR first, then the abilities PR.
2 savePost() side effects in non-admin context. Triggers cache invalidation, fires aioseo_after_* hooks (some assume is_admin()), regenerates sitemap entries. An MCP-triggered call has no admin context. Audit the hooks fired during savePost() for admin-context dependencies. Add an explicit "ability execution context" flag if needed. Test sitemap regen and dynamic options cache via a real Claude Desktop call.
3 WP < 6.9 sites. AIOSEO supports older WP. Abilities API only exists in 6.9 core. The function_exists('wp_register_ability') gate in PR #8004 already handles this — abilities silently don't register on older WP. Optional Composer fallback (wordpress/abilities-api) is a Phase 2 decision based on Lite-user WP-version data.
4 mcp-adapter 0.x churn. Breaking changes between minors. Soft-require pattern reduces our exposure but doesn't eliminate it. Pin a tested minor in plugin docs. Treat upgrades as feature work. Subscribe to the repo's releases for early warning.
5 Schema strictness across MCP clients. Different clients enforce JSON Schema with different strictness. additionalProperties: false on output will break some. Drop additionalProperties: false from all outputs (§3.1). Keep it on inputs.
6 Closing PR #8004 was the wrong instinct. The political cost (CEO author, 10 weeks in review) of a close-and-replace was high; the technical gain was lower than I claimed. Don't close. Pair-review and iterate. Co-author no one new; Benjamin stays the author.
7 Yoast head start. Yoast shipped 3 abilities in April. Every week of AIOSEO delay grows the gap. Ship Phase 1 in 4.9.8 or 4.9.9. Don't let the perfect (Registrar architecture) be the enemy of the shipped (working abilities).
8 Third-party shims own the AIOSEO agent surface today. Easy MCP AI, MCP Content Manager Lite expose AIOSEO via uncontrolled adapters. Shipping first-party abilities reclaims the surface. Once registered, the shims are competing with the canonical implementation.
9 Security review for write abilities. Agent-driven writes are a new threat model. Application Password rotation, scope limits, and abuse patterns need consideration. Block on a security review pass before write abilities ship. App Passwords can be revoked individually; document this clearly. Add a per-user rate limit in permission_callback (transient-backed).
10 Telemetry pipeline coupling. The "log writes via AIOSEO usage tracking" plan assumes that pipeline can carry ability-call events. Verify with the data team before merge. If not viable, defer the telemetry to Phase 2 rather than adding a new DB table.

14. Appendix: the 5-reviewer stress test

The original draft of this report recommended closing PR #8004 and opening a fresh PR with a custom Registrar service, middleware layer, schema namespace, custom action hook, activity-log table, bundled mcp-adapter, and Vue admin page. Five independent reviewers were briefed and asked to push back. The five lenses were chosen deliberately to avoid overlap.

Reviewer 1 — Devil's advocate (politics & pragmatism)

Verdict: iterate, don't close

Closing the CEO's PR after 10 weeks in REVIEW_REQUIRED damages contribution culture more than any architectural gain. Most of the cited "blockers" are line-item fixes, not redesigns. The proposed rewrite concentrates all risk in one giant PR that will sit in review for another quarter. Every week of delay gives the surface to Yoast and third-party shims. Verdict: pair-review and iterate.

Reviewer 2 — Architecture (simplicity & YAGNI)

Verdict: drop nearly every proposed abstraction

For 9 abilities all owned by the main plugin in Phase 1, the Registrar's queue+flush mechanism buys nothing — direct wp_register_ability() in wp_abilities_api_init is correct. Middleware wraps a contract the Abilities API didn't ask to be wrapped. Schemas.php earns its way in at ~25 abilities, not 10. Permissions.php hides one line behind one line. Definitions/ split helps at ~20 files, not 9. Soft-require mcp-adapter, don't bundle it. Defer the Vue page.

Reviewer 3 — PM (user value)

Verdict: ability selection partially wrong

The two-step AI pattern (generate + apply) is a human-UX projection — agents prefer atomic ops with a dry_run flag. list-posts-with-issues isn't Phase 1-ready without a defined issue taxonomy; defer. get-robots-txt is cheap and frequently asked — restore it. get-sitemap-status is a top-3 day-one question and was missing entirely. Fold analyze-post-seo into get-post-seo-data with an include=analysis param.

Reviewer 4 — WP ecosystem (idiom)

Verdict: scrap the framework, ship the abilities

Yoast and Jetpack both call wp_register_ability() directly on wp_abilities_api_init. Nobody wraps callbacks with middleware. Nobody has a proprietary register hook. Jetpack ships THE central activity log; per-plugin tables duplicate that and add GDPR exposure. WP 7.0 absorbs client onboarding — a Vue admin page now is code AIOSEO rips out in two releases. PR #8004's current structure is closer to ecosystem idiom than the proposed replacement.

Reviewer 5 — Engineering risk (execution reality)

Verdict: 3-week estimate is fantasy; 6–8 weeks realistic for the fresh-PR plan

Post::getSaveShape() alone is 3–5 days because of lossy round-tripping in the Post model. savePost() side effects in non-admin contexts are unaccounted for. Schema primitives are 3–4 days, not 1. New DB table is 4–5 days with GDPR + multisite + retention. Vue page is 4–5 days. Jetpack Autoloader collision matrix is untested. Missing entirely: security review, capability mapping doc, rollback plan, addon compat check, support enablement.

Convergence

Five reviewers, five non-overlapping lenses, the same conclusion: PR #8004's basic structure (direct wp_register_ability(), Common → Pro extension) is already closer to WP ecosystem idiom than the proposed replacement. The proposed Registrar / Middleware / Schemas / Definitions / hook / activity-log / Vue page stack is either premature (YAGNI), idiomatically wrong (nobody else does it), about to be obsoleted (WP 7.0), or unrealistically estimated (6–8 weeks not 3).

When five independent angles converge on the same answer, the lone disagreeing voice (the original draft) is the one to update. The recommendation in §2 reflects that update.

15. Action checklist

  1. Get PM sign-off on "iterate, don't rewrite" and on the revised 9-ability list (§4).
  2. Loop Benjamin in with the line-by-line PR review (§3) — not as a public PR comment thread, but as a pair session.
  3. Spike Post::getSaveShape() first. If it's 3–5 days as expected, continue. If it's blowing past a week, split it into its own PR and ship abilities behind a feature flag.
  4. Land the blocker fixes in PR #8004 (§3.1). MCP flag, robots bug, AIOSEO caps, getRedirects normalizer, tight schemas, EOF newlines.
  5. Make the ability swaps (§3.2). Drop seo-checklist, fold analyze-post-seo, add sitemap-status, add update-with-ai.
  6. Add tests (§3.4).
  7. QA against Claude Desktop and wp ai on a baseline WP 6.9 install (§3.5).
  8. Security review pass on the 3 write abilities (update-post-seo-data, update-post-seo-with-ai, create-redirect).
  9. Merge into release/4.9.8 (or 4.9.9 if 4.9.8 has already cut).
  10. Block out Phase 2 design — one-pager on the issue taxonomy for list-posts-with-issues.
  11. Watch the WP ecosystem — if Jetpack/core ships a centralized agent-management UI, link out instead of building.