MCP abilities
RowSprout Pro
RowSprout Pro 3.1 registers 15 WordPress Abilities in the category rowsprout. An agent calls them through the MCP adapter’s mcp-adapter-execute-ability tool; your own PHP code calls them with wp_get_ability( 'rowsprout/…' )->execute( $input ). How to connect an agent is explained in AI agents (MCP).
The descriptions below are the ones the agent receives, so they are written for an AI model and name the other abilities by their tool name (generate_pages is the ability rowsprout/generate-pages).
| Ability | What it does |
|---|---|
rowsprout/list-templates |
List rowsprout_template posts, optionally filtered by status or search term. |
rowsprout/get-template |
Get a template’s full details: title, content, href pattern, properties (field_types), and groups merged with their current generation status. |
rowsprout/create-template |
Create a new rowsprout_template with an href pattern and optional initial properties. |
rowsprout/update-template |
Update a template’s title, content, href pattern, and/or status. |
rowsprout/list-template-properties |
List a template’s properties (field_types — the columns every group shares), plus “available_types”: the live registry of types valid for add_template_property’s own “type” argument. |
rowsprout/add-template-property |
Add a new property (field/column) to a template. |
rowsprout/list-template-groups |
List a template’s groups (the rows generated pages are built from) with their field values and current generation status. |
rowsprout/add-template-group |
Add a new group to a template. |
rowsprout/update-template-group |
Update one group’s field values (partial — only listed keys change) and/or its parent link. |
rowsprout/generate-pages |
Queue pages for background generation — for the whole template or a specific set of groups — using a chosen save-action behavior. |
rowsprout/get-generated-page |
Read a generated rowsprout_page post directly by its page_id (get_generation_status’s “rowsprout_page_id”): real title, slug, post status, permalink, and content. |
rowsprout/get-generation-status |
Check generation status for a template’s groups — use this to poll after calling generate_pages. |
rowsprout/get-group-planning |
Read the planning of a template’s groups — the same overview as the Planning tab in the template editor. |
rowsprout/set-group-planning |
Plan — or clear — the moment each group is generated (which is when its page goes live). |
rowsprout/autofill-group-planning |
Spread planned moments over a set of groups from a few parameters, like the Planning tab’s auto-fill wizard. |
Abilities
Section titled “Abilities”rowsprout/list-templates
Section titled “rowsprout/list-templates”List rowsprout_template posts, optionally filtered by status or search term.
| Parameter | Type | Required | Description |
|---|---|---|---|
status |
string: any, publish, draft, pending, private | ||
search |
string | ||
page |
integer | ||
per_page |
integer |
rowsprout/get-template
Section titled “rowsprout/get-template”Get a template’s full details: title, content, href pattern, properties (field_types), and groups merged with their current generation status.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes |
rowsprout/create-template
Section titled “rowsprout/create-template”Create a new rowsprout_template with an href pattern and optional initial properties. Creates no groups and generates no pages. Placeholder syntax: write “@code_<code>_<id>@” anywhere in content or href_pattern to insert a property’s value at generation time. “<code>” is a property’s own “code” (see list_template_properties/get_template — most commonly just its key, e.g. “href”, “title”); a few reserved words also work as shortcuts regardless of a property’s own code: “title” for the title-type property, “href”/“slug” for the href-type property, “textarea”/“content” for a textarea property. “<id>” is normally this template’s own post ID (template_id) — but for a property this template only has because it INHERITS it from a parent template (see get_template’s “field_types”), use the PARENT template’s post ID instead, since that is where the value actually lives.
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
string | yes | |
content |
string | HTML content. May contain @code_<code>_<id>@ placeholder tokens — see tool description. | |
href_pattern |
string | yes | URL slug pattern for generated pages. May contain @code_<code>_<id>@ placeholder tokens — see tool description. |
status |
string: draft, publish | ||
parent_id |
integer | The post ID of a PARENT TEMPLATE (a rowsprout_template post), if this template should inherit its properties. Not related to a group’s own parent link — see add_template_group/update_template_group’s “parent_group_id” for that. | |
field_types |
array |
rowsprout/update-template
Section titled “rowsprout/update-template”Update a template’s title, content, href pattern, and/or status. Does not touch properties, groups, or generation. Placeholder syntax: write “@code_<code>_<id>@” anywhere in content or href_pattern to insert a property’s value at generation time. “<code>” is a property’s own “code” (see list_template_properties/get_template — most commonly just its key, e.g. “href”, “title”); a few reserved words also work as shortcuts regardless of a property’s own code: “title” for the title-type property, “href”/“slug” for the href-type property, “textarea”/“content” for a textarea property. “<id>” is normally this template’s own post ID (template_id) — but for a property this template only has because it INHERITS it from a parent template (see get_template’s “field_types”), use the PARENT template’s post ID instead, since that is where the value actually lives. Fails with an error (rather than silently overwriting) if this template’s properties/groups were changed by anyone else — another API call, or someone saving via the classic/Elementor editor — after you last read them. On that error, call get_template again and retry with the current data.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
title |
string | ||
content |
string | HTML content. May contain @code_<code>_<id>@ placeholder tokens — see tool description. | |
href_pattern |
string | URL slug pattern for generated pages. May contain @code_<code>_<id>@ placeholder tokens — see tool description. | |
status |
string |
rowsprout/list-template-properties
Section titled “rowsprout/list-template-properties”List a template’s properties (field_types — the columns every group shares), plus “available_types”: the live registry of types valid for add_template_property’s own “type” argument. Properties can only be listed and added via this API, never modified or removed — a deliberate safety limit given generated pages can already be live in production; use the admin UI for that.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes |
rowsprout/add-template-property
Section titled “rowsprout/add-template-property”Add a new property (field/column) to a template. Every existing group gets an empty value for it. Properties can only be added here, not modified or removed (deliberate — see list_template_properties). Call list_template_properties first: its “available_types” is the authoritative, current list of valid values for “type” (not fixed here since it’s filterable/site-specific). Fails with an error (rather than silently overwriting) if this template’s properties/groups were changed by anyone else — another API call, or someone saving via the classic/Elementor editor — after you last read them. On that error, call get_template again and retry with the current data.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
type |
string | yes | One of list_template_properties’ “available_types” for this template (e.g. “title”, “href”, “textarea”, “item-list”, “thumbnail”). |
label |
string | yes | Human-readable name shown in the admin UI (e.g. the column header). Not used in placeholder tokens or as the fields{} key. |
key |
string | The internal identifier for this property: the key used in a group’s “fields” map (add_template_group/update_template_group) and in get_template’s “field_types”/group output. Must be unique on this template — properties are never removed, so a collision here is permanent. Auto-generated (matching the admin UI’s own convention) if omitted; only pass one explicitly if you need a specific, predictable key. | |
code |
string | The “<code>” used in this property’s own @code_<code>_<id>@ placeholder token (see create_template’s own description). Defaults to “key” if omitted — most properties never need to set this separately. | |
options |
array | ||
can_be_overruled |
boolean | ||
required |
boolean |
rowsprout/list-template-groups
Section titled “rowsprout/list-template-groups”List a template’s groups (the rows generated pages are built from) with their field values and current generation status. Each field value comes back nested: {“key”: {“type”:…, “value”:…, “code”:…}}. group_id values are stable across normal add_template_group/update_template_group calls, but are NOT guaranteed to survive a WPML translation update being applied to this template (WPML can regenerate its whole group list with new ids) — re-fetch via list_template_groups/get_template after one if this template has translations, rather than reusing an id read beforehand.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
group_ids |
array | ||
status |
string: not_queued, pending, scheduled, waiting, in-process, completed, failed, stale, deleted-completed | “not_queued” = no DB queue row yet (e.g. a group with nothing generated for it yet). The rest are real queue statuses; “stale” means the config changed since this group’s page was last built and it is waiting to be picked up by a future generate_pages call. | |
page |
integer | ||
per_page |
integer |
rowsprout/add-template-group
Section titled “rowsprout/add-template-group”Add a new group to a template. Fields not specified default to an empty value. Accepts either a plain scalar per field key ({“href”: “the-hague”}) or the nested shape get_template/list_template_groups return ({“href”: {“value”: “the-hague”, …}}) — both work. Generates no page — call generate_pages afterwards; the new group is marked ready for that automatically. Groups can only be added and modified via this API, never removed. group_id values are stable across normal add_template_group/update_template_group calls, but are NOT guaranteed to survive a WPML translation update being applied to this template (WPML can regenerate its whole group list with new ids) — re-fetch via list_template_groups/get_template after one if this template has translations, rather than reusing an id read beforehand. Fails with an error (rather than silently overwriting) if this template’s properties/groups were changed by anyone else — another API call, or someone saving via the classic/Elementor editor — after you last read them. On that error, call get_template again and retry with the current data.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
fields |
object | Map of field key to its new value — plain scalar or {“value”: …}. See tool description. | |
parent_group_id |
string | The group_id of a group on this template’s PARENT TEMPLATE, if this group should inherit from it. A string identifying a GROUP — unrelated to create_template’s “parent_id”, which is an integer identifying a TEMPLATE POST. |
rowsprout/update-template-group
Section titled “rowsprout/update-template-group”Update one group’s field values (partial — only listed keys change) and/or its parent link. Accepts either a plain scalar per field key ({“href”: “the-hague”}) or the nested shape get_template/list_template_groups return ({“href”: {“value”: “the-hague”, …}}) — both work. If this group already has a generated page, it is marked stale so the next generate_pages call (even without listing this group_id, and without force_full_regenerate) will rebuild it. Never generates a page itself. Groups can only be modified via this API, never removed. group_id values are stable across normal add_template_group/update_template_group calls, but are NOT guaranteed to survive a WPML translation update being applied to this template (WPML can regenerate its whole group list with new ids) — re-fetch via list_template_groups/get_template after one if this template has translations, rather than reusing an id read beforehand. Fails with an error (rather than silently overwriting) if this template’s properties/groups were changed by anyone else — another API call, or someone saving via the classic/Elementor editor — after you last read them. On that error, call get_template again and retry with the current data.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
group_id |
string | yes | |
fields |
object | yes | Map of field key to its new value — plain scalar or {“value”: …}. See tool description. |
parent_group_id |
string | The group_id of a group on this template’s PARENT TEMPLATE, if this group should inherit from it (empty string clears it). A string identifying a GROUP — unrelated to create_template’s “parent_id”, which is an integer identifying a TEMPLATE POST. |
rowsprout/generate-pages
Section titled “rowsprout/generate-pages”Queue pages for background generation — for the whole template or a specific set of groups — using a chosen save-action behavior. Only queues; actual generation happens on the next background queue tick (usually within about a minute). Mirrors the admin “Generate” row action exactly. A (re)generated page always updates the SAME rowsprout_page post in place (same post ID) — it is never duplicated; only its slug can change, and only if a field that feeds the href pattern changed (note: this API leaves no redirect behind when that happens — see get_generated_page). save_action: “update_pages” (default) actually (re)builds pages; “save_template” only marks groups stale/queued without building anything (mirrors “Save template only” in the editor). This tool always generates NOW; to choose WHEN groups are generated use get_group_planning / set_group_planning / autofill_group_planning. Called for the whole template (no group_ids) it leaves planned groups alone; naming a planned group in group_ids, or force_full_regenerate=true, generates it immediately regardless of its plan. With save_action=update_pages and no group_ids: by default (force_full_regenerate not set) only groups already marked stale or newly added are rebuilt — a group whose fields were changed via update_template_group IS included (that call marks it stale), but a change made outside these tools may not be picked up without force_full_regenerate=true, which unconditionally rebuilds every group. Use get_generation_status to check progress afterwards.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
group_ids |
array | ||
save_action |
string: update_pages, save_template | Defaults to “update_pages” if omitted. | |
force_full_regenerate |
boolean | Only applies when group_ids is empty and save_action is “update_pages”. true = rebuild every group in the template regardless of whether it changed. false/omitted = only rebuild groups already marked stale or newly added. |
rowsprout/get-generated-page
Section titled “rowsprout/get-generated-page”Read a generated rowsprout_page post directly by its page_id (get_generation_status’s “rowsprout_page_id”): real title, slug, post status, permalink, and content. “content” is a fresh, uncached render of the actual live page (bypasses page caching so it reflects the current data, not what happens to be cached right now — see generate_pages/get_generation_status for whether the page has actually been rebuilt since a change; this tool answers “what would the current data produce”, not “what is currently cached”). Use this to diagnose a page directly through the API instead of fetching its live URL by hand — e.g. to confirm whether page_link’s slug-collision warning actually applies to this page.
| Parameter | Type | Required | Description |
|---|---|---|---|
page_id |
integer | yes |
rowsprout/get-generation-status
Section titled “rowsprout/get-generation-status”Check generation status for a template’s groups — use this to poll after calling generate_pages. “page_link” is a real get_permalink() lookup of the generated post (not a computed/guessed URL) — but generated-page slugs deliberately don’t go through WordPress’s own slug-uniqueness check, so it CAN collide with another post’s URL; if a returned link doesn’t show the page you expect, that’s the first thing to check. “generated_at” is when this group’s page was last actually (re)built (null if never, or on a site whose database hasn’t finished migrating yet) — distinct from “status”: a “completed” group can still be showing older content than the current config if nothing has queued it for rebuild since (see generate_pages).
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
group_ids |
array | ||
status |
string: pending, scheduled, waiting, in-process, completed, failed, stale, deleted-completed |
rowsprout/get-group-planning
Section titled “rowsprout/get-group-planning”Read the planning of a template’s groups — the same overview as the Planning tab in the template editor. For every group: its “state” (unplanned = not generated yet, planned, waiting_parent, queued, processing, live, stale = outdated, failed, deleted), “planned_at” (the moment it will be generated), its parent group’s planned moment (a child can never be planned earlier than its parent), when it was last generated (“generated_at”) and its page link. Generating a group’s page IS what makes it live, so “planned_at” is effectively the go-live moment (plus a short delay for the background queue). All date-times are in the site’s timezone (returned as “timezone”); “processing_window” says whether generation is restricted to a daily time window. Read-only; works on any language’s template.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
state |
string: unplanned, planned, waiting_parent, queued, processing, live, stale, failed, deleted | ||
page |
integer | ||
per_page |
integer |
rowsprout/set-group-planning
Section titled “rowsprout/set-group-planning”Plan — or clear — the moment each group is generated (which is when its page goes live). “plan” maps a group_id to a date-time in the site’s timezone, “YYYY-MM-DD HH:MM”, or to “” (empty) to clear that group’s plan. All-or-nothing: if any entry is invalid nothing is saved and the error names the group. A child group (one with a parent_group_id) cannot be planned earlier than its parent group’s planned moment; a child whose parent group has no page yet simply waits for it. Groups currently being generated are skipped and reported. This only changes WHEN generation happens — it never generates anything now. Like the other write tools it is refused on a template that is a WPML translation of another (plan the original-language template; a translation is planned in the template editor’s Planning tab). A group that already has a page is refreshed at its planned moment while the old page stays live until then. Clearing a plan sets the group back to “stale”. Changing a group’s data later does not cancel its plan.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
plan |
object | yes | Map of group_id to “YYYY-MM-DD HH:MM” (site timezone), or “” to clear. |
rowsprout/autofill-group-planning
Section titled “rowsprout/autofill-group-planning”Spread planned moments over a set of groups from a few parameters, like the Planning tab’s auto-fill wizard. Starting at “start” (site timezone, “YYYY-MM-DD HH:MM”), it hands out “per” groups per “period” (“day” or “hour”), between the daily times “from” and “to” (default 09:00–17:00; a day’s slots are spread evenly across that window), optionally only on certain “weekdays” (0 = Sunday … 6 = Saturday). “order”: “table” (the template’s own order, default), “title” (alphabetical) or “random”. Which groups: “group_ids” if given, otherwise “apply”: “empty” (default — groups that have no plan yet) or “all”. A child group is never placed earlier than its parent group’s planned moment (it is moved later, and a note says so). By default this is a PREVIEW — nothing is stored; pass save=true to store it (same rules and errors as set_group_planning). The preview works on any language’s template; save=true is refused on a template that is a WPML translation, like the other write tools.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id |
integer | yes | |
start |
string | yes | “YYYY-MM-DD HH:MM” in the site’s timezone. |
per |
integer | Groups per period. Default 5. | |
period |
string: day, hour | Default “day”. | |
from |
string | “HH:MM”. Default 09:00. | |
to |
string | “HH:MM”. Default 17:00. | |
weekdays |
array of integer | Allowed weekdays, 0 = Sunday … 6 = Saturday. Default: every day. | |
order |
string: table, title, random | ||
apply |
string: empty, all | Which groups when group_ids is not given. Default “empty”. | |
group_ids |
array of string | Plan exactly these groups (overrides “apply”). | |
save |
boolean | false (default) = preview only; true = store the planning. |
What an agent is told
Section titled “What an agent is told”Besides the descriptions above, an agent that discovers the abilities gets this general guidance about RowSprout (the description of the ability category). On a site with WPML, the part after it is added.
Guidance for every site
This category manages "rowsprout" content on a WordPress site: templatesthat define a pattern of properties, and the generated pages built fromper-row "groups" of values for that pattern (e.g. one template per productcategory, one generated page per city/location).
Data model:- A TEMPLATE (rowsprout_template post) has PROPERTIES and GROUPS.- PROPERTIES (aka "field_types") are the columns every group shares: a key, a type (title/href/textarea/thumbnail/etc.), a label, and a "code" used in @code_<code>_<id>@ placeholder tokens inside the template's own title/content/href pattern — see create_template's own description for the full placeholder syntax, it's the single most important thing to read before writing any template content/href_pattern. Properties can only be listed and added here — not modified or removed (deliberate; same for templates and groups themselves — nothing in this API deletes anything, use the admin UI for that).- GROUPS are the actual data rows — one group normally becomes one generated PAGE (rowsprout_page post). Each group has a value per property. Groups can be listed, added, and modified (field values, parent link) — never removed. A group's own "group_id" is stable across normal edits but NOT guaranteed to survive a WPML translation update on that template — see add_template_group/update_template_group's own description.- A CHILD template (has a parent template) automatically shares any property whose key also exists on its parent — those show first, in the parent's own order, followed by the child's own properties. A child's group inherits an empty field from its parent's matching group at generation time.- A group's field values are read back nested: {"key": {"type":..., "value":..., "code":...}}. When writing (add_template_group / update_template_group), either that nested shape or a plain scalar per key ({"key": "value"}) is accepted — no need to strip it down yourself before sending values back.- "parent_id" means two different things depending which tool: an integer TEMPLATE post id on create_template, but a string GROUP id ("parent_group_id") on add_template_group/update_template_group. Same concept (inheritance), different namespace — don't confuse the two.
Generating pages:- generate_pages only QUEUES groups for background generation — it never builds a page synchronously. Actual generation happens on the next background tick, usually within about a minute. Poll get_generation_status afterwards to see when it's done and get the resulting page id/link.- A (re)generated page always updates the SAME underlying rowsprout_page post in place — same post ID, every time. It is never duplicated. Only its slug/URL can change, and only if a field feeding the template's href pattern changed.- save_action controls what a queue does, default "update_pages" if omitted: "update_pages" actually (re)builds the queued group(s); "save_template" only marks them stale/queued without generating anything (mirrors the editor's "Save template only" option). generate_pages always generates NOW; to choose WHEN groups are generated, use the planning tools described under "Planning" below.- With save_action="update_pages" and no group_ids given (whole-template mode): by default only groups already marked stale, or newly added, actually get rebuilt — NOT every "completed" group whose data might have changed. update_template_group marks the group(s) it touches stale, so a follow-up generate_pages call picks them up correctly. Pass force_full_regenerate=true to unconditionally rebuild every group regardless of whether anything changed.- Adding a property, or changing a group's field values, never triggers generation by itself — call generate_pages afterwards for the change to actually produce/update a page.- get_generation_status's "page_link" is a genuine get_permalink() lookup of the real post, not a guessed URL — but generated-page slugs deliberately skip WordPress's own slug-uniqueness check, so two pages (even from different templates) can end up sharing one slug; if the link doesn't show the expected content, a slug collision is the first thing to suspect. Its "generated_at" is when that specific page was last actually rebuilt — a "completed" status alone doesn't mean the content is current. get_generated_page reads a page directly by its rowsprout_page_id (title/slug/status/permalink/content) — use it to confirm what's actually on a page instead of fetching its live URL.- No redirect is left behind when a field change moves a page's slug — rowsprout_page is a hierarchical post type, which WordPress's own old-slug-redirect mechanism explicitly excludes. An href-driven slug change on an already-published, already-indexed page is a real broken- link risk with no built-in mitigation; flag this to the user rather than assuming it's handled.
Planning (choosing WHEN groups are generated):- Generating a group's page IS what makes it live — there is no separate publish date. So "planning" a group means choosing the moment it gets generated: get_group_planning shows every group's state and planned moment, set_group_planning plans or clears them, and autofill_group_planning spreads moments over many groups from a few parameters (preview by default; save=true stores it). All date-times are in the site's timezone.- A planned group is generated by the background queue shortly after its moment (within the queue's normal cadence, and only inside the site's processing window if one is set) — planning never generates anything by itself. A group that already has a page keeps that page live until its planned moment, when it is refreshed.- A child group (one with a parent_group_id) can never be planned earlier than its parent group, and is only generated once its parent group's page exists.- Reading the planning works on any language's template, but WRITING it (set_group_planning, autofill_group_planning with save=true) is refused on a WPML translation, like every other write tool — plan the original-language template; a translation is planned by a person in the template editor's Planning tab. The autofill preview works everywhere.- Editing a planned group's data later does not cancel its plan: it is generated with the then-current data when its moment arrives.- generate_pages generates now. Called for the whole template (the default), it leaves planned groups alone; naming a planned group in group_ids, or passing force_full_regenerate=true, generates it immediately regardless of its plan.
Suggested order for common tasks: list_templates → get_template (to seecurrent properties/groups/status) → add_template_property /add_template_group / update_template_group as needed → generate_pages (now)or autofill_group_planning / set_group_planning (later) → get_generation_statusor get_group_planning → get_generated_page to confirm.Added on sites with WPML
WPML (multilingual):- Each language of a template/page is its own separate WordPress post with its own id — a WPML translation is not a variant of the same post, it's a whole different rowsprout_template post that started as a copy of the source language's config. None of these tools expose which language a template is in or which other post is its translation; if you need a specific language's version of a template and aren't sure of its post id, ask the user for it rather than guessing from the source-language template's id.- Translations are created/managed through WPML's own Translation Editor/Dashboard in the WordPress admin, not through this API — there is no tool here for creating or managing a translation.- A template that IS a WPML translation of another template can be read (including its planning) and have its pages (re)generated, but update_template/add_template_property/add_template_group/ update_template_group/set_group_planning (and autofill_group_planning with save=true) all refuse to write to it — edit the original-language template, or use WPML's own Translation Editor, instead.