@respira/wordpress-mcp-server 7.6.1 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +59 -31
  2. package/TOOL_CATALOG.md +288 -0
  3. package/dist/__tests__/pagespeed-error-classification.test.d.ts +2 -0
  4. package/dist/__tests__/pagespeed-error-classification.test.d.ts.map +1 -0
  5. package/dist/__tests__/pagespeed-error-classification.test.js +52 -0
  6. package/dist/__tests__/pagespeed-error-classification.test.js.map +1 -0
  7. package/dist/__tests__/rest-route-fallback.test.js +0 -64
  8. package/dist/__tests__/rest-route-fallback.test.js.map +1 -1
  9. package/dist/__tests__/site-token-401-error-classification.test.d.ts +0 -19
  10. package/dist/__tests__/site-token-401-error-classification.test.d.ts.map +1 -1
  11. package/dist/__tests__/site-token-401-error-classification.test.js +20 -60
  12. package/dist/__tests__/site-token-401-error-classification.test.js.map +1 -1
  13. package/dist/__tests__/tools-list-protocol-smoke.test.d.ts +2 -0
  14. package/dist/__tests__/tools-list-protocol-smoke.test.d.ts.map +1 -0
  15. package/dist/__tests__/tools-list-protocol-smoke.test.js +78 -0
  16. package/dist/__tests__/tools-list-protocol-smoke.test.js.map +1 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +20 -7
  19. package/dist/config.js.map +1 -1
  20. package/dist/elementor-tools.js +2 -2
  21. package/dist/elementor-tools.js.map +1 -1
  22. package/dist/server.d.ts.map +1 -1
  23. package/dist/server.js +758 -19
  24. package/dist/server.js.map +1 -1
  25. package/dist/usage-emitter.d.ts +7 -0
  26. package/dist/usage-emitter.d.ts.map +1 -1
  27. package/dist/usage-emitter.js +41 -1
  28. package/dist/usage-emitter.js.map +1 -1
  29. package/dist/wordpress-client.d.ts +59 -42
  30. package/dist/wordpress-client.d.ts.map +1 -1
  31. package/dist/wordpress-client.js +149 -135
  32. package/dist/wordpress-client.js.map +1 -1
  33. package/package.json +5 -8
  34. package/tool-capabilities.json +4122 -0
package/dist/server.js CHANGED
@@ -1628,6 +1628,22 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
1628
1628
  },
1629
1629
  readOnlyHint: true,
1630
1630
  },
1631
+ {
1632
+ name: 'wordpress_search_abilities',
1633
+ description: 'Search the curated WordPress Abilities directory and classify each result as Respira-native, inhaled, unavailable, or replaced by a safer Respira workflow. ' +
1634
+ 'Results include per-site install/inhalation state, the preferred replacement tool when one exists, and the next action needed to make an unavailable ability callable.',
1635
+ inputSchema: {
1636
+ type: 'object',
1637
+ properties: {
1638
+ q: { type: 'string', description: 'Free-text capability search.' },
1639
+ plugin: { type: 'string', description: 'Optional exact plugin slug or name.' },
1640
+ category: { type: 'string', description: 'Optional exact ability category.' },
1641
+ kind: { type: 'string', enum: ['read', 'write'], description: 'Optional operation kind.' },
1642
+ limit: { type: 'number', description: 'Maximum results, 1–100 (default 20).' },
1643
+ },
1644
+ },
1645
+ readOnlyHint: true,
1646
+ },
1631
1647
  {
1632
1648
  name: 'wordpress_abilities_gap_report',
1633
1649
  description: 'Compare the active plugins on this WordPress site against the curated list of plugins known to expose abilities via the WordPress Abilities API (wp_register_ability). ' +
@@ -2006,12 +2022,16 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
2006
2022
  },
2007
2023
  {
2008
2024
  name: 'wordpress_update_theme_builder_template',
2009
- description: 'Replace the content of an existing Divi Theme Builder layout (a global header, footer, or body) by its layout_id (from list_theme_builder_templates). Snapshot-protected. For a targeted single-module edit, use apply_builder_patch on the same layout_id instead. Works on Divi 4 and Divi 5.',
2025
+ description: 'Replace the content of an existing Divi Theme Builder layout (a global header, footer, or body) by its layout_id (from list_theme_builder_templates). This rewrites the layout on EVERY page that uses it, and unlike a page edit it goes live immediately: there is no staged duplicate and no approval step, because Divi resolves a global layout by id and a second copy would compete with the original. A snapshot is taken first, so it is reversible with restore_snapshot. The first call is refused unless confirm_live_edit is true. For a targeted single-module edit, use apply_builder_patch on the same layout_id instead. Works on Divi 4 and Divi 5.',
2010
2026
  inputSchema: {
2011
2027
  type: 'object',
2012
2028
  properties: {
2013
2029
  layout_id: { type: 'number', description: 'The et_*_layout post id from list_theme_builder_templates.' },
2014
2030
  structure: { description: 'Divi 4 shortcode string, or a Divi 5 block/node array (the new content).' },
2031
+ confirm_live_edit: {
2032
+ type: 'boolean',
2033
+ description: 'Required. Set true to acknowledge that this rewrites a global layout live on every page that uses it. Tell the user what is about to change before setting it.',
2034
+ },
2015
2035
  },
2016
2036
  required: ['layout_id', 'structure'],
2017
2037
  },
@@ -2524,6 +2544,326 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
2524
2544
  description: 'End the explicit snapshot session started by wordpress_begin_session. Later changes fall back to automatic time-window grouping.',
2525
2545
  inputSchema: { type: 'object', properties: {} },
2526
2546
  },
