@respira/wordpress-mcp-server 7.6.2 → 8.0.1

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 (35) hide show
  1. package/README.md +43 -23
  2. package/TOOL_CATALOG.md +288 -0
  3. package/dist/__tests__/config-path-expansion.test.d.ts +2 -0
  4. package/dist/__tests__/config-path-expansion.test.d.ts.map +1 -0
  5. package/dist/__tests__/config-path-expansion.test.js +63 -0
  6. package/dist/__tests__/config-path-expansion.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 +26 -0
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/config.js +80 -9
  20. package/dist/config.js.map +1 -1
  21. package/dist/elementor-tools.js +2 -2
  22. package/dist/elementor-tools.js.map +1 -1
  23. package/dist/server.d.ts.map +1 -1
  24. package/dist/server.js +750 -19
  25. package/dist/server.js.map +1 -1
  26. package/dist/usage-emitter.d.ts +7 -0
  27. package/dist/usage-emitter.d.ts.map +1 -1
  28. package/dist/usage-emitter.js +34 -0
  29. package/dist/usage-emitter.js.map +1 -1
  30. package/dist/wordpress-client.d.ts +53 -42
  31. package/dist/wordpress-client.d.ts.map +1 -1
  32. package/dist/wordpress-client.js +105 -94
  33. package/dist/wordpress-client.js.map +1 -1
  34. package/package.json +5 -3
  35. 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" } }] }.',
@@ -3031,7 +3371,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
3031
3371
  },
3032
3372
  {
3033
3373
  name: 'wordpress_activate_plugin',
3034
- 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.',
3035
3375
  inputSchema: {
3036
3376
  type: 'object',
3037
3377
  properties: {
@@ -3043,6 +3383,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
3043
3383
  type: 'string',
3044
3384
  description: 'Second-step approval token returned by the first call. Echo it back unchanged with the same slug to complete activation.',
3045
3385
  },
3386
+ force_without_probe: {
3387
+ type: 'boolean',
3388
+ description: 'High-risk override for hosts that block loopback verification. Default false.',
3389
+ },
3046
3390
  },
3047
3391
  required: ['slug'],
3048
3392
  },
@@ -4913,7 +5257,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
4913
5257
  },
