Skip to content
OmniRetailConnect Docs

Commerce · MCP

Catalogue write tools

Write tools for product SEO, web address, variants, properties, labels, sale prices, price breaks, brands, the label set and featured products.

View as Markdown

Overview

Besides the first write tools, a token with commerce.write.products (and, for featured products, commerce.write.collections) can change the parts of the catalogue that make a shop findable and attractive: SEO fields, web addresses, variant details, properties, labels, sale prices, quantity price breaks, brands and the label set. These tools are in the server since version 1.3.0 (SEO, address, variants, properties, labels, brands, featured products) and 1.4.0 (sale prices and price breaks). Every tool is also a REST endpoint with the same payload.

Catalogue write tools
Tool Scope Purpose
update_product_seo commerce.write.products Set the own SEO title and meta description of a product.
change_product_slug commerce.write.products Change the web address of a product.
update_variant commerce.write.products Change the EAN and/or tax class of a variant, by SKU.
set_product_properties commerce.write.products Replace the hand-set properties of a product.
set_labels commerce.write.products Replace the labels of a product.
set_variant_sale, end_variant_sale commerce.write.products Put a variant on sale for a period, or end its sales.
set_price_breaks commerce.write.products Replace the quantity price breaks of a variant.
create_brand, rename_brand, change_brand_slug, delete_brand commerce.write.products Manage brands.
set_brand_logo, remove_brand_logo commerce.write.products Set or remove the logo of a brand.
create_label, update_label, move_label, delete_label commerce.write.products Manage the label set.
feature_product_in_collection, unfeature_product_in_collection, move_featured_product_in_collection commerce.write.collections Feature products on top of a category listing.

The common rules of the write tools apply: set semantics where possible (changed and changes in every result), one database transaction together with the change-log row, the PIM ownership rules, and the write limit of 30 calls per token per minute. A token without the scope does not see these tools at all: a call answers JSON-RPC -32602.

Reference lists (read)

Four read tools give the ids the write tools take. They need commerce.read only and never write.

Reference list tools
Tool Scope Purpose
list_brands commerce.read The brands by id, a page at a time.
list_labels commerce.read The product labels in display order.
list_tax_classes commerce.read The tax classes (VAT rates).
list_properties commerce.read The product properties with their known values, a page at a time.
  • list_brands and list_properties take limit and cursor and return items, next_cursor and has_more. A brand has id, name, slug, url, logo_url, product_count (any status; a brand in use cannot be deleted) and pim_managed (a PIM product uses it, so it cannot be renamed). A property has id, name, handle, type (list or number), unit and values ([{id, label}], at most 100, values_truncated).
  • list_labels and list_tax_classes take no input and return everything with truncated (more than 200 labels or 100 tax classes). A label has id, name, slug, tone (neutral, primary, accent, dark, success), position and product_count. A tax class has id, name and default.

get_product now also returns what the full-list writes replace, so a client can read it first: slug, seo (meta_title, meta_description), labels and properties, and per variant sales and price_breaks. See the tool reference.

update_product_seo

Set the shop's own SEO title and meta description of a product. Allowed on PIM products. At least one of the two fields besides id. Plain text, whitespace collapsed.

Inputs of update_product_seo
Name Type Required Description
id integer Required Product id.
meta_title string|null Optional At most 255 characters. null or empty removes the own title; the shop then uses the product name.
meta_description string|null Optional At most 320 characters. null or empty removes it; the fallback is the description.

Output. product_id, seo (meta_title and meta_description as stored), changed and changes.

change_product_slug

Change the web address of a product (/producten/{slug}) with id and slug (made URL-safe: lower case, dashes; at most 255 characters). Allowed on PIM products, because the shop owns the address.

  • A slug that is empty after cleaning, or used by another product, is invalid_argument.
  • A published product keeps its old address as a permanent redirect to the new one (changes.redirect holds the old path). A draft gets none.
  • The check and the write are serialised per slug with the admin; a busy lock answers conflict after 5 seconds.
  • Output: product_id, slug, url, changed, changes.

update_variant

Change the EAN and/or the tax class of a variant, found by SKU. At least one of the two. Both are PIM-owned on a PIM product (field_owned_by_pim).

Inputs of update_variant
Name Type Required Description
sku string Required SKU of the variant.
ean string|null Optional A valid GTIN (8, 12, 13 or 14 digits, correct check digit). null or empty clears it.
tax_class_id integer Optional A tax class id from list_tax_classes.

Output. sku, product_id, variant (id, sku, ean, tax_class_id, tax_class, price), changed, changes. The price customers pay stays the same when the tax class changes; changes.price shows a rounding difference.

set_product_properties

Set the hand-set properties of a product with id and properties: the complete list (it may be empty) of {property_id, values}, each property once, at most 50 properties and at most 50 values of at most 100 characters each. Ids and known values come from list_properties.

  • The list replaces every value set by hand. The tool is advertised as destructive: an empty list wipes them. Values that come from variants stay.
  • A known label is reused (ignoring case); a new one becomes a new value of the property; a number property keeps the first value.
  • An unknown property refuses the whole call (invalid_argument, nothing stored).
  • Output: product_id, properties (property_id, name, values), changed, changes.

set_labels

Set the labels of a product with id and label_ids: the complete list of distinct ids from list_labels (it may be empty), at most 50. It replaces the product's labels and is advertised as destructive: an empty list wipes them. Allowed on PIM products. An unknown label is invalid_argument. Output: product_id, labels (id, name, in label order), changed, changes.