2547
+ {
2548
+ name: 'wordpress_list_site_templates',
2549
+ description: 'List native Full Site Editing templates or template parts with hierarchy, source, customization state, public route, block count, and a concurrency fingerprint.',
2550
+ inputSchema: {
2551
+ type: 'object',
2552
+ properties: {
2553
+ kind: { type: 'string', enum: ['template', 'template_part'], description: 'Defaults to template.' },
2554
+ search: { type: 'string' },
2555
+ area: { type: 'string', description: 'Optional template-part area such as header or footer.' },
2556
+ customized_only: { type: 'boolean' },
2557
+ page: { type: 'number' },
2558
+ per_page: { type: 'number' },
2559
+ },
2560
+ },
2561
+ readOnlyHint: true,
2562
+ },
2563
+ {
2564
+ name: 'wordpress_list_activity',
2565
+ description: 'List privacy-safe Respira activity with site/resource/tool/outcome/date filters and pagination.',
2566
+ inputSchema: {
2567
+ type: 'object',
2568
+ properties: {
2569
+ tool: { type: 'string' },
2570
+ resource_type: { type: 'string' },
2571
+ resource_id: { type: 'number' },
2572
+ outcome: { type: 'string', enum: ['success', 'error'] },
2573
+ date_from: { type: 'string' },
2574
+ date_to: { type: 'string' },
2575
+ page: { type: 'number' },
2576
+ per_page: { type: 'number' },
2577
+ },
2578
+ },
2579
+ readOnlyHint: true,
2580
+ },
2581
+ {
2582
+ name: 'wordpress_get_activity',
2583
+ description: 'Get one activity record with compact before/after/diff and links to related snapshots, structural proposals, approvals, and rollback recovery.',
2584
+ inputSchema: {
2585
+ type: 'object',
2586
+ properties: { id: { type: 'number' } },
2587
+ required: ['id'],
2588
+ },
2589
+ readOnlyHint: true,
2590
+ },
2591
+ {
2592
+ name: 'wordpress_get_site_template',
2593
+ description: 'Read one FSE template or template part as normalized blocks. Returns its source, render route, supported targeted operations, and expected_fingerprint for safe updates.',
2594
+ inputSchema: {
2595
+ type: 'object',
2596
+ properties: {
2597
+ id: { type: 'string', description: 'Canonical theme//slug ID or slug.' },
2598
+ kind: { type: 'string', enum: ['template', 'template_part'] },
2599
+ },
2600
+ required: ['id'],
2601
+ },
2602
+ readOnlyHint: true,
2603
+ },
2604
+ {
2605
+ name: 'wordpress_create_site_template',
2606
+ description: 'Stage creation of a native FSE template customization. Structural writes are approval-first; pass dry_run=true to preview or edit_target=live only when Direct Editing is enabled.',
2607
+ inputSchema: {
2608
+ type: 'object',
2609
+ properties: {
2610
+ kind: { type: 'string', enum: ['template', 'template_part'] },
2611
+ slug: { type: 'string' },
2612
+ title: { type: 'string' },
2613
+ area: { type: 'string' },
2614
+ blocks: { type: 'array', items: { type: 'object' } },
2615
+ content: { type: 'string', description: 'Serialized block markup. Use either content or blocks.' },
2616
+ verification_marker: { type: 'string', description: 'Expected public marker used for render verification.' },
2617
+ dry_run: { type: 'boolean' },
2618
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2619
+ },
2620
+ required: ['slug'],
2621
+ },
2622
+ },
2623
+ {
2624
+ name: 'wordpress_update_site_template',
2625
+ description: 'Stage targeted path-addressed FSE block operations with stale-write protection. Operations: set_attributes, replace_block, insert_before, insert_after, insert_inside, remove_block, move_block.',
2626
+ inputSchema: {
2627
+ type: 'object',
2628
+ properties: {
2629
+ id: { type: 'string' },
2630
+ kind: { type: 'string', enum: ['template', 'template_part'] },
2631
+ expected_fingerprint: { type: 'string' },
2632
+ operations: { type: 'array', items: { type: 'object' }, maxItems: 50 },
2633
+ verification_marker: { type: 'string' },
2634
+ dry_run: { type: 'boolean' },
2635
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2636
+ },
2637
+ required: ['id', 'expected_fingerprint', 'operations'],
2638
+ },
2639
+ },
2640
+ {
2641
+ name: 'wordpress_reset_site_template',
2642
+ description: 'Stage removal of a user FSE customization so the theme-provided template becomes active. Requires the current fingerprint and retains a structural rollback snapshot.',
2643
+ inputSchema: {
2644
+ type: 'object',
2645
+ properties: {
2646
+ id: { type: 'string' },
2647
+ kind: { type: 'string', enum: ['template', 'template_part'] },
2648
+ expected_fingerprint: { type: 'string' },
2649
+ dry_run: { type: 'boolean' },
2650
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2651
+ },
2652
+ required: ['id', 'expected_fingerprint'],
2653
+ },
2654
+ destructiveHint: true,
2655
+ },
2656
+ {
2657
+ name: 'wordpress_list_site_patterns',
2658
+ description: 'List native WordPress site patterns, distinguishing editable user patterns from immutable theme/plugin patterns. Returns sync status, source, block count, and fingerprints.',
2659
+ inputSchema: {
2660
+ type: 'object',
2661
+ properties: {
2662
+ search: { type: 'string' },
2663
+ source: { type: 'string', enum: ['user', 'registered', 'theme', 'plugin', 'core'] },
2664
+ sync_status: { type: 'string', enum: ['synced', 'unsynced', 'registered'] },
2665
+ page: { type: 'number' },
2666
+ per_page: { type: 'number' },
2667
+ },
2668
+ },
2669
+ readOnlyHint: true,
2670
+ },
2671
+ {
2672
+ name: 'wordpress_get_site_pattern',
2673
+ description: 'Read a user, theme, plugin, or core pattern as a path-addressed block tree. User patterns return an expected_fingerprint and references for safe targeted updates.',
2674
+ inputSchema: {
2675
+ type: 'object',
2676
+ properties: { id: { type: 'string', description: 'User pattern post ID, registered pattern name, or slug.' } },
2677
+ required: ['id'],
2678
+ },
2679
+ readOnlyHint: true,
2680
+ },
2681
+ {
2682
+ name: 'wordpress_create_site_pattern',
2683
+ description: 'Stage creation of a native synced or unsynced user pattern. The write is approval-first, snapshot-backed, read-back verified, and server-render verified.',
2684
+ inputSchema: {
2685
+ type: 'object',
2686
+ properties: {
2687
+ title: { type: 'string' },
2688
+ slug: { type: 'string' },
2689
+ sync_status: { type: 'string', enum: ['synced', 'unsynced'] },
2690
+ blocks: { type: 'array', items: { type: 'object' } },
2691
+ content: { type: 'string', description: 'Serialized block markup. Use either content or blocks.' },
2692
+ verification_marker: { type: 'string' },
2693
+ dry_run: { type: 'boolean' },
2694
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2695
+ },
2696
+ required: ['title'],
2697
+ },
2698
+ },
2699
+ {
2700
+ name: 'wordpress_update_site_pattern',
2701
+ description: 'Stage targeted path-addressed operations on an editable user pattern with stale-write, wrong-target, snapshot, and render protection.',
2702
+ inputSchema: {
2703
+ type: 'object',
2704
+ properties: {
2705
+ id: { type: 'string' },
2706
+ expected_fingerprint: { type: 'string' },
2707
+ operations: { type: 'array', items: { type: 'object' }, maxItems: 50 },
2708
+ verification_marker: { type: 'string' },
2709
+ dry_run: { type: 'boolean' },
2710
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2711
+ },
2712
+ required: ['id', 'expected_fingerprint', 'operations'],
2713
+ },
2714
+ },
2715
+ {
2716
+ name: 'wordpress_delete_site_pattern',
2717
+ description: 'Stage deletion of an editable user pattern. Referenced patterns are refused unless allow_referenced_delete is explicitly approved; a rollback snapshot is retained.',
2718
+ inputSchema: {
2719
+ type: 'object',
2720
+ properties: {
2721
+ id: { type: 'string' },
2722
+ expected_fingerprint: { type: 'string' },
2723
+ allow_referenced_delete: { type: 'boolean' },
2724
+ dry_run: { type: 'boolean' },
2725
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2726
+ },
2727
+ required: ['id', 'expected_fingerprint'],
2728
+ },
2729
+ destructiveHint: true,
2730
+ },
2731
+ {
2732
+ name: 'wordpress_list_site_navigations',
2733
+ description: 'List native block navigation entities with compact nested items, exact block paths, status, block count, and concurrency fingerprints.',
2734
+ inputSchema: {
2735
+ type: 'object',
2736
+ properties: {
2737
+ search: { type: 'string' },
2738
+ page: { type: 'number' },
2739
+ per_page: { type: 'number' },
2740
+ },
2741
+ },
2742
+ readOnlyHint: true,
2743
+ },
2744
+ {
2745
+ name: 'wordpress_get_site_navigation',
2746
+ description: 'Read one native block navigation entity as a compact menu tree plus its lossless path-addressed block document, references, and expected_fingerprint.',
2747
+ inputSchema: {
2748
+ type: 'object',
2749
+ properties: { id: { type: 'string', description: 'Navigation post ID or slug.' } },
2750
+ required: ['id'],
2751
+ },
2752
+ readOnlyHint: true,
2753
+ },
2754
+ {
2755
+ name: 'wordpress_create_site_navigation',
2756
+ description: 'Stage creation of a native block navigation entity. The write is approval-first, snapshot-backed, read-back verified, and server-render verified.',
2757
+ inputSchema: {
2758
+ type: 'object',
2759
+ properties: {
2760
+ title: { type: 'string' },
2761
+ slug: { type: 'string' },
2762
+ blocks: { type: 'array', items: { type: 'object' } },
2763
+ content: { type: 'string', description: 'Serialized navigation-link/submenu blocks. Use either content or blocks.' },
2764
+ verification_marker: { type: 'string' },
2765
+ dry_run: { type: 'boolean' },
2766
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2767
+ },
2768
+ required: ['title'],
2769
+ },
2770
+ },
2771
+ {
2772
+ name: 'wordpress_update_site_navigation',
2773
+ description: 'Stage exact path-addressed operations on a native block navigation entity while preserving unknown extension blocks and rejecting stale or wrong targets.',
2774
+ inputSchema: {
2775
+ type: 'object',
2776
+ properties: {
2777
+ id: { type: 'string' },
2778
+ expected_fingerprint: { type: 'string' },
2779
+ operations: { type: 'array', items: { type: 'object' }, maxItems: 50 },
2780
+ verification_marker: { type: 'string' },
2781
+ dry_run: { type: 'boolean' },
2782
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2783
+ },
2784
+ required: ['id', 'expected_fingerprint', 'operations'],
2785
+ },
2786
+ },
2787
+ {
2788
+ name: 'wordpress_delete_site_navigation',
2789
+ description: 'Stage deletion of a native block navigation entity. Referenced navigation is refused unless allow_referenced_delete is explicitly approved; a rollback snapshot is retained.',
2790
+ inputSchema: {
2791
+ type: 'object',
2792
+ properties: {
2793
+ id: { type: 'string' },
2794
+ expected_fingerprint: { type: 'string' },
2795
+ allow_referenced_delete: { type: 'boolean' },
2796
+ dry_run: { type: 'boolean' },
2797
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2798
+ },
2799
+ required: ['id', 'expected_fingerprint'],
2800
+ },
2801
+ destructiveHint: true,
2802
+ },
2803
+ {
2804
+ name: 'wordpress_list_design_tokens',
2805
+ description: 'List native Gutenberg theme.json color, typography, spacing, or breakpoint tokens. This is the first-class agent surface over Respira’s existing theme.json variable store.',
2806
+ inputSchema: {
2807
+ type: 'object',
2808
+ properties: { type: { type: 'string', enum: ['color', 'typography', 'spacing', 'breakpoints'] } },
2809
+ required: ['type'],
2810
+ },
2811
+ readOnlyHint: true,
2812
+ },
2813
+ {
2814
+ name: 'wordpress_create_design_token',
2815
+ description: 'Create a user-managed native Gutenberg theme.json design token through approval and structural snapshot protection.',
2816
+ inputSchema: {
2817
+ type: 'object',
2818
+ properties: {
2819
+ type: { type: 'string', enum: ['color', 'typography', 'spacing', 'breakpoints'] },
2820
+ id: { type: 'string' },
2821
+ name: { type: 'string' },
2822
+ value: {},
2823
+ expected_fingerprint: { type: 'string', description: 'Optional document revision returned by wordpress_list_design_tokens.' },
2824
+ approval_token: { type: 'string' },
2825
+ dry_run: { type: 'boolean' },
2826
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2827
+ },
2828
+ required: ['type', 'name', 'value'],
2829
+ },
2830
+ },
2831
+ {
2832
+ name: 'wordpress_update_design_token',
2833
+ description: 'Update a user-managed native Gutenberg theme.json design token with document revision, approval, snapshot, and render verification.',
2834
+ inputSchema: {
2835
+ type: 'object',
2836
+ properties: {
2837
+ type: { type: 'string', enum: ['color', 'typography', 'spacing', 'breakpoints'] },
2838
+ id: { type: 'string' },
2839
+ name: { type: 'string' },
2840
+ value: {},
2841
+ expected_fingerprint: { type: 'string' },
2842
+ approval_token: { type: 'string' },
2843
+ dry_run: { type: 'boolean' },
2844
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2845
+ },
2846
+ required: ['type', 'id', 'expected_fingerprint'],
2847
+ },
2848
+ idempotentHint: true,
2849
+ },
2850
+ {
2851
+ name: 'wordpress_delete_design_token',
2852
+ description: 'Delete a user-managed native Gutenberg theme.json design token through approval and structural snapshot protection.',
2853
+ inputSchema: {
2854
+ type: 'object',
2855
+ properties: {
2856
+ type: { type: 'string', enum: ['color', 'typography', 'spacing', 'breakpoints'] },
2857
+ id: { type: 'string' },
2858
+ expected_fingerprint: { type: 'string' },
2859
+ approval_token: { type: 'string' },
2860
+ dry_run: { type: 'boolean' },
2861
+ edit_target: { type: 'string', enum: ['approval', 'live'] },
2862
+ },
2863
+ required: ['type', 'id', 'expected_fingerprint'],
2864
+ },
2865
+ destructiveHint: true,
2866
+ },
2527
2867
  {
2528
2868
  name: 'wordpress_apply_builder_patch',
2529
2869
  description: 'Apply a list of targeted builder patch operations. Each operation is { identifier: { id|admin_label|path|type [+match_content] }, updates: { content?, attributes?, ...flat_settings? } }. The identifier block follows the same shape as wordpress_find_element\'s identifier; the updates block follows the same shape as wordpress_update_module\'s updates. Returns 400 respira_patch_invalid_operation when an entry is missing either field. This is NOT a JSON-Patch document — do not pass { op, path, value } shapes (those will be rejected). Example: { operations: [{ identifier: { admin_label: "Hero" }, updates: { admin_label: "Hero Content" } }] }.',
@@ -2803,6 +3143,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
2803
3143
  fresh: { type: 'boolean', default: false, description: 'Bypass the 1h transient cache.' },
2804
3144
  site_id: { type: 'string', description: 'Per-call site override.' },
2805
3145
  },
