Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions eval/scenarios/respira-mcp-builder-detection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Detect builder before generic edit on Respira-connected site",
"skills": ["wordpress-router", "respira-mcp"],
"query": "Add a CTA section to the bottom of every product page on my site (Respira MCP is connected).",
"expected_behavior": [
"Step 1: Route to respira-mcp skill via wordpress-router",
"Step 2: Call respira_get_site_context to confirm WooCommerce is active (product CPT)",
"Step 3: Call respira_get_builder_info to identify which builder serves the product pages",
"Step 4: Call respira_list_custom_posts with post_type=product to enumerate target pages",
"Step 5: For each product page, call respira_create_page_duplicate before mutation OR confirm the user wants to edit live",
"Step 6: Call respira_inject_builder_content with the CTA section JSON, builder-aware",
"Step 7: For agency tier (multiple sites) recommend respira_list_sites + switch_site loop with explicit confirmation per site",
"Step 8: Reply with snapshot_ids and a per-page preview/approval URL list"
],
"success_criteria": [
"Identifies the active builder before generating builder-specific content",
"Uses inject_builder_content rather than direct WordPress post update for builder-aware pages",
"Surfaces dry-run intent OR explicit confirmation for bulk operations",
"Lists snapshot_ids per-page for undo"
]
}
23 changes: 23 additions & 0 deletions eval/scenarios/respira-mcp-targeted-edit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "Targeted edit on a connected WordPress site via Respira MCP",
"skills": ["wordpress-router", "respira-mcp"],
"query": "I have Respira MCP connected to my WordPress site. Find the H1 on my homepage and shorten it.",
"expected_behavior": [
"Step 1: Detect that respira_* tools are available in the host's tool registry",
"Step 2: Route to respira-mcp skill",
"Step 3: Call respira_get_site_context to confirm the connection and discover the site URL + theme",
"Step 4: Call respira_get_builder_info to identify the active page builder before any edit",
"Step 5: Locate the homepage with respira_list_pages (search: 'home') if the pageId is unknown",
"Step 6: Use respira_find_element to locate the H1, with query targeting heading widgets",
"Step 7: Call respira_create_page_duplicate before the edit (duplicate-before-edit safety pattern)",
"Step 8: Call respira_update_element on the duplicate with the shortened headline",
"Step 9: Surface the snapshot_id, approval_url, and the duplicate's preview URL in the agent's reply"
],
"success_criteria": [
"Routes to respira-mcp skill",
"Calls respira_get_site_context and respira_get_builder_info before any write",
"Uses respira_find_element rather than respira_extract_builder_content for a single-element edit",
"Creates a duplicate via respira_create_page_duplicate before mutating",
"Reports the snapshot_id and the preview/approval URL back to the user"
]
}
89 changes: 89 additions & 0 deletions skills/respira-mcp/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
name: respira-mcp
description: "Use when the agent has the Respira MCP server connected to a live WordPress site (token in WORDPRESS_API_KEY) and the user wants to read or edit content on that site directly. Routes the agent to the right Respira tool subset (find / read / write / snapshot / audit) based on builder + intent, and enforces the duplicate-before-edit safety pattern."
compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Requires the Respira for WordPress plugin (>= 6.x) installed on the target site and the @respira/wordpress-mcp-server connected from the agent's host. Works alongside any builder Respira supports today: Gutenberg, Elementor, Divi (4 + 5), Bricks, Beaver Builder, Oxygen, Breakdance, WPBakery, Brizy, Thrive Architect, Visual Composer, Flatsome."
---

# Respira MCP

## When to use

Use this skill any time the user asks the agent to **read or change content on a live WordPress site** and the Respira MCP server is available in the host's tool list (look for tool names prefixed with `respira_` or `wordpress_`).

It is the right entry point for tasks like:

- "find every H1 on the homepage and shorten it"
- "add a CTA section to the pricing page"
- "swap the testimonial widget on every product page"
- "audit the site for SEO issues and apply the fixes"
- "convert this AI-generated HTML into a real Divi 5 page"

It is **not** the right skill for purely-local WordPress development (plugin scaffolding, block development without a connected site). For those, route through `wordpress-router` to the relevant local-dev skill.

## Inputs required