set_variant_sale and end_variant_sale

A sale price of one variant next to its regular price, which a sale never changes. Scope commerce.write.products.

Inputs of set_variant_sale
Name Type Required Description
sku string Required SKU of the variant, at most 64 characters.
amount_minor integer Required Tax-inclusive sale price in cents, 1 to 100000000, below the regular price as stored.
starts_at string|null Optional ISO 8601 with a time and an offset (2026-11-20T00:00:00+01:00 or ...Z). Omitted, null or in the past: now. The price history is never backdated.
ends_at string|null Optional Same format, exclusive, after the start and after now. Omitted or null: no end. A date that does not exist (30 February) is invalid_argument.
  • A sale that overlaps the period is replaced: a running one ends when the new one starts, a planned one is deleted. When the only overlapping sale already is this one, nothing changes.
  • end_variant_sale (sku) ends the running sale now (it stays in the price history) and deletes the planned ones. It is advertised as destructive. Without a sale nothing changes.
  • Both write the sale periods of the price history that the optional "lowest price of the last 30 days" line reads. Whether that line is shown is the shop owner's setting and is not touched.
  • No regular price, a sale price not below it, or a period that ends too early is invalid_argument. On a PIM-linked product whose prices the PIM owns, both tools are field_owned_by_pim.
  • Output: sku, product_id, regular_price, sales and price_breaks (as in get_product), changed, changes (sale with the replaced or ended sales and the new one, prices as money objects).

set_price_breaks

Replace the quantity price breaks (staffelprijzen) of one variant. Inputs: sku and price_breaks, the complete list of {min_quantity, amount_minor} (tax-inclusive price per unit from that quantity on). An empty list removes them all; the tool is advertised as destructive.

  • At most 10 breaks, min_quantity 2 to 9999 and unique, every price above zero and below the regular price, and a larger quantity is never dearer per unit. Otherwise invalid_argument with the rule in the message.
  • On a PIM-linked product whose prices the PIM owns: field_owned_by_pim.
  • Read the current list with get_product first. Output as set_variant_sale, with changes.price_breaks.

Brands

  • create_brand (name, at most 255 characters) and rename_brand (id, name). A name must be new ignoring case, so a repeated create is invalid_argument and never makes a duplicate. A brand that a PIM-linked product uses cannot be renamed (field_owned_by_pim). Renaming keeps the address.
  • change_brand_slug (id, slug): the address /merken/{slug}. A slug another brand uses is invalid_argument. The old address becomes a permanent redirect. Brand addresses are changed one at a time; a busy lock answers conflict after 5 seconds.
  • delete_brand (id): only a brand that no product uses (of any status). Otherwise invalid_argument. Its old address redirects to the brands overview. Destructive; a repeat is not_found. Output: brand_id, deleted, changed, changes.
  • set_brand_logo (id, image_url, alt) downloads the image with the rules of add_product_media (https, public host, no redirects, at most 10 MB, no SVG) and makes it the brand's only logo; JPEG and PNG are stored as WebP. Every call stores the image again. remove_brand_logo (id) deletes the logo; without a logo it changes nothing. It is advertised as destructive.
  • Output of the others: brand (id, name, slug, url, logo_url, product_count, pim_managed), changed, changes. Assign a brand to a product by name with update_product.

Labels

  • create_label (name, at most 40 characters and new ignoring case; optional tone: neutral (default), primary, accent, dark, success) adds a label at the end of the label order. A repeat is invalid_argument.
  • update_label (id, at least one of name, tone) renames or recolours one. The slug stays, because themes style by it.
  • move_label (id, direction up or down) swaps it with its neighbour; nothing happens at either end. Not idempotent.
  • delete_label (id) deletes it and takes it off its products. Destructive; a repeat is not_found.
  • Output: label (id, name, slug, tone, position, product_count) or, for delete, label_id and deleted, plus changed and changes.

Scope commerce.write.collections. Featured products sort above all other products of a category listing. feature_product_in_collection, unfeature_product_in_collection and move_featured_product_in_collection all take collection_id and product_id; the product must be in the category, otherwise invalid_argument. The move tool also takes direction (up or down).

  • Featuring puts the product on top; already on top changes nothing; featuring another later puts that one on top.
  • Unfeaturing puts it back among the others; a product that is not featured changes nothing.
  • Moving swaps it with its neighbour among the featured products. A product that is not featured is invalid_argument. Not idempotent.
  • A category of the hidden PIM import tree is invalid_argument. The category's product list is locked for the call; a busy lock is conflict.
  • Output: product_id, collection, featured, featured_product_ids (top first, at most 100), changed, changes.

Errors

Errors of the catalogue write tools
Code When
invalid_argument Failed validation: an unknown argument, a taken name or slug, a brand that is still in use, a product that is not in the category, a refused image URL, a sale price not below the regular price, a break list that breaks a rule, or an unknown id in a list. The message names the rule.
not_found The product, SKU, brand, label or category does not exist; a repeated delete.
field_owned_by_pim On a PIM-linked product: EAN and tax class, sale prices and price breaks when the PIM owns prices, or renaming a brand a PIM product uses. SEO, web address, labels and featured products are the shop's own and always editable.
conflict The data changed during the call, or another change of the same data (a slug, a brand address, a category product list) kept it locked for 5 seconds. Read again and retry.