3146
+ anyOf: [
3147
+ { required: ['page_id'] },
3148
+ { required: ['url'] },
3149
+ ],
2806
3150
  },
2807
3151
  readOnlyHint: true,
2808
3152
  },
@@ -2822,6 +3166,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
2822
3166
  fresh: { type: 'boolean', default: false, description: 'Bypass the 1h cache.' },
2823
3167
  site_id: { type: 'string', description: 'Per-call site override.' },
2824
3168
  },
3169
+ anyOf: [
3170
+ { required: ['page_id'] },
3171
+ { required: ['url'] },
3172
+ ],
2825
3173
  },
2826
3174
  readOnlyHint: true,
2827
3175
  },
@@ -3023,7 +3371,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
3023
3371
  },
3024
3372
  {
3025
3373
  name: 'wordpress_activate_plugin',
3026
- description: 'EXPERIMENTAL: Activate a plugin. Requires plugin management to be enabled in Respira settings. Approval-gated: first call returns `respira_approval_required` with an `approval_token`; call again with the same `slug` plus that token to complete activation. Monitor the site after activation.',
3374
+ description: 'EXPERIMENTAL: Safely activate a plugin. Respira checks declared PHP, WordPress, dependency and companion-plugin compatibility, activates in a fresh loopback request, probes REST and frontend boot, and automatically deactivates the plugin if the site fails. Approval-gated. Use force_without_probe only after explicit operator approval on a host that blocks loopback requests.',
3027
3375
  inputSchema: {
3028
3376
  type: 'object',
3029
3377
  properties: {
@@ -3035,6 +3383,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
3035
3383
  type: 'string',
3036
3384
  description: 'Second-step approval token returned by the first call. Echo it back unchanged with the same slug to complete activation.',
3037
3385
  },
3386
+ force_without_probe: {
3387
+ type: 'boolean',
3388
+ description: 'High-risk override for hosts that block loopback verification. Default false.',
3389
+ },
3038
3390
  },
3039
3391
  required: ['slug'],
3040
3392
  },