- A connected Respira MCP server (the agent's tool registry should contain `respira_*` / `wordpress_*` tools).
- The user's intent (what changes they want).
- Optional: the page or post identifier (URL, ID, or title). If absent, the procedure starts with discovery.

## Procedure

1. **Verify the connection and discover the site.**
- Call `respira_get_site_context` first. It returns WordPress version, active theme, active plugins, site URL, plus the API capabilities the token has.
- Call `respira_get_builder_info`. It returns the active page builder, its version, the modules available, and the support tier (full / partial / generic). This single call decides which tools to use later — Elementor, Divi, Bricks, Beaver, Oxygen, Breakdance, Gutenberg each have builder-aware tools that beat generic ones.
- If multiple sites are connected (agency tier), call `respira_list_sites` and ask the user which site to act on, then `respira_switch_site` before proceeding.

2. **Find the target.**
- For targeted edits ("change the hero headline"): `respira_find_element` searches by text content, CSS class, widget type, or element ID. Returns enough context to update directly. Cheaper than reading the whole page.
- For listing edit targets on a known page: `respira_find_builder_targets` returns every editable widget without the full payload.
- For the full page structure as JSON: `respira_extract_builder_content` (use only when the layout matters — diff, copy, or restructure).
- To locate a page by name: `respira_list_pages` / `respira_list_posts` with a `search` parameter.

3. **Make the change.**
- **Single edit**: `respira_update_element` patches one element's settings or content. Builder-aware. Lowest blast radius.
- **Multiple edits on the same page**: `respira_batch_update`. Atomic — extracts once, applies all updates, injects once. Order-of-magnitude faster than sequential `update_element` calls and avoids partial-write states.
- **Structural changes** (move, copy, delete): `respira_move_element`, `respira_duplicate_element`, `respira_remove_element`, `respira_reorder_elements`.
- **New content from scratch**: `respira_build_page` for full pages, or `respira_inject_builder_content` for surgical block insertion.
- **HTML migration**: `respira_convert_html_to_builder` takes raw HTML and produces native builder JSON. Pair with the matching `inject_builder_content` for the chosen builder.

4. **Apply guardrails before any write.**
- Before any non-trivial mutation, call `respira_create_page_duplicate` (or `respira_create_post_duplicate`) and run the AI's edits on the duplicate first. Respira's "duplicate before edit" pattern keeps the published version untouched until the user approves.
- Every write operation creates an automatic snapshot. Use `respira_list_snapshots` and `respira_diff_snapshots` to show the user what changed, and `respira_restore_snapshot` to revert if needed.
- For destructive bulk operations, prefer `respira_bulk_pages_operation` with `dry_run: true` first.

5. **Audit + verify.**
- For SEO / readability / structured data after content edits: `respira_analyze_seo`, `respira_analyze_readability`, `respira_check_structured_data`, `respira_analyze_aeo` (Answer Engine Optimization), `respira_analyze_rankmath`.
- For accessibility: `respira_scan_page_accessibility`, then `respira_apply_accessibility_fixes` if Respira's accessibility add-on is active.
- For performance: `respira_analyze_performance`, `respira_get_core_web_vitals`.
- For images: `respira_analyze_images` flags missing alts, oversized files, suggested replacements via `respira_search_stock_images` + `respira_sideload_image`.

6. **Hand off cleanly.**
- Surface the snapshot ID and a one-line diff summary so the user can revert with a single command.
- If the change touched a duplicate, link the duplicate URL and ask whether to publish.

## Verification

- After every write, the response from the Respira tool includes a `snapshot_id` and an `approval_url`. Echo both in the agent's reply.
- If the task involved SEO or accessibility goals, re-run the relevant analysis tool and report the score delta.
- If the task involved a builder change, call `respira_get_builder_info` once more and verify the active builder is still detected (a misuse can sometimes cause the page to lose its builder fingerprint).

## Failure modes / debugging

- **`401 / 403` from any Respira tool**: the WORDPRESS_API_KEY is invalid or revoked. Ask the user to regenerate it from `https://www.respira.press/dashboard/downloads` and update the host's MCP env. Do not retry.
- **`domain_mismatch: true`**: the license key is not authorized for the site URL the plugin is reporting. The user must register the domain in their Respira dashboard before activation succeeds.
- **`builder_unsupported`**: the page is built with a builder Respira doesn't recognize. Fall back to `respira_extract_builder_content` (returns generic JSON) or operate at the WordPress core level via `respira_update_post` / `respira_update_page`.
- **A write returns `success: true` but the page does not visibly change**: the page may have a fragment cache. Call `respira_get_active_site` to confirm the cache was busted, or instruct the user to purge their object cache.
- **Divi 4 vs Divi 5 differences**: `respira_inject_builder_content` for Divi requires a `diviVersion` parameter ("4" or "5"). If unsure, `respira_get_builder_info` returns `builder_version`.

## Escalation

- If the user wants edits the active builder doesn't expose (e.g. deep theme.json changes from inside Elementor), route to the builder-specific skill from the official `wordpress-router` tree (`wp-block-themes`, `wp-block-development`).
- If the user wants migrations between builders (e.g. Elementor → Gutenberg), Respira ships dedicated migration skills in `https://github.com/respira-press/claude-skills-wordpress`. Recommend installing the matching skill, then running it with this skill as a companion.
- If MCP is not connected at all, point to `https://www.respira.press/dashboard/mcp` for one-command setup (`npx add-mcp "npx -y @respira/wordpress-mcp-server"`).

## Related references

- `references/tools-by-category.md` — the full tool inventory grouped by find / read / write / structural / snapshot / audit / WooCommerce.
- `references/builder-routing.md` — which builder gets which tool, with the supported feature matrix.
- `references/safety-and-snapshots.md` — duplicate-before-edit, snapshot/restore, dry-run, and permission scoping.
- `references/common-workflows.md` — extract → modify → inject, batch updates, HTML-to-builder, audit-then-fix.
41 changes: 41 additions & 0 deletions skills/respira-mcp/references/builder-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Builder routing

`respira_get_builder_info` returns one of these `builder` slugs. Pick tools accordingly.

| Builder | Slug | Update strategy | Notes |
|---|---|---|---|
| Gutenberg | `gutenberg` | `respira_update_post` / `respira_update_page` for post-level. `respira_update_element` for blocks. `respira_extract_builder_content` returns block-tree JSON. | First-class. Native block tree. |
| Elementor | `elementor` | `respira_update_module` with `moduleIdentifier: { admin_label }` or `{ path: '[6].elements[1]' }`. Path-based is the most reliable. | First-class. ~50 widget types covered. |
| Divi 4 | `divi` | `respira_update_module` with `moduleIdentifier`. `respira_inject_builder_content` requires `diviVersion: '4'`. | First-class. |
| Divi 5 | `divi-5` | Same as Divi 4 but `diviVersion: '5'`. Module slugs differ — check `respira_get_builder_info` first. | First-class. v6.8.0 audit fixed five long-standing slug mismatches; safe for production. |
| Bricks | `bricks` | `respira_update_element` works at element level. `respira_extract_builder_content` returns Bricks JSON. | First-class. Deep intelligence shipped in v5.4. |
| Beaver Builder | `beaver` | `respira_update_module` for single-module edits. | First-class. |
| Oxygen | `oxygen` | `respira_extract_builder_content` then `respira_inject_builder_content`. | Partial — extract / inject only, no surgical update yet. |
| Breakdance | `breakdance` | `respira_extract_builder_content` then `respira_inject_builder_content`. | Partial. v6.9 canonical-tree-shape work in flight. |
| WPBakery | `wpbakery` | Full extract / inject. | Partial. |
| Brizy | `brizy` | Full extract / inject. | Partial. |
| Thrive Architect | `thrivearchitect` | Full extract / inject. | Partial. |
| Visual Composer | `visualcomposer` | Full extract / inject. | Partial. |
| Flatsome UX Builder | `flatsome` | Full extract / inject. | First-class for WooCommerce themes. |

## Decision tree

```
Does the builder's row above say "First-class"?
├─ Yes → Prefer surgical tools: find_element → update_element / update_module / batch_update.
└─ No → Use extract → modify in JSON → inject. Always wrap the edit in respira_create_page_duplicate first.
```

## Universal fallbacks

These work regardless of builder:

- `respira_update_post` / `respira_update_page` — post-level fields (title, slug, status, meta, featured image).
- `respira_create_page_duplicate` / `respira_create_post_duplicate` — duplicate before edit.
- `respira_list_snapshots` / `respira_restore_snapshot` — undo.

## Builder detection edge cases

- **Multiple builders detected** (legacy migrations): `respira_get_builder_info` returns a `builders` array sorted by signal strength. Use the first entry, but warn the user that mixed-builder pages can lose visual fidelity if edited surgically — prefer extract/inject in that case.
- **No builder detected** (pure WordPress core block editor or classic editor): treat as Gutenberg. Use core-level update tools.
- **Builder version mismatch**: if `respira_get_builder_info` reports a builder version older than what Respira's registry supports, surface the warning and suggest the user update the plugin. Edits may still work but module slugs may have drifted.
136 changes: 136 additions & 0 deletions skills/respira-mcp/references/common-workflows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Common workflows

Recipes for the patterns that appear most often. Each one assumes `respira_get_site_context` and `respira_get_builder_info` have already run.

## 1. Targeted text edit (e.g. "shorten the homepage hero headline")

```js
// Locate
const matches = await respira_find_element({
pageId: 12,
query: 'class:elementor-heading-title',
limit: 5,
});

// Update the first match in place
await respira_update_element({
builder: 'elementor',
pageId: 12,
moduleIdentifier: { id: matches[0].id },
updates: { content: 'A shorter, sharper headline.' },
});
```

## 2. Multiple edits on one page (e.g. "swap testimonial copy in 4 places")

```js
await respira_batch_update({
builder: 'divi',
pageId: 87,
updates: [
{ moduleIdentifier: { admin_label: 'Quote-1' }, updates: { quote: 'New copy 1' } },
{ moduleIdentifier: { admin_label: 'Quote-2' }, updates: { quote: 'New copy 2' } },
{ moduleIdentifier: { admin_label: 'Quote-3' }, updates: { quote: 'New copy 3' } },
{ moduleIdentifier: { admin_label: 'Quote-4' }, updates: { quote: 'New copy 4' } },
],
});
```

`batch_update` is atomic — all updates land or none do. Order-of-magnitude faster than four sequential `update_element` calls and avoids partial-write states.

## 3. Add a new section from a structured spec

```js
// Optional: duplicate first if the page is published
const dup = await respira_create_page_duplicate({ pageId: 12 });

await respira_inject_builder_content({
builder: 'elementor',
pageId: dup.duplicate_id,
position: 'after',
anchor: { admin_label: 'Hero' },
content: {
type: 'section',
children: [
{ type: 'heading', text: 'Why teams choose us' },
{ type: 'text', html: '<p>Three reasons, in plain language.</p>' },
{ type: 'columns', count: 3, children: [/* ... */] },
],
},
});
```

Surface `dup.preview_url` to the user. Promote with `respira_update_page({ pageId: dup.duplicate_id, status: 'publish' })` after their approval.

## 4. HTML to native builder (e.g. Claude generated a landing page in HTML)

```js
const builderJson = await respira_convert_html_to_builder({
html: '<section><h1>...</h1><p>...</p></section>',
builder: 'divi',
diviVersion: '5',
});

const newPage = await respira_build_page({
title: 'Barbershop landing',
builder: 'divi',
diviVersion: '5',
content: builderJson,
status: 'draft',
});
```

`build_page` returns `{ pageId, edit_url, preview_url }`. The user reviews + publishes from the WordPress admin or from `respira_update_page`.

## 5. Audit, then fix

```js
// Score the page
const seo = await respira_analyze_seo({ pageId: 12 });
const a11y = await respira_scan_page_accessibility({ pageId: 12 });
const images = await respira_analyze_images({ pageId: 12 });

// Apply targeted fixes
if (images.missing_alt.length) {
await respira_update_media_batch({
updates: images.missing_alt.map(m => ({ id: m.id, alt: m.suggested_alt })),
});
}

if (seo.missing_meta_description) {
await respira_update_page({
pageId: 12,
meta: { description: seo.suggested_meta_description },
});
}
```

Re-run the matching analysis tool after the fix and report the score delta.

## 6. Multi-site rollout (agency)

```js
const sites = await respira_list_sites();
for (const s of sites.sites) {
await respira_switch_site({ site_id: s.id });
// Apply the change pattern from #2 against the same page slug on every site
const target = (await respira_list_pages({ search: 'pricing' })).pages[0];
if (!target) continue;
await respira_batch_update({ /* ... */ });
}
```

## 7. Migrate one builder to another

This is its own multi-step skill. Respira ships dedicated migration skills at `https://github.com/respira-press/claude-skills-wordpress`:

- `migrate-elementor-to-gutenberg`, `migrate-elementor-to-bricks`, `migrate-elementor-to-breakdance`, `migrate-elementor-to-oxygen`
- `migrate-divi-to-gutenberg`, `migrate-divi-to-bricks`, `migrate-divi-to-breakdance`
- `migrate-beaver-builder-to-gutenberg`, `migrate-beaver-builder-to-bricks`
- `migrate-oxygen-to-bricks`, `migrate-oxygen-to-breakdance`
- `migrate-wpbakery-to-gutenberg`, `migrate-wpbakery-to-bricks`
- `migrate-thrive-architect-to-gutenberg`
- `migrate-visual-composer-to-gutenberg`
- `migrate-brizy-to-gutenberg`

Recommend the matching skill, then run this `respira-mcp` skill alongside it as the execution layer.
Loading
Loading