# WooCommerce Bulk Tools

> Reference for the 6 WooCommerce bulk tools in Royal MCP Pro: price updates, product edits, stock, categories, order status and deletes, each with 72h undo.

- Canonical: <https://royalplugins.com/support/royal-mcp-pro/woocommerce-bulk-tools/>
- Last updated: 2026-09-20
- HTML version: <https://royalplugins.com/support/royal-mcp-pro/woocommerce-bulk-tools/>

---

Complete reference for the 6 WooCommerce bulk operation tools in Royal MCP Pro. Bulk price updates, product edits, stock changes, category assignment, and order status transitions. Every write returns a 72-hour undo token; destructive ops layer additional safety (two-step confirm on deletes above 10 products, active-subscriptions guard, notification-suppression default on order updates).

Before running any bulk op on a live store

These tools are designed for portfolio-scale changes (updating 50, 500, or 5,000 products in one call). The 72-hour undo is your recovery net, but for high-blast operations we strongly recommend a **SiteVault backup before commit** in addition — especially for `wc_bulk_delete_products` with `force=true` (permanent delete has no undo path).

## Prerequisites

- WooCommerce active on the site
- Royal MCP Pro installed and licensed (see [Getting Started](https://royalplugins.com/support/royal-mcp-pro/getting-started/))
- MCP client connected to your site
- **`manage_woocommerce` capability** for the acting user — standard WC shop-manager or admin role

For `wc_bulk_delete_products` against products backing WC Subscriptions, the plugin auto-detects and refuses unless you explicitly pass `force_delete_subscriptions: true`.

## Shared safety layer

Every WC bulk tool ships the standard Pro safety envelope plus category-specific guards:

- **Dry-run support on 4 of 6 tools** (`wc_bulk_price_update`, `wc_bulk_update_products`, `wc_bulk_update_stock`) — pass `dry_run: true` to preview matches + planned changes without writing.
- **Two-step confirm on `wc_bulk_delete_products` above 10 products.** First call returns a preview + `confirm_token`; second call must echo the token back. This prevents an AI from accidentally deleting your catalog on the first request.
- **Active-subscriptions guard on `wc_bulk_delete_products`.** If any target product backs a live WC Subscription, the tool refuses with a specific error unless `force_delete_subscriptions: true` is passed. Deleting a subscription product means the next billing cycle for subscribers on it will hit missing-product.
- **Notification suppression DEFAULT ON for order updates.** `wc_bulk_update_orders` suppresses customer-facing status-change emails by default across the whole batch — bulk-updating 500 orders would otherwise fire 500 emails. Opt into emails with `suppress_notifications: false`.
- **Whitelisted product fields on `wc_bulk_update_products`.** Only `name`, `description`, `short_description`, `status`, `sku`, `catalog_visibility` can be updated in bulk — other fields require single-item WC tools for safety.
- **72-hour undo on every destructive tool.** Undo handlers restore per-product state (prior prices, prior product state, prior stock, prior category assignments, prior order statuses).
- **Audit Log row on every call** — both dry-run and commit runs.

## The 6 tools

### wc\_bulk\_price\_update

Update `regular_price` and/or `sale_price` across N products in one call. Products not in the array are untouched.

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `updates` required | `array` | Array of price change entries. Each entry: `{product_id, regular_price?, sale_price?}`. |
| `dry_run` | `boolean` | If `true`, report what would change without writing. No undo token issued in dry\_run. |

#### Example

```
Bulk update prices with wc_bulk_price_update — apply 12% off across products 42, 108, 143, and 227. Do a dry run first, then commit.
```

Undo: 72h token — restores prior `regular_price` and `sale_price` per product.

### wc\_bulk\_update\_products

Update whitelisted product fields (name, description, short\_description, status, sku, catalog\_visibility) across N products. Fields not listed in an entry are untouched.

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `updates` required | `array` | Array of product update entries. Fields not listed in the item are untouched. |
| `dry_run` | `boolean` | If `true`, report what would change without writing. |

Undo: 72h token — restores prior field values per product.

### wc\_bulk\_delete\_products

Bulk delete N products. `force=false` trashes (undoable via `wp_untrash_post`). `force=true` permanently deletes and CANNOT be undone. Two-step confirm required above 10 products. Refuses on any target backing an active WC Subscription unless bypassed.

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `product_ids` required | `array<integer>` | WooCommerce product IDs to delete. |
| `force` | `boolean` | `true` = permanent (NO undo). Default `false` = trash (undoable via 72h token). |
| `confirm_token` | `string` | Required on second call when `product_ids` count > 10 — echo the token from the first-call preview response back. |
| `force_delete_subscriptions` | `boolean` | Bypass the active-subscriptions guard when any target product backs a live WC Subscription. **Dangerous** — customers on those subscriptions will hit missing-product on next billing. |

#### Two-step confirm flow (product\_ids count > 10)

```
Ask AI: "Delete products 42, 108, 143, 227, 331, 442, 508, 619, 727, 831, 942, 1054 with wc_bulk_delete_products."

First response's structuredContent includes a preview + confirm_token, e.g.:
  {
    "count": 12,
    "threshold": 10,
    "confirm_token": "<opaque token string>",
    "expires_in": 300,
    "preview": [
      { "id": 42, "name": "Widget A", "sku": "WDG-A", "price": "19.99", "image": "https://..." },
      { "id": 108, "name": "Widget B", "sku": "WDG-B", "price": "24.99", "image": "https://..." },
      ...
    ]
  }

The token has a 5-minute TTL (expires_in: 300 seconds). Have your AI echo the token back in a second call:

Ask AI: "Confirm the delete with that confirm_token."
Second call executes the delete.
```

force=true is unrecoverable

Passing `force: true` skips the trash + skips the 72-hour undo path entirely. Product rows are removed from the database with no restore point. Use only when you genuinely want permanent deletion.

Undo (when `force=false`): 72h token — untrashes the products via `wp_untrash_post`.

### wc\_bulk\_update\_stock

Bulk stock quantity + status updates across N products. `manage_stock` is force-enabled on any product being updated (so the change actually takes effect).

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `updates` required | `array` | Array of stock update entries. `manage_stock` is force-enabled per product. |
| `dry_run` | `boolean` | If `true`, report what would change without writing. |

Undo: 72h token — restores prior stock state (quantity, status, and prior `manage_stock` flag).

### wc\_bulk\_assign\_categories

Assign `product_cat` terms across N products. Three modes: `add` appends, `replace` overwrites, `remove` strips.

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `product_ids` required | `array<integer>` | Product IDs to modify. |
| `category_ids` required | `array<integer>` | `product_cat` term IDs to apply (or remove — see mode). |
| `mode` | `string` | `add` (default) = append to existing categories. `replace` = overwrite entirely. `remove` = strip the listed IDs. |

Uncategorized auto-assignment

WooCommerce may auto-assign "Uncategorized" if a product ends up with zero categories after a `replace` or `remove` operation. This is standard WC behavior, not something Royal MCP Pro can override.

Undo: 72h token — restores prior term assignments per product.

### wc\_bulk\_update\_orders

Bulk order status transitions with customer-notification suppression DEFAULT ON. Each entry triggers `WC_Order::update_status`.

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `order_updates` required | `array` | Array of `{order_id, status, note?}` entries. |
| `suppress_notifications` | `boolean` | Default `TRUE` — customer-facing status-change emails are suppressed for the entire batch. Set `false` to fire the standard per-transition emails. |

500 orders = 500 emails without suppression

WooCommerce's default behavior fires an email on every status transition. If you set `suppress_notifications: false` and bulk-update 500 orders, that's 500 customer emails leaving your server — potentially in violation of your bulk-email SLA and definitely enough to trip spam filters. The default-on suppression is the safer choice; opt in deliberately.

Undo: 72h token — restores prior order statuses. Undo also suppresses notifications by default (the restore itself is a status change and would otherwise fire another 500 emails).

## Related documentation

- [**Bulk Price Updates + Undo workflow**](https://royalplugins.com/support/royal-mcp-pro/bulk-price-updates-with-undo/) — end-to-end flagship guide for sale-campaign scenarios
- [Undo Tokens explainer](https://royalplugins.com/support/royal-mcp-pro/#undo-tokens) — how to consume the tokens returned by every write tool

## Still Stuck? Two-Step Support Path

If a WC bulk tool isn't behaving the way you expected, work through these two steps in order — most tool-level failures resolve at Step 1 because they're actually MCP-connection or host-layer issues, not WC-specific.

### Step 1: Start with the Royal MCP Troubleshooting Guide

[**Royal MCP Troubleshooting — Start Here**](https://royalplugins.com/support/royal-mcp/troubleshooting-start-here/) covers MCP-layer issues. If Claude can't reach your site at all, the tool call never fires — that guide is where to start.

For Pro-specific patterns:

- [Undo token errors](https://royalplugins.com/support/royal-mcp-pro/undo-token-errors/) — expired, consumed, or handler missing
- [Pro tool returned upgrade prompt with valid license](https://royalplugins.com/support/royal-mcp-pro/pro-tool-returned-upgrade-prompt/)

### Step 2: Email priority support

If you've worked through Start Here and the relevant Pro-specific doc and the issue still isn't resolved, email priority support from your purchase email address at **[support@royalplugins.com](mailto:support@royalplugins.com)**. Priority email support is included with your license — typical response within 24 hours. **Never include your license key in email**; we look it up from your purchase address.

What to include in your email

- **Your hosting provider** (SiteGround, Cloudways, Hostinger, Kinsta, WP Engine, Liquid Web, self-hosted VPS, etc.)
- **Royal MCP Pro version** from WP Admin → Plugins
- **WooCommerce version** from WP Admin → Plugins, plus **WC Subscriptions version** if installed
- **Whether HPOS (High-Performance Order Storage) is enabled** for orders — check WP Admin → WooCommerce → Settings → Advanced → Features
- **Active caching plugins** (LiteSpeed Cache, WP Rocket, W3 Total Cache, SpeedyCache, Hummingbird, none)
- **Active security plugins** (Wordfence, Defender Pro, Solid Security, NinjaFirewall, none)
- **Which MCP client** — claude.ai web custom connector, Claude Desktop with `mcp-remote`, ChatGPT MCP, Cursor, or another MCP-compatible client
- **The exact WC bulk tool name and args** you called (e.g. `wc_bulk_update_stock` with `updates: [{product_id: 42, stock_quantity: 100, ...}]`)
- **The exact error message returned** (from the MCP client's chat surface), plus any `ofid_xxxxx` reference code if claude.ai shows one
- **Screenshot of the most recent `oauth:` row in Activity Log** AND **the most recent Pro tool row in Audit Log** with View Details expanded (or confirmation that the logs are empty after a reproduced failure)
- **Approximate product / order count** for the bulk operation — helps us understand whether it's a batch-size timeout vs a per-item failure

[← Elementor Pro Tools](https://royalplugins.com/support/royal-mcp-pro/elementor-pro-tools/)
[Cross-plugin Composers →](https://royalplugins.com/support/royal-mcp-pro/cross-plugin-composers/)