@@ -4905,7 +5257,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
4905
5257
  },
4906
5258
  {
4907
5259
  name: 'woocommerce_sales_report',
4908
- description: 'Get WooCommerce sales report for week/month/year/custom range.',
5260
+ description: 'Deprecated compatibility alias for woocommerce_revenue_summary. Retained for two minor releases.',
4909
5261
  inputSchema: {
4910
5262
  type: 'object',
4911
5263
  properties: {
@@ -4916,6 +5268,176 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
4916
5268
  },
4917
5269
  readOnlyHint: true,
4918
5270
  },
5271
+ {
5272
+ name: 'woocommerce_revenue_summary',
5273
+ description: 'Bounded HPOS-compatible revenue summary with currency, store timezone, exact date boundaries, included statuses, pagination coverage, and explicit gross/discount/refund/tax/shipping/net definitions.',
5274
+ inputSchema: {
5275
+ type: 'object',
5276
+ properties: {
5277
+ date_start: { type: 'string', description: 'ISO date/time in the store timezone. Defaults to 30 days ago.' },
5278
+ date_end: { type: 'string', description: 'ISO date/time in the store timezone. Defaults to now.' },
5279
+ statuses: { type: 'array', items: { type: 'string' } },
5280
+ max_orders: { type: 'number', description: 'Bounded coverage cap, 1-10000. Defaults to 2000.' },
5281
+ },
5282
+ },
5283
+ readOnlyHint: true,
5284
+ },
5285
+ {
5286
+ name: 'woocommerce_sales_timeseries',
5287
+ description: 'Revenue timeseries grouped by day, week, or month in the WooCommerce store timezone.',
5288
+ inputSchema: {
5289
+ type: 'object',
5290
+ properties: {
5291
+ date_start: { type: 'string' },
5292
+ date_end: { type: 'string' },
5293
+ statuses: { type: 'array', items: { type: 'string' } },
5294
+ interval: { type: 'string', enum: ['day', 'week', 'month'] },
5295
+ max_orders: { type: 'number' },
5296
+ },
5297
+ },
5298
+ readOnlyHint: true,
5299
+ },
5300
+ {
5301
+ name: 'woocommerce_top_products',
5302
+ description: 'Rank products by bounded net sales with quantity, gross sales, net sales, and order counts.',
5303
+ inputSchema: {
5304
+ type: 'object',
5305
+ properties: {
5306
+ date_start: { type: 'string' },
5307
+ date_end: { type: 'string' },
5308
+ statuses: { type: 'array', items: { type: 'string' } },
5309
+ max_orders: { type: 'number' },
5310
+ limit: { type: 'number' },
5311
+ },
5312
+ },
5313
+ readOnlyHint: true,
5314
+ },
5315
+ {
5316
+ name: 'woocommerce_orders_summary',
5317
+ description: 'Order count, status distribution, revenue metrics, coverage, currency, timezone, and date definitions.',
5318
+ inputSchema: {
5319
+ type: 'object',
5320
+ properties: {
5321
+ date_start: { type: 'string' },
5322
+ date_end: { type: 'string' },
5323
+ statuses: { type: 'array', items: { type: 'string' } },
5324
+ max_orders: { type: 'number' },
5325
+ },
5326
+ },
5327
+ readOnlyHint: true,
5328
+ },
5329
+ {
5330
+ name: 'woocommerce_customers_summary',
5331
+ description: 'Privacy-safe active, repeat-in-range, one-time, and guest customer counts. Never returns names or emails.',
5332
+ inputSchema: {
5333
+ type: 'object',
5334
+ properties: {
5335
+ date_start: { type: 'string' },
5336
+ date_end: { type: 'string' },
5337
+ statuses: { type: 'array', items: { type: 'string' } },
5338
+ max_orders: { type: 'number' },
5339
+ },
5340
+ },
5341
+ readOnlyHint: true,
5342
+ },
5343
+ {
5344
+ name: 'woocommerce_get_store_configuration',
5345
+ description: 'Read sanitized WooCommerce currency, timezone, tax, units, checkout, page, and HPOS configuration. Credentials and secrets are never returned.',
5346
+ inputSchema: { type: 'object', properties: {} },
5347
+ readOnlyHint: true,
5348
+ },
5349
+ {
5350
+ name: 'woocommerce_list_payment_gateways',
5351
+ description: 'List payment gateway IDs, public titles, enabled state, and supported features without settings, credentials, or tokens.',
5352
+ inputSchema: { type: 'object', properties: {} },
5353
+ readOnlyHint: true,
5354
+ },
5355
+ {
5356
+ name: 'woocommerce_list_shipping_zones',
5357
+ description: 'List WooCommerce shipping zones, locations, and public method state.',
5358
+ inputSchema: { type: 'object', properties: {} },
5359
+ readOnlyHint: true,
5360
+ },
5361
+ {
5362
+ name: 'woocommerce_list_tax_rates',
5363
+ description: 'List WooCommerce tax rates for a tax class without exposing sensitive configuration.',
5364
+ inputSchema: {
5365
+ type: 'object',
5366
+ properties: { tax_class: { type: 'string', description: 'Empty for standard rates.' } },
5367
+ },
5368
+ readOnlyHint: true,
5369
+ },
5370
+ {
5371
+ name: 'woocommerce_list_webhooks',
5372
+ description: 'List native WooCommerce webhooks. Secrets are never returned.',
5373
+ inputSchema: {
5374
+ type: 'object',
5375
+ properties: { page: { type: 'number' }, per_page: { type: 'number' } },
5376
+ },
5377
+ readOnlyHint: true,
5378
+ },
5379
+ {
5380
+ name: 'woocommerce_get_webhook',
5381
+ description: 'Read one native WooCommerce webhook without its secret.',
5382
+ inputSchema: {
5383
+ type: 'object',
5384
+ properties: { id: { type: 'number' } },
5385
+ required: ['id'],
5386
+ },
5387
+ readOnlyHint: true,
5388
+ },
5389
+ {
5390
+ name: 'woocommerce_create_webhook',
5391
+ description: 'Create a native WooCommerce webhook. Requires an approval-token round trip, an allowlisted topic, and a public HTTPS target. Secret is write-only.',
5392
+ inputSchema: {
5393
+ type: 'object',
5394
+ properties: {
5395
+ name: { type: 'string' },
5396
+ topic: { type: 'string' },
5397
+ delivery_url: { type: 'string' },
5398
+ secret: { type: 'string' },
5399
+ approval_token: { type: 'string' },
5400
+ },
5401
+ required: ['topic', 'delivery_url'],
5402
+ },
5403
+ },
5404
+ {
5405
+ name: 'woocommerce_update_webhook',
5406
+ description: 'Update a native WooCommerce webhook through an approval-token round trip. Targets must remain HTTPS and secrets remain write-only.',
5407
+ inputSchema: {
5408
+ type: 'object',
5409
+ properties: {
5410
+ id: { type: 'number' },
5411
+ name: { type: 'string' },
5412
+ topic: { type: 'string' },
5413
+ delivery_url: { type: 'string' },
5414
+ status: { type: 'string', enum: ['active', 'paused', 'disabled'] },
5415
+ secret: { type: 'string' },
5416
+ approval_token: { type: 'string' },
5417
+ },
5418
+ required: ['id'],
5419
+ },
5420
+ idempotentHint: true,
5421
+ },
5422
+ {
5423
+ name: 'woocommerce_delete_webhook',
5424
+ description: 'Delete a native WooCommerce webhook through an approval-token round trip.',
5425
+ inputSchema: {
5426
+ type: 'object',
5427
+ properties: { id: { type: 'number' }, approval_token: { type: 'string' } },
5428
+ required: ['id'],
5429
+ },
5430
+ destructiveHint: true,
5431
+ },
5432
+ {
5433
+ name: 'woocommerce_test_webhook',
5434
+ description: 'Send a rate-limited redacted test payload to a webhook target through an approval-token round trip. Test payloads are not stored.',
5435
+ inputSchema: {
5436
+ type: 'object',
5437
+ properties: { id: { type: 'number' }, approval_token: { type: 'string' } },
5438
+ required: ['id'],
5439
+ },
5440
+ },
4919
5441
  // --- Brands (addon v3.0) ---
4920
5442
  {
4921
5443
  name: 'woocommerce_list_brands',
@@ -5120,7 +5642,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5120
5642
  // --- Storefront intelligence (addon v3.0 exposes existing REST tools) ---
5121
5643
  {
5122
5644
  name: 'woocommerce_analyze_shop_page',
5123
- description: 'Analyze the shop page through the page-builder layer: product grids, hierarchy score, issues, recommendations.',
5645
+ description: 'Analyze the shop page: product grids, hierarchy score, issues, recommendations. Works on a block theme by reading the native archive-product template (Product Collection / Product Template blocks), and falls back to the page-builder layer on builder-built shops. A pure FSE storefront is supported, not a fallback.',
5124
5646
  inputSchema: {
5125
5647
  type: 'object',
5126
5648
  properties: {
@@ -5143,7 +5665,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5143
5665
  },
5144
5666
  {
5145
5667
  name: 'woocommerce_update_product_card_layout',
5146
- description: 'Change product grid layout (columns, rows, ordering) on archive pages through the page-builder layer. Snapshots; dry_run supported.',
5668
+ description: 'Change product grid layout (columns, rows, ordering) on archive pages. On a block theme this edits the native archive-product template by exact block path, fingerprint-guarded and verified after the write; on builder-built shops it falls back to the page-builder layer. Snapshots; dry_run supported.',
5147
5669
  inputSchema: {
5148
5670
  type: 'object',
5149
5671
  properties: {
@@ -5156,7 +5678,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5156
5678
  },
5157
5679
  {
5158
5680
  name: 'woocommerce_add_low_stock_badge',
5159
- description: 'Find products under a stock threshold and produce badge data (e.g. "Only 3 left") for product cards.',
5681
+ description: 'Preview or add a low-stock badge to WooCommerce product cards. Block themes only: this writes into the native archive-product template and has no page-builder path. Use dry_run=true to inspect affected products without writing. A non-dry-run call succeeds only after the badge is inserted and verified; an unsupported template returns an explicit error and never reports a false success.',
5160
5682
  inputSchema: {
5161
5683
  type: 'object',
5162
5684
  properties: {
@@ -5167,11 +5689,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5167
5689
  dry_run: { type: 'boolean' },
5168
5690
  },
5169
5691
  },
5170
- readOnlyHint: true,
5171
5692
  },
5172
5693
  {
5173
5694
  name: 'woocommerce_add_sale_badge',
5174
- description: 'List on-sale products with computed discount percentages and badge data for product cards.',
5695
+ description: 'Preview or add a sale badge to WooCommerce product cards. Block themes only: this writes into the native archive-product template and has no page-builder path. Requires the WooCommerce sale-badge block to be registered on the site. Use dry_run=true to inspect on-sale products. A non-dry-run call succeeds only after the template is changed and verified; an unsupported template returns an explicit error without mutation.',
5175
5696
  inputSchema: {
5176
5697
  type: 'object',
5177
5698
  properties: {
@@ -5179,11 +5700,32 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5179
5700
  dry_run: { type: 'boolean' },
5180
5701
  },
5181
5702
  },
5703
+ },
5704
+ {
5705
+ name: 'woocommerce_analyze_storefront_card',
5706
+ description: 'Report the field composition of the WooCommerce product card on a block theme: which canonical blocks it is built from (woocommerce/product-image, product-title, product-price, product-button, and so on), their exact block paths, and their render order. Read-only. Call this before update_storefront_card_field so you address a field that actually exists.',
5707
+ inputSchema: {
5708
+ type: 'object',
5709
+ properties: {},
5710
+ },
5182
5711
  readOnlyHint: true,
5183
5712
  },
5713
+ {
5714
+ name: 'woocommerce_update_storefront_card_field',
5715
+ description: 'Set attributes on one named field of the WooCommerce product card, addressed by its CANONICAL block name (for example woocommerce/product-image or woocommerce/product-price), on a block theme. Requested attributes are intersected with the attributes the installed block actually registers, so an unknown key is refused rather than written and reported as success. Snapshot, fingerprint guard, dry_run and render verification all apply.',
5716
+ inputSchema: {
5717
+ type: 'object',
5718
+ properties: {
5719
+ field: { type: 'string', description: 'Canonical block name, e.g. "woocommerce/product-image". Use analyze_storefront_card to list what this card has.' },
5720
+ attributes: { type: 'object', description: 'Attributes to set on that block.' },
5721
+ dry_run: { type: 'boolean' },
5722
+ },
5723
+ required: ['field', 'attributes'],
5724
+ },
5725
+ },
5184
5726
  {
5185
5727
  name: 'woocommerce_update_checkout_layout',
5186
- description: 'Apply layout changes to the checkout page through the page-builder layer. Snapshots; dry_run supported.',
5728
+ description: 'Preview or apply targeted checkout layout changes. Use dry_run=true first. The tool never reports success for intent-only or no-op writes; unsupported layouts return respira_woo_fse_write_not_supported without changing checkout content.',
5187
5729
  inputSchema: {
5188
5730
  type: 'object',
5189
5731
  properties: {
@@ -5783,13 +6325,24 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5783
6325
  },
5784
6326
  {
5785
6327
  name: 'woocommerce_get_feed_status',
5786
- description: 'Per-format feed URLs, row counts, generation times, running build progress, and wp-cron health warnings.',
6328
+ description: 'Per-format feed URLs, row counts, generation times, running build progress, Action Scheduler health, last successful build, pending/failed/overdue actions, and stale-lock state. This tool is read-only.',
5787
6329
  inputSchema: {
5788
6330
  type: 'object',
5789
6331
  properties: {},
5790
6332
  },
5791
6333
  readOnlyHint: true,
5792
6334
  },
6335
+ {
6336
+ name: 'woocommerce_repair_feed_scheduler',
6337
+ description: 'Safely clear a confirmed-stale Respira feed lock and idempotently resume the existing build. Does not delete Action Scheduler history. Returns a verified mutation envelope; returns a non-success response when no stale lock exists.',
6338
+ inputSchema: {
6339
+ type: 'object',
6340
+ properties: {
6341
+ dry_run: { type: 'boolean', description: 'Inspect whether a stale lock would be repaired without changing scheduler state.' },
6342
+ },
6343
+ },
6344
+ idempotentHint: true,
6345
+ },
5793
6346
  {
5794
6347
  name: 'woocommerce_validate_feed',
5795
6348
  description: 'Check a catalog sample against one feed format\'s requirements (identifiers, images, descriptions, titles, category mapping) with per-check failing product IDs, so the catalog tools can fix them.',
@@ -6146,6 +6699,8 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6146
6699
  return await client.getDiviMigrationReadiness();
6147
6700
  case 'wordpress_abilities_gap_report':
6148
6701
  return await client.getAbilitiesGapReport();
6702
+ case 'wordpress_search_abilities':
6703
+ return await client.searchAbilities(args);
6149
6704
  case 'wordpress_invoke_ability':
6150
6705
  return await client.invokeInhaledAbility(args?.ability, args?.args || {});
6151
6706
  case 'wordpress_list_pages':
@@ -6227,6 +6782,9 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6227
6782
  return await client.updateThemeBuilderTemplate({
6228
6783
  layout_id: args.layout_id,
6229
6784
  structure: args.structure,
6785
+ // Accept the camelCase and bare-`confirmed` spellings too: agents
6786
+ // reliably send those, and the plugin already normalises all three.
6787
+ confirm_live_edit: args.confirm_live_edit ?? args.confirmLiveEdit ?? args.confirmed,
6230
6788
  });
6231
6789
  case 'wordpress_build_mega_menu':
6232
6790
  return await client.buildMegaMenu({
@@ -6453,7 +7011,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6453
7011
  case 'wordpress_install_plugin':
6454
7012
  return await client.installPlugin(args.slug_or_url, args.source || 'wordpress.org', args.approval_token);
6455
7013
  case 'wordpress_activate_plugin':
6456
- return await client.activatePlugin(args.slug, args.approval_token);
7014
+ return await client.activatePlugin(args.slug, args.approval_token, args.force_without_probe);
6457
7015
  case 'wordpress_deactivate_plugin':
6458
7016
  return await client.deactivatePlugin(args.slug, args.approval_token);
6459
7017
  case 'wordpress_update_plugin':
@@ -6622,6 +7180,52 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6622
7180
  return await client.callRestV2('POST', '/snapshots/session/begin', {});
6623
7181
  case 'wordpress_end_session':
6624
7182
  return await client.callRestV2('POST', '/snapshots/session/end', {});
7183
+ case 'wordpress_list_site_templates':
7184
+ return await client.callRestV2('GET', '/fse/templates', args);
7185
+ case 'wordpress_list_activity':
7186
+ return await client.callRestV1('GET', '/activity', args);
7187
+ case 'wordpress_get_activity':
7188
+ return await client.callRestV1('GET', `/activity/${args.id}`);
7189
+ case 'wordpress_get_site_template':
7190
+ return await client.callRestV2('GET', '/fse/template', args);
7191
+ case 'wordpress_create_site_template':
7192
+ return await client.callRestV2('POST', '/fse/templates', args);
7193
+ case 'wordpress_update_site_template':
7194
+ return await client.callRestV2('PUT', '/fse/template', args);
7195
+ case 'wordpress_reset_site_template':
7196
+ return await client.callRestV2('DELETE', '/fse/template', args);
7197
+ case 'wordpress_list_site_patterns':
7198
+ return await client.callRestV2('GET', '/fse/patterns', args);
7199
+ case 'wordpress_get_site_pattern':
7200
+ return await client.callRestV2('GET', '/fse/pattern', args);
7201
+ case 'wordpress_create_site_pattern':
7202
+ return await client.callRestV2('POST', '/fse/patterns', args);
7203
+ case 'wordpress_update_site_pattern':
7204
+ return await client.callRestV2('PUT', '/fse/pattern', args);
7205
+ case 'wordpress_delete_site_pattern':
7206
+ return await client.callRestV2('DELETE', '/fse/pattern', args);
7207
+ case 'wordpress_list_site_navigations':
7208
+ return await client.callRestV2('GET', '/fse/navigations', args);
7209
+ case 'wordpress_get_site_navigation':
7210
+ return await client.callRestV2('GET', '/fse/navigation', args);
7211
+ case 'wordpress_create_site_navigation':
7212
+ return await client.callRestV2('POST', '/fse/navigations', args);
7213
+ case 'wordpress_update_site_navigation':
7214
+ return await client.callRestV2('PUT', '/fse/navigation', args);
7215
+ case 'wordpress_delete_site_navigation':
7216
+ return await client.callRestV2('DELETE', '/fse/navigation', args);
7217
+ case 'wordpress_list_design_tokens':
7218
+ return await client.callRestV2('GET', `/design-tokens/${encodeURIComponent(args.type)}`);
7219
+ case 'wordpress_create_design_token': {
7220
+ const { type, ...token } = args;
7221
+ return await client.callRestV2('POST', `/design-tokens/${encodeURIComponent(type)}`, token);
7222
+ }
7223
+ case 'wordpress_update_design_token': {
7224
+ const { type, id, ...patch } = args;
7225
+ return await client.callRestV2('PUT', `/design-tokens/${encodeURIComponent(type)}/${encodeURIComponent(id)}`, patch);
7226
+ }
7227
+ case 'wordpress_delete_design_token':
7228
+ return await client.callRestV2('DELETE', `/design-tokens/${encodeURIComponent(args.type)}/${encodeURIComponent(args.id)}`, args);
6625
7229
  case 'wordpress_apply_builder_patch':
6626
7230
  return await client.applyBuilderPatch(args.builder, args.post_id, args.operations, args.include, args.edit_target);
6627
7231
  case 'woocommerce_list_products':
@@ -6674,6 +7278,38 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6674
7278
  }
6675
7279
  case 'woocommerce_sales_report':
6676
7280
  return await client.woocommerceSalesReport(args);
7281
+ case 'woocommerce_revenue_summary':
7282
+ return await client.callRestV1('GET', '/woocommerce/reports/revenue-summary', args);
7283
+ case 'woocommerce_sales_timeseries':
7284
+ return await client.callRestV1('GET', '/woocommerce/reports/sales-timeseries', args);
7285
+ case 'woocommerce_top_products':
7286
+ return await client.callRestV1('GET', '/woocommerce/reports/top-products', args);
7287
+ case 'woocommerce_orders_summary':
7288
+ return await client.callRestV1('GET', '/woocommerce/reports/orders-summary', args);
7289
+ case 'woocommerce_customers_summary':
7290
+ return await client.callRestV1('GET', '/woocommerce/reports/customers-summary', args);
7291
+ case 'woocommerce_get_store_configuration':
7292
+ return await client.callRestV1('GET', '/woocommerce/configuration/store');
7293
+ case 'woocommerce_list_payment_gateways':
7294
+ return await client.callRestV1('GET', '/woocommerce/configuration/payment-gateways');
7295
+ case 'woocommerce_list_shipping_zones':
7296
+ return await client.callRestV1('GET', '/woocommerce/configuration/shipping-zones');
7297
+ case 'woocommerce_list_tax_rates':
7298
+ return await client.callRestV1('GET', '/woocommerce/configuration/tax-rates', args);
7299
+ case 'woocommerce_list_webhooks':
7300
+ return await client.callRestV1('GET', '/woocommerce/webhooks', args);
7301
+ case 'woocommerce_get_webhook':
7302
+ return await client.callRestV1('GET', `/woocommerce/webhooks/${args.id}`);
7303
+ case 'woocommerce_create_webhook':
7304
+ return await client.callRestV1('POST', '/woocommerce/webhooks', args);
7305
+ case 'woocommerce_update_webhook': {
7306
+ const { id, ...payload } = args;
7307
+ return await client.callRestV1('PUT', `/woocommerce/webhooks/${id}`, payload);
7308
+ }
7309
+ case 'woocommerce_delete_webhook':
7310
+ return await client.callRestV1('DELETE', `/woocommerce/webhooks/${args.id}`, { approval_token: args.approval_token });
7311
+ case 'woocommerce_test_webhook':
7312
+ return await client.callRestV1('POST', `/woocommerce/webhooks/${args.id}/test`, { approval_token: args.approval_token });
6677
7313
  // --- WooCommerce Add-on v3.0 ---
6678
7314
  case 'woocommerce_list_brands':
6679
7315
  return await client.woocommerceListBrands(args);
@@ -6717,6 +7353,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6717
7353
  return await client.woocommerceAddSaleBadge(args);
6718
7354
  case 'woocommerce_update_checkout_layout':
6719
7355
  return await client.woocommerceUpdateCheckoutLayout(args);
7356
+ case 'woocommerce_analyze_storefront_card':
7357
+ return await client.woocommerceAnalyzeStorefrontCard(args);
7358
+ case 'woocommerce_update_storefront_card_field':
7359
+ return await client.woocommerceUpdateStorefrontCardField(args);
6720
7360
  case 'woocommerce_set_product_attributes': {
6721
7361
  const { id, ...payload } = args;
6722
7362
  return await client.woocommerceSetProductAttributes(id, payload);
@@ -6841,6 +7481,8 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6841
7481
  return await client.woocommerceGenerateFeed(args);
6842
7482
  case 'woocommerce_get_feed_status':
6843
7483
  return await client.woocommerceGetFeedStatus();
7484
+ case 'woocommerce_repair_feed_scheduler':
7485
+ return await client.woocommerceRepairFeedScheduler(args);
6844
7486
  case 'woocommerce_validate_feed':
6845
7487
  return await client.woocommerceValidateFeed(args);
6846
7488
  case 'woocommerce_set_feed_category_mapping':
@@ -6892,11 +7534,26 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6892
7534
  return r;
6893
7535
  }
6894
7536
  case 'wordpress_move_element': {
6895
- const { post_id, ...rest } = args;
6896
- return await client.callRestV2('POST', `/builder/elements/move/${post_id}`, rest);
7537
+ // Same edit_target/editTarget normalization as update_element: the
7538
+ // plugin's next_call_examples suggests camelCase editTarget, agents
7539
+ // may send either, the plugin reads editTarget first. Before this fix
7540
+ // neither param was in the schema at all, so strict MCP clients
7541
+ // rejected the confirmation-handshake retry and live moves could
7542
+ // never complete (C.Y., Mainely Social).
7543
+ const { post_id, edit_target, editTarget, ...rest } = args;
7544
+ const resolvedEditTarget = edit_target ?? editTarget;
7545
+ const payload = { ...rest };
7546
+ if (resolvedEditTarget !== undefined) {
7547
+ payload.editTarget = resolvedEditTarget;
7548
+ }
7549
+ return await client.callRestV2('POST', `/builder/elements/move/${post_id}`, payload);
6897
7550
  }
6898
7551
  case 'wordpress_duplicate_element': {
6899
- const { post_id, ...rest } = args;
7552
+ const { post_id, edit_target, editTarget, ...rest } = args;
7553
+ const resolvedEditTarget = edit_target ?? editTarget;
7554
+ if (resolvedEditTarget !== undefined) {
7555
+ rest.editTarget = resolvedEditTarget;
7556
+ }
6900
7557
  // Pre-mcp-6.19.7 the tool exposed a single `element_id` arg, but the
6901
7558
  // plugin route /builder/elements/duplicate/{id} has always required
6902
7559
  // identifier_type + identifier_value (it inherits the same auth and
@@ -6913,15 +7570,27 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6913
7570
  return await client.callRestV2('POST', `/builder/elements/duplicate/${post_id}`, rest);
6914
7571
  }
6915
7572
  case 'wordpress_remove_element': {
6916
- const { post_id, ...rest } = args;
7573
+ const { post_id, edit_target, editTarget, ...rest } = args;
7574
+ const resolvedEditTarget = edit_target ?? editTarget;
7575
+ if (resolvedEditTarget !== undefined) {
7576
+ rest.editTarget = resolvedEditTarget;
7577
+ }
6917
7578
  return await client.callRestV2('POST', `/builder/elements/remove/${post_id}`, rest);
6918
7579
  }
6919
7580
  case 'wordpress_batch_update': {
6920
- const { post_id, ...rest } = args;
7581
+ const { post_id, edit_target, editTarget, ...rest } = args;
7582
+ const resolvedEditTarget = edit_target ?? editTarget;
7583
+ if (resolvedEditTarget !== undefined) {
7584
+ rest.editTarget = resolvedEditTarget;
7585
+ }
6921
7586
  return await client.callRestV2('POST', `/builder/elements/batch/${post_id}`, rest);
6922
7587
  }
6923
7588
  case 'wordpress_reorder_elements': {
6924
- const { post_id, ...rest } = args;
7589
+ const { post_id, edit_target, editTarget, ...rest } = args;
7590
+ const resolvedEditTarget = edit_target ?? editTarget;
7591
+ if (resolvedEditTarget !== undefined) {
7592
+ rest.editTarget = resolvedEditTarget;
7593
+ }
6925
7594
  return await client.callRestV2('POST', `/builder/elements/reorder/${post_id}`, rest);
6926
7595
  }
6927
7596
  case 'wordpress_build_page':
@@ -7051,7 +7720,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7051
7720
  },
7052
7721
  {
7053
7722
  name: 'wordpress_move_element',
7054
- description: 'Move an element to a different container or position within the page. Locate the element using the same identifier_type/identifier_value pattern as respira_find_element / respira_remove_element. The destination is a container PATH (e.g. "0.1" for sections[0].rows[1], or "root"/empty for top level), not a container element id.',
7723
+ description: 'Move an element to a different container or position within the page. Locate the element using the same identifier_type/identifier_value pattern as respira_find_element / respira_remove_element. The destination is a container PATH (e.g. "0.1" for sections[0].rows[1], or "root"/empty for top level), not a container element id.\n\nLive-edit confirmation: when writing to a published original, the first call can return `status: "confirmation_required"` with a `next_call_examples` payload. Re-call with `edit_target` (and `confirm_live_edit: true` for the live path) to acknowledge. Both params are exposed at the top level here; earlier schemas omitted them, so agents saw the handshake but could never complete it (C.Y., Elementor, bug: infinite confirmation loop).',
7055
7724
  inputSchema: {
7056
7725
  type: 'object',
7057
7726
  properties: {
@@ -7073,6 +7742,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7073
7742
  type: 'number',
7074
7743
  description: 'Position index within the target container (0-based). Pass -1 to append.',
7075
7744
  },
7745
+ edit_target: {
7746
+ type: 'string',
7747
+ enum: ['live', 'duplicate'],
7748
+ description: 'Where to apply the write. "duplicate" (default) routes the edit to the Respira duplicate of the original (or auto-creates one). "live" writes straight to the published original (requires Respira → Settings → Allow direct edit, or the original to be a draft / existing duplicate).',
7749
+ },
7750
+ editTarget: {
7751
+ type: 'string',
7752
+ enum: ['live', 'duplicate'],
7753
+ description: 'CamelCase alias of edit_target (matches the plugin\'s next_call_examples payload). Prefer edit_target.',
7754
+ },
7755
+ confirm_live_edit: {
7756
+ type: 'boolean',
7757
+ description: 'Required when responding to a `confirmation_required` reply on the live path. Pass `true` alongside `edit_target: "live"` to acknowledge the published-original write.',
7758
+ },
7076
7759
  },
7077
7760
  required: ['post_id', 'identifier_type', 'identifier_value', 'target_container_path', 'position'],
7078
7761
  },
@@ -7097,6 +7780,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7097
7780
  type: 'string',
7098
7781
  description: 'DEPRECATED — pre-mcp-6.19.7 single-arg form. Equivalent to identifier_type:"id" + identifier_value:<this>. Kept for back-compat; new callers should use the explicit pair.',
7099
7782
  },
7783
+ edit_target: {
7784
+ type: 'string',
7785
+ enum: ['live', 'duplicate'],
7786
+ description: 'Where to apply the write. "duplicate" (default) routes the edit to the Respira duplicate of the original (or auto-creates one). "live" writes straight to the published original (requires Respira → Settings → Allow direct edit, or the original to be a draft / existing duplicate). Needed to complete a `confirmation_required` handshake.',
7787
+ },
7788
+ editTarget: {
7789
+ type: 'string',
7790
+ enum: ['live', 'duplicate'],
7791
+ description: 'CamelCase alias of edit_target (matches the plugin\'s next_call_examples payload). Prefer edit_target.',
7792
+ },
7793
+ confirm_live_edit: {
7794
+ type: 'boolean',
7795
+ description: 'Pass `true` alongside `edit_target: "live"` to acknowledge a published-original write when the first call returned `confirmation_required`.',
7796
+ },
7100
7797
  },
7101
7798
  required: ['post_id'],
7102
7799
  },
@@ -7117,6 +7814,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7117
7814
  type: 'string',
7118
7815
  description: 'Value matching the chosen identifier_type (e.g. the element ID, the class name, the text to match).',
7119
7816
  },
7817
+ edit_target: {
7818
+ type: 'string',
7819
+ enum: ['live', 'duplicate'],
7820
+ description: 'Where to apply the write. "duplicate" (default) routes the edit to the Respira duplicate of the original (or auto-creates one). "live" writes straight to the published original (requires Respira → Settings → Allow direct edit, or the original to be a draft / existing duplicate). Needed to complete a `confirmation_required` handshake.',
7821
+ },
7822
+ editTarget: {
7823
+ type: 'string',
7824
+ enum: ['live', 'duplicate'],
7825
+ description: 'CamelCase alias of edit_target (matches the plugin\'s next_call_examples payload). Prefer edit_target.',
7826
+ },
7827
+ confirm_live_edit: {
7828
+ type: 'boolean',
7829
+ description: 'Pass `true` alongside `edit_target: "live"` to acknowledge a published-original write when the first call returned `confirmation_required`.',
7830
+ },
7120
7831
  },
7121
7832
  required: ['post_id', 'identifier_type', 'identifier_value'],
7122
7833
  },
@@ -7146,13 +7857,27 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7146
7857
  },
7147
7858
  },
7148
7859
  },
7860
+ edit_target: {
7861
+ type: 'string',
7862
+ enum: ['live', 'duplicate'],
7863
+ description: 'Where to apply the write. "duplicate" (default) routes the edit to the Respira duplicate of the original (or auto-creates one). "live" writes straight to the published original (requires Respira → Settings → Allow direct edit, or the original to be a draft / existing duplicate). Needed to complete a `confirmation_required` handshake.',
7864
+ },
7865
+ editTarget: {
7866
+ type: 'string',
7867
+ enum: ['live', 'duplicate'],
7868
+ description: 'CamelCase alias of edit_target (matches the plugin\'s next_call_examples payload). Prefer edit_target.',
7869
+ },
7870
+ confirm_live_edit: {
7871
+ type: 'boolean',
7872
+ description: 'Pass `true` alongside `edit_target: "live"` to acknowledge a published-original write when the first call returned `confirmation_required`.',
7873
+ },
7149
7874
  },
7150
7875
  required: ['post_id', 'operations'],
7151
7876
  },
7152
7877
  },
7153
7878
  {
7154
7879
  name: 'wordpress_reorder_elements',
7155
- description: 'Reorder child elements within a container. The container is identified by its PATH inside the page (e.g. "0.1" for sections[0].rows[1], or "root"/"" for the top level).',
7880
+ description: 'Reorder child elements within a container. The container is identified by its PATH inside the page (e.g. "0.1" for sections[0].rows[1], or "root"/"" for the top level).\n\nLive-edit confirmation: when writing to a published original, the first call can return `status: "confirmation_required"`. Re-call with `edit_target` (and `confirm_live_edit: true` for the live path) to acknowledge. Both params are exposed at the top level here; earlier schemas omitted them, so agents could never complete the handshake.',
7156
7881
  inputSchema: {
7157
7882
  type: 'object',
7158
7883
  properties: {
@@ -7166,6 +7891,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7166
7891
  description: 'Array of element IDs in the desired order.',
7167
7892
  items: { type: 'string' },
7168
7893
  },
7894
+ edit_target: {
7895
+ type: 'string',
7896
+ enum: ['live', 'duplicate'],
7897
+ description: 'Where to apply the write. "duplicate" (default) routes the edit to the Respira duplicate of the original (or auto-creates one). "live" writes straight to the published original (requires Respira → Settings → Allow direct edit, or the original to be a draft / existing duplicate).',
7898
+ },
7899
+ editTarget: {
7900
+ type: 'string',
7901
+ enum: ['live', 'duplicate'],
7902
+ description: 'CamelCase alias of edit_target (matches the plugin\'s next_call_examples payload). Prefer edit_target.',
7903
+ },
7904
+ confirm_live_edit: {
7905
+ type: 'boolean',
7906
+ description: 'Required when responding to a `confirmation_required` reply on the live path. Pass `true` alongside `edit_target: "live"` to acknowledge the published-original write.',
7907
+ },
7169
7908
  },
7170
7909
  required: ['post_id', 'container_path', 'new_order'],
7171
7910
  },