wc_create_product: create a product
Creates a simple or variable product.
Arguments
| Argument | Meaning |
|---|---|
type |
simple (default) or variable |
name |
Product name |
slug |
URL slug |
status |
Post status |
description |
Full description |
short_description |
Short description |
sku |
Stock keeping unit |
regular_price |
Normal price |
sale_price |
Sale price |
manage_stock |
Whether to track stock |
stock_quantity |
Stock level |
categories |
Product category IDs |
dry_run |
Report without creating |
Permissions
Allow WooCommerce catalog writes open, plus manage_woocommerce or edit_products.
type is decided at creation and matters
Passing type: variable creates a variable product; anything else creates a simple one.
The difference is structural. A simple product carries its own price and stock. A variable product carries neither in a meaningful way — those live on its variations, and a variable product with no variations is unbuyable.
Choosing wrongly is awkward to correct: converting between types is not something these tools do.
Creating a variable product is step one of four
- Create the product with
type: variable. - Ensure the global attributes exist —
wc_get_product_attributes, andwc_create_product_attributeif genuinely needed. - Attach them with
wc_set_product_attributes, marked as used for variations. - Create the variations with
wc_create_variation.
Stopping after step one leaves a product customers cannot buy. Plan the whole sequence before starting.
Status is not defaulted to draft
Unlike wp_create_post, which forces a draft when no status is given, this tool applies only the fields you pass. Omitting status leaves WooCommerce's own default, which may publish the product.
Pass status explicitly:
Create it as a draft.
Then review it in the WooCommerce admin and publish deliberately. A product created straight to published is on the storefront before anyone has checked its price.
Prices are strings, and both matter
Set regular_price for the normal price. Set sale_price only if the product should launch on offer — setting it inadvertently means the product goes live discounted.
The read-only price field in the response tells you which one is in effect. Check it.
Stock has two parts
manage_stock enables tracking; stock_quantity sets the number. Setting a quantity without enabling management stores a value WooCommerce ignores, and the product shows as in stock indefinitely.
Set both, or neither.
SKUs must be unique
WooCommerce rejects a duplicate SKU. On a bulk creation run this is the most likely failure, and it fails per product rather than stopping the batch — so read the results.
Categories are IDs
categories takes term IDs, not names. Read them first with wp_get_categories against the product category taxonomy, and decide explicitly whether the assistant may create new ones.
Use the dry run
Returns the payload it would create. Worth it before a first creation to confirm the type, status and price fields landed where you intended.
What it returns
The created product in full, including the new id and the computed price.
Common problems
| Symptom | Cause |
|---|---|
| The write is refused | Catalog write gate closed |
pom_ai_mcp_wc_forbidden |
Missing shop capability |
| The product went live immediately | status was not passed |
| It launched at a discount | sale_price was set |
| Customers cannot buy it | Variable product with no variations |
| Stock is ignored | manage_stock was not enabled |
| Creation failed | Duplicate SKU |