4914
5258
  {
4915
5259
  name: 'woocommerce_sales_report',
4916
- 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.',
4917
5261
  inputSchema: {
4918
5262
  type: 'object',
4919
5263
  properties: {
@@ -4924,6 +5268,176 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
4924
5268
  },
4925
5269
  readOnlyHint: true,
4926
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
+ },
4927
5441
  // --- Brands (addon v3.0) ---
4928
5442
  {
4929
5443
  name: 'woocommerce_list_brands',
@@ -5128,7 +5642,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5128
5642
  // --- Storefront intelligence (addon v3.0 exposes existing REST tools) ---
5129
5643
  {
5130
5644
  name: 'woocommerce_analyze_shop_page',
5131
- 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.',
5132
5646
  inputSchema: {
5133
5647
  type: 'object',
5134
5648
  properties: {
@@ -5151,7 +5665,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5151
5665
  },
5152
5666
  {
5153
5667
  name: 'woocommerce_update_product_card_layout',
5154
- 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.',
5155
5669
  inputSchema: {
5156
5670
  type: 'object',
5157
5671
  properties: {
@@ -5164,7 +5678,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5164
5678
  },
5165
5679
  {
5166
5680
  name: 'woocommerce_add_low_stock_badge',
5167
- 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.',
5168
5682
  inputSchema: {
5169
5683
  type: 'object',
5170
5684
  properties: {
@@ -5175,11 +5689,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5175
5689
  dry_run: { type: 'boolean' },
5176
5690
  },
5177
5691
  },
5178
- readOnlyHint: true,
5179
5692
  },
5180
5693
  {
5181
5694
  name: 'woocommerce_add_sale_badge',
5182
- 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.',
5183
5696
  inputSchema: {
5184
5697
  type: 'object',
5185
5698
  properties: {
@@ -5187,11 +5700,32 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5187
5700
  dry_run: { type: 'boolean' },
5188
5701
  },
5189
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
+ },
5190
5711
  readOnlyHint: true,
5191
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
+ },
5192
5726
  {
5193
5727
  name: 'woocommerce_update_checkout_layout',
5194
- 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.',
5195
5729
  inputSchema: {
5196
5730
  type: 'object',
5197
5731
  properties: {
@@ -5791,13 +6325,24 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
5791
6325
  },
5792
6326
  {
5793
6327
  name: 'woocommerce_get_feed_status',
5794
- 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.',
5795
6329
  inputSchema: {
5796
6330
  type: 'object',
5797
6331
  properties: {},
5798
6332
  },
5799
6333
  readOnlyHint: true,
5800
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
+ },
5801
6346
  {
5802
6347
  name: 'woocommerce_validate_feed',
5803
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.',
@@ -6154,6 +6699,8 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6154
6699
  return await client.getDiviMigrationReadiness();
6155
6700
  case 'wordpress_abilities_gap_report':
6156
6701
  return await client.getAbilitiesGapReport();
6702
+ case 'wordpress_search_abilities':
6703
+ return await client.searchAbilities(args);
6157
6704
  case 'wordpress_invoke_ability':
6158
6705
  return await client.invokeInhaledAbility(args?.ability, args?.args || {});
6159
6706
  case 'wordpress_list_pages':
@@ -6235,6 +6782,9 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6235
6782
  return await client.updateThemeBuilderTemplate({
6236
6783
  layout_id: args.layout_id,
6237
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,
6238
6788
  });
6239
6789
  case 'wordpress_build_mega_menu':
6240
6790
  return await client.buildMegaMenu({
@@ -6461,7 +7011,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6461
7011
  case 'wordpress_install_plugin':
6462
7012
  return await client.installPlugin(args.slug_or_url, args.source || 'wordpress.org', args.approval_token);
6463
7013
  case 'wordpress_activate_plugin':
6464
- return await client.activatePlugin(args.slug, args.approval_token);
7014
+ return await client.activatePlugin(args.slug, args.approval_token, args.force_without_probe);
6465
7015
  case 'wordpress_deactivate_plugin':
6466
7016
  return await client.deactivatePlugin(args.slug, args.approval_token);
6467
7017
  case 'wordpress_update_plugin':
@@ -6630,6 +7180,52 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6630
7180
  return await client.callRestV2('POST', '/snapshots/session/begin', {});
6631
7181
  case 'wordpress_end_session':
6632
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);
6633
7229
  case 'wordpress_apply_builder_patch':
6634
7230
  return await client.applyBuilderPatch(args.builder, args.post_id, args.operations, args.include, args.edit_target);
6635
7231
  case 'woocommerce_list_products':
@@ -6682,6 +7278,38 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6682
7278
  }
6683
7279
  case 'woocommerce_sales_report':
6684
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 });
6685
7313
  // --- WooCommerce Add-on v3.0 ---
6686
7314
  case 'woocommerce_list_brands':
6687
7315
  return await client.woocommerceListBrands(args);
@@ -6725,6 +7353,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6725
7353
  return await client.woocommerceAddSaleBadge(args);
6726
7354
  case 'woocommerce_update_checkout_layout':
6727
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);
6728
7360
  case 'woocommerce_set_product_attributes': {
6729
7361
  const { id, ...payload } = args;
6730
7362
  return await client.woocommerceSetProductAttributes(id, payload);
@@ -6849,6 +7481,8 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6849
7481
  return await client.woocommerceGenerateFeed(args);
6850
7482
  case 'woocommerce_get_feed_status':
6851
7483
  return await client.woocommerceGetFeedStatus();
7484
+ case 'woocommerce_repair_feed_scheduler':
7485
+ return await client.woocommerceRepairFeedScheduler(args);
6852
7486
  case 'woocommerce_validate_feed':
6853
7487
  return await client.woocommerceValidateFeed(args);
6854
7488
  case 'woocommerce_set_feed_category_mapping':
@@ -6900,11 +7534,26 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6900
7534
  return r;
6901
7535
  }
6902
7536
  case 'wordpress_move_element': {
6903
- const { post_id, ...rest } = args;
6904
- 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);
6905
7550
  }
6906
7551
  case 'wordpress_duplicate_element': {
6907
- 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
+ }
6908
7557
  // Pre-mcp-6.19.7 the tool exposed a single `element_id` arg, but the
6909
7558
  // plugin route /builder/elements/duplicate/{id} has always required
6910
7559
  // identifier_type + identifier_value (it inherits the same auth and
@@ -6921,15 +7570,27 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
6921
7570
  return await client.callRestV2('POST', `/builder/elements/duplicate/${post_id}`, rest);
6922
7571
  }
6923
7572
  case 'wordpress_remove_element': {
6924
- 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
+ }
6925
7578
  return await client.callRestV2('POST', `/builder/elements/remove/${post_id}`, rest);
6926
7579
  }
6927
7580
  case 'wordpress_batch_update': {
6928
- 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
+ }
6929
7586
  return await client.callRestV2('POST', `/builder/elements/batch/${post_id}`, rest);
6930
7587
  }
6931
7588
  case 'wordpress_reorder_elements': {
6932
- 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
+ }
6933
7594
  return await client.callRestV2('POST', `/builder/elements/reorder/${post_id}`, rest);
6934
7595
  }
6935
7596
  case 'wordpress_build_page':
@@ -7059,7 +7720,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7059
7720
  },
7060
7721
  {
7061
7722
  name: 'wordpress_move_element',
7062
- 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).',
7063
7724
  inputSchema: {
7064
7725
  type: 'object',
7065
7726
  properties: {
@@ -7081,6 +7742,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7081
7742
  type: 'number',
7082
7743
  description: 'Position index within the target container (0-based). Pass -1 to append.',
7083
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
+ },
7084
7759
  },
7085
7760
  required: ['post_id', 'identifier_type', 'identifier_value', 'target_container_path', 'position'],
7086
7761
  },
@@ -7105,6 +7780,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7105
7780
  type: 'string',
7106
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.',
7107
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
+ },
7108
7797
  },
7109
7798
  required: ['post_id'],
7110
7799
  },
@@ -7125,6 +7814,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7125
7814
  type: 'string',
7126
7815
  description: 'Value matching the chosen identifier_type (e.g. the element ID, the class name, the text to match).',
7127
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
+ },
7128
7831
  },
7129
7832
  required: ['post_id', 'identifier_type', 'identifier_value'],
7130
7833
  },
@@ -7154,13 +7857,27 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7154
7857
  },
7155
7858
  },
7156
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
+ },
7157
7874
  },
7158
7875
  required: ['post_id', 'operations'],
7159
7876
  },
7160
7877
  },
7161
7878
  {
7162
7879
  name: 'wordpress_reorder_elements',
7163
- 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.',
7164
7881
  inputSchema: {
7165
7882
  type: 'object',
7166
7883
  properties: {
@@ -7174,6 +7891,20 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
7174
7891
  description: 'Array of element IDs in the desired order.',
7175
7892
  items: { type: 'string' },
7176
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
+ },
7177
7908
  },
7178
7909
  required: ['post_id', 'container_path', 'new_order'],
7179
7910
  },