# MCP: katalog produktů

> Nástroje MCP pro produkty, kategorie, značky a vlastnosti: oprávnění, potvrzení, kredity, důsledky zápisu a všechny parametry včetně operací.

- Sekce: Pro vývojáře
- Stránka: https://shopzi.cz/dokumentace/vyvojari/mcp-katalog
- Ověřeno: 2026-09-16

---

Čtení a úpravy katalogu: vyhledání a detail produktu, strom kategorií a jejich obrázky, značky, vlastnosti a ceníky, tabulky velikostí a informační panely, zakládání produktů rovnou s variantami a údaji pro dopravu, náhled importu z jiného e-shopu a stav importů, úpravy produktů včetně obsahu stránky produktu, údajů GPSR, běžné ceny a sazby DPH existujících variant, změny struktury variant (z jednoduchého produktu variantní a zpět) a hromadná AI úprava i s jejím stavem.

Nástroje volá klient přes server MCP na doméně obchodu, například `https://muj-eshop.cz/api/mcp`, a v odpovědi na `tools/list` dostane jen ty, na jejichž oprávnění klíč dosáhne. Jak server mluví, kdy se ptá člověka a jak se změny vracejí, popisuje článek [MCP server](/dokumentace/vyvojari/mcp-server).

U každého nástroje stojí oprávnění, které chce, jestli se server před provedením zeptá člověka a kudy, jestli volání strhne kredity obchodu nebo peníze z karty, co vrací pro deník změn a jakou větu o důsledku člověk v potvrzení uvidí. Všechno z toho se vyhodnocuje z téhož kódu, podle kterého se server rozhoduje. Popisy parametrů jsou převzaté ze schématu, které server posílá v `tools/list`; kde se v něm text obrací přímo k modelu, je tady převedený do vykání. Povinnost parametru platí uvnitř objektu, ve kterém parametr leží.

Před zápisem, který přepisuje nebo maže, před útratou kreditů nebo platbou kartou a před hledáním mimo obchod se server ptá člověka a do té doby neprovede nic. Nejdřív použije schválení, které pro totéž volání se stejnými hodnotami už v administraci leží schválené. Jinak se zeptá formulářem, když ho klient deklaruje a politika akce ho dovoluje; formulář potvrzuje ten, kdo drží klíč, takže před ukradeným klíčem takové potvrzení nechrání. Otázka ve formuláři nese pod nadpisem „Co se změní“ tytéž řádky jako stránka schválení. Klient s elicitací URL dostane odkaz na stránku schválení v administraci a klient bez elicitace odmítnutí `approval_required` s odkazem v `_meta`; po schválení volání zopakuje se stejnými hodnotami. Na stránce schválení rozhoduje jen přihlášený člověk, kterého u každé akce jmenuje odrážka Potvrzení přes MCP, a účet podpory SHOPZI nikdy. Když politika nedovoluje nic, co klient umí, přijde odmítnutí `confirmation_required` a neprovede se nic. Výsledek potvrzeného volání nese v `_meta["cz.shopzi/confirmation"]` údaj, že akci potvrdil člověk a kde (`form` nebo `approval`), a v obsahu českou větu pro model, u placené akce i s cenou a zůstatkem kreditů z dotazu. Na otázku formulářem je 15 minut, schválení na stránce platí 60 minut, pokud u akce není uvedeno jinak.

Zápisové nástroje vracejí v poli `change_id` ID záznamu v deníku změn; co pole u kterého nástroje nese, říká jeho odrážka Deník změn. Změnu z deníku vrací `shopzi_undo_change` podle jejího druhu: obnoví předchozí hodnoty, u skladu zapíše vyrovnávací pohyb, u běžné ceny zapíše návrat do 30denní historie cen (nic z ní nemaže) a změnu, která už opustila obchod nebo stála peníze (odeslaný e-mail, stržené kredity, platbu kartou), odmítne s vysvětlením.

## `shopzi_search_products` [#shopzi-search-products]

Vrátí stránku produktů seřazenou od nejnovějších, s parametrem `sort` od nejlevnějšího nebo od nejdražšího, a k ní souhrn spočítaný nad celým výběrem: průměr, součet, minimum, maximum a zásobu. Produkt najde podle názvu, značky, adresy nebo SKU a výpis zúží kategorií, stavem nebo časem poslední změny.

* **Oprávnění:** `products:read`, u klíče „Katalog: produkty, kategorie, dodavatelé (čtení)“.
* **Druh:** čtení (`readOnlyHint`).
* **Potvrzení přes MCP:** ne.
* **Kredity a platba kartou:** ne.

## `shopzi_search_products`: parametry [#shopzi-search-products-parametry]

* `search` (text, 1 až 120 znaků; nepovinný): Text v názvu produktu, ve ZNAČCE, v adrese (slug) nebo v SKU varianty. Hledá se i uvnitř slova. Na „kolik mám produktů od značky X“ tedy stačí poslat jméno té značky a přečíst `total`. `total` počítá jen to, co dotazu odpovídá.
* `categoryId` (`__uncategorized` nebo UUID; nepovinný): ID kategorie ze `shopzi_list_catalog` (`resource: categories`). Počítá se PŘÍMÉ zařazení, ne podstrom, přesně jako filtr v seznamu produktů: u nadřazené kategorie tedy vrátí jen to, co je přiřazené přímo k ní. Hodnota `__uncategorized` vrátí produkty bez jakéhokoli zařazení.
* `status` (text; nepovinný): Filtr stavu, například `active` nebo `draft`.
* `updatedSince` (text se vzorem; nepovinný): ISO datum. Vrátí jen produkty ZMĚNĚNÉ od té doby, tedy nové i upravené.
* `sort` (jedna z hodnot `price_asc` a `price_desc`; nepovinný): Řazení. `price_asc` = od nejlevnějšího, `price_desc` = od nejdražšího. Použijte VŽDY, když se ptá na nejlevnější, nejdražší nebo cenové pořadí: bez toho dostanete produkty od nejnovějšího a o ceně z nich nic neplyne. Cenové řazení vrací první stránku a `next_cursor` u něj neplatí.
* `limit` (celé číslo od 1 do 100, výchozí `25`; nepovinný): Počet položek na stránku, 1 až 100. Velká stránka se do jedné odpovědi nemusí vejít a nástroj ji pak odmítne, což stojí krok navíc: berte jen tolik položek, kolik na odpověď opravdu potřebujete.
* `cursor` (text; nepovinný): Průběžná pozice z předchozí odpovědi (`next_cursor`). Vynechte pro první stránku.

## `shopzi_get_product` [#shopzi-get-product]

Vrátí jeden produkt i s variantami, cenami, zásobou a zařazením do kategorií včetně té hlavní. Každá varianta nese svůj název složený z hodnot voleb, třeba `Černá / 42`, a každá cena přijde v haléřích i jako hotový text pod jménem bez `_minor`, třeba `price` vedle `price_minor`. Parametr `include` přidá další karty editoru ve tvaru, v jakém je přijímá `shopzi_manage_product`: modifikátory, vlastnosti, vazby, složení balíčku, překlady, obsah stránky produktu, velkoobchodní ceny a podrobnosti (DPH, značka, údaje GPSR, vyloučení z odstoupení, další SEO a logistika variant).

* **Oprávnění:** `products:read`, u klíče „Katalog: produkty, kategorie, dodavatelé (čtení)“.
* **Druh:** čtení (`readOnlyHint`).
* **Potvrzení přes MCP:** ne.
* **Kredity a platba kartou:** ne.

## `shopzi_get_product`: parametry [#shopzi-get-product-parametry]

* `productId` (UUID; povinný): ID produktu (UUID) z `shopzi_search_products`.
* `include` (pole, položka: jedna z hodnot `modifiers`, `attributes`, `links`, `bundle`, `translations`, `page_content`, `wholesale` a `details`, nejvýš 8 položek; nepovinný): Karty navíc. attributes = filtrovatelné vlastnosti a `custom_params` (tabulka Parametry), page\_content = obsah pod produktem (bloky, výjimky panelů), wholesale = velkoobchod (cena varianty bez DPH), details = DPH, značka, GPSR, odstoupení, SEO navíc, logistika variant. Berte jen potřebné: každá sada odpověď zvětší.

## `shopzi_list_catalog` [#shopzi-list-catalog]

Vrátí podle `resource` strom kategorií (s `detail: true` i popisy, SEO a obrázek každé kategorie), značky a výrobce uvedené u produktů, definice vlastností, cenové hladiny včetně velkoobchodních, tabulky velikostí, informační panely stránky produktu, stav hromadné AI úpravy produktů (`ai_runs`), nebo posledních dvacet importů z jiného e-shopu (`imports`). V položkách katalogu umí hledat podle názvu.

* **Oprávnění:** `products:read`, u klíče „Katalog: produkty, kategorie, dodavatelé (čtení)“.
* **Druh:** čtení (`readOnlyHint`).
* **Potvrzení přes MCP:** ne.
* **Kredity a platba kartou:** ne.

### `shopzi_list_catalog`: oblasti [#shopzi-list-catalog-oblasti]

* `categories`
* `vendors`
* `attributes`
* `price_lists`
* `size_guides`
* `info_panels`
* `ai_runs`
* `imports`

## `shopzi_list_catalog`: parametry [#shopzi-list-catalog-parametry]

* `resource` (jedna z hodnot `categories`, `vendors`, `attributes`, `price_lists`, `size_guides`, `info_panels`, `ai_runs` a `imports`; povinný): Která část katalogu.
* `search` (text, 1 až 120 znaků; nepovinný): Text v názvu. U `categories` se hledá i v názvech nadřazených kategorií (takže „nábytek sedačky“ najde Sedačky pod Nábytkem), u `vendors` i v adrese (slug), u `attributes` i v klíči vlastnosti. Hledá se i uvnitř slova a na pořadí slov nezáleží. `total` počítá jen to, co dotazu odpovídá.
* `detail` (`true` nebo `false`; nepovinný): Jen `categories`: true přidá popisy, H1, SEO, obrázek a příznaky (jména polí jako v `shopzi_manage_category`). Odpověď je velká: zuž ji `search` nebo `limit`.
* `limit` (celé číslo od 1 do 100, výchozí `25`; nepovinný): Počet položek na stránku, 1 až 100. Velká stránka se do jedné odpovědi nemusí vejít a nástroj ji pak odmítne, což stojí krok navíc: berte jen tolik položek, kolik na odpověď opravdu potřebujete.
* `offset` (celé číslo od 0 do 100000, výchozí `0`; nepovinný): Kolik položek přeskočit. 0 = první stránka.

## `shopzi_manage_product` [#shopzi-manage-product]

Zakládá (nový produkt rovnou i s variantami, hmotností, rozměry, nákupní cenou a vlastními parametry), upravuje (včetně značky, údajů GPSR, vyloučení z odstoupení a SEO) a archivuje produkty a spravuje jejich zařazení do kategorií, varianty, modifikátory, vlastnosti, vazby, překlady, složení balíčku, běžné i velkoobchodní ceny a obsah stránky produktu (tabulka velikostí, sestavený popis z bloků, nadpis nad popisem, výjimky informačních panelů); hromadně přepíná stav, z adresy jiného e-shopu připraví náhled importu (spouští ho obchodník v průvodci), potvrzuje dokončený import a řídí hromadnou AI úpravu. Strukturu variant mění `set_variant_axes` (z jednoduchého produktu udělá variantní), `remove_variants` a `collapse_to_simple` (zpátky na jednoduchý); tyto tři operace vrátit nejde, a proto odmítnou variantu se zásobou, s objednávkami nebo v balíčku. Změna běžné ceny (`set_retail_price`) se zapisuje do 30denní historie cen podle § 12a a vrací se dalším pohybem ceny zpátky. `set_vat_rate` změní sazbu DPH všem variantám: cena s DPH zůstane, mění se základ daně dalších prodejů a vystavené doklady zůstanou beze změny. Konkrétní produkt nesmaže; mazat umí jen nedotčené ukázkové produkty ze startovního obsahu.

* **Oprávnění:** `products:write`, u klíče „Katalog: produkty, kategorie a číselníky (zápis)“.
* **Druh:** zápis, který umí přepsat nebo smazat existující data (`destructiveHint`), sahá mimo obchod na veřejný internet (`openWorldHint`).
* **Potvrzení přes MCP:** ano: formulář v klientu, který potvrdí ten, kdo drží klíč; jinak odkaz na stránku schválení přes elicitaci URL; jinak odkaz na stránku schválení v odmítnutí `approval_required`. Na stránce schválení rozhoduje vlastník nebo manažer obchodu.
* **Kredity a platba kartou:** podle `operation`, viz seznam níž.
* **Deník změn:** výsledek nese `change_id`. ID záznamu v deníku. Předejte ho do `shopzi_undo_change`.
* **Věta o důsledku, kterou člověk uvidí v potvrzení:** podle `operation`, viz seznam níž.

### `shopzi_manage_product`: operace (produkt a zařazení) [#shopzi-manage-product-operace-produkt-a-zarazeni]

* `create` (založit)
  * Kredity a platba kartou: ne.

* `update` (upravit)
  * Kredity a platba kartou: ne.

* `archive` (archivovat)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Archivace stáhne produkt z e-shopu zákazníkům i z vyhledávačů. Vrátit to jde jedním krokem přes „vrátit zpět“.

* `assign_category` (přiřadit kategorii)
  * Kredity a platba kartou: ne.

* `unassign_category` (odebrat z kategorie)
  * Kredity a platba kartou: ne.

* `set_categories` (nastavit zařazení do kategorií)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Když je Agent nastavuje najednou, nastaví se kategorie jako CELÁ sada: kategorie, která na kartě není, z produktu zmizí.

* `bulk_status` (hromadně přepnout stav)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Hromadná změna stavu se provede na VŠECH produktech vypsaných níž, naráz a přesně na nich (jiných se nedotkne): publikování je zveřejní v e-shopu, koncept a archivace je z něj stáhnou zákazníkům i z vyhledávačů. Vrátit to jde jedním krokem přes „vrátit zpět“, celou dávku najednou.

* `delete_samples` (uklidit ukázkové produkty)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Úklid ukázkových produktů vzít zpět nejde: s produkty se smažou i jejich fotky z úložiště a zásoba se odepíše. Týká se jen produktů ze startovního obsahu, kterých se od té doby nikdo nedotkl, a dávku si vybírá sám, takže karta níž NEUKÁŽE ani jejich počet, ani jména: nechte si je před potvrzením vypsat („vyjmenuj ukázkové produkty, které bys smazal“).

Hodnota bez odrážky Věta o důsledku v potvrzení žádnou takovou větu nemá.

### `shopzi_manage_product`: operace (karty editoru) [#shopzi-manage-product-operace-karty-editoru]

* `save_modifiers` (přepsat modifikátory)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Uložení modifikátorů PŘEPÍŠE celou jejich sadu: co v ní není, z produktu zmizí.

* `save_attributes` (přepsat vlastnosti)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Uložení vlastností PŘEPÍŠE celou jejich sadu: co v ní není, z produktu zmizí.

* `save_links` (přepsat propojení s produkty)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Uložení vazeb PŘEPÍŠE celou jejich sadu: co v ní není, z produktu zmizí.

* `save_translation` (uložit překlad)
  * Kredity a platba kartou: ne.

* `save_bundle` (přepsat obsah balíčku)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Uložení složení balíčku PŘEPÍŠE celou sadu: co v ní není, z balíčku zmizí.

* `save_page_content` (uložit obsah stránky produktu)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Bloky obsahu pod produktem se nahradí CELOU sadou: blok, který v seznamu není, zmizí.

Hodnota bez odrážky Věta o důsledku v potvrzení žádnou takovou větu nemá.

### `shopzi_manage_product`: operace (varianty, ceny a DPH) [#shopzi-manage-product-operace-varianty-ceny-a-dph]

* `add_variants` (přidat varianty)
  * Kredity a platba kartou: ne.

* `update_variants` (upravit údaje variant)
  * Kredity a platba kartou: ne.

* `set_wholesale_price` (nastavit velkoobchodní cenu)
  * Kredity a platba kartou: ne.

* `set_wholesale_terms` (nastavit podmínky velkoobchodu)
  * Kredity a platba kartou: ne.

* `set_retail_price` (změnit cenu)
  * Kredity a platba kartou: ne.

* `remove_variants` (odebrat varianty)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Odebrané varianty zmizí z e-shopu i z produktu a vzít to zpět nejde: znovu je lze jen přidat jako nové, s novou cenou a bez historie cen. Variantu se zásobou, s objednávkami nebo v balíčku Agent neodebere.

* `set_variant_axes` (rozdělit produkt na varianty)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Z jednoduchého produktu se stane variantní. Stávající varianta si ponechá cenu, zásobu i SKU, nové varianty přibudou s cenou z karty. Vzít zpět to nejde: zpátky na jednoduchý produkt to převede jen převod, který varianty odebere.

* `collapse_to_simple` (převést na produkt bez variant)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Variantní produkt se převede na jednoduchý: všechny varianty a vlastnosti, podle kterých se lišily, zmizí a zůstane jedna varianta s cenou a údaji té výchozí. Vzít zpět to nejde. Produkt, jehož varianta má zásobu, objednávky nebo je v balíčku, Agent nepřevede.

* `set_vat_rate` (změnit sazbu DPH)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Nová sazba DPH platí pro všechny varianty a další prodeje. Cena s DPH zůstává, mění se základ daně; už vystavené doklady se nemění. Vrátit to jde přes „vrátit zpět“.

Hodnota bez odrážky Věta o důsledku v potvrzení žádnou takovou větu nemá.

### `shopzi_manage_product`: operace (AI úprava a import) [#shopzi-manage-product-operace-ai-uprava-a-import]

* `start_ai_run` (spustit a zaplatit hromadnou AI úpravu)
  * Kredity a platba kartou: strhne kredity obchodu.
  * Věta o důsledku v potvrzení:

    > Spuštění hromadné AI úpravy STOJÍ KREDITY: strhávají se při zadání a nevracejí se, ani když se výsledek nelíbí. Kolik to bude a kolik vám zbývá, stojí na kartě níž. Do produktů se ale nic nezapíše: úprava vyrobí návrhy a čeká, až je v Produktech schválíte vy, a stisknout „Použít“ za vás nemůžu. Vzít zpět to nejde.

* `regenerate_ai_item` (napsat návrh znovu (další kredit))
  * Kredity a platba kartou: strhne kredity obchodu.
  * Věta o důsledku v potvrzení:

    > Přegenerování jednoho návrhu je další kredit a původní návrh přepíše. Vzít zpět to nejde.

* `cancel_ai_run` (zastavit hromadnou AI úpravu)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Zastavení hromadné AI úpravy platí pro tu, která PRÁVĚ BĚŽÍ: doběhne rozpracovaná položka, kredity za ni se nevracejí a znovu se ta úprava nerozjede. Vzít zpět to nejde.

* `revert_ai_run` (vrátit hromadnou AI úpravu)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Vrácení platí pro POSLEDNÍ dokončenou úpravu a přepíše zpátky jen ty hodnoty, které se pořád rovnají tomu, co napsala AI, takže vaše pozdější úpravy zůstanou; fotky, které úprava k produktům přidala, se ale smažou z úložiště. Vzít zpět to nejde.

* `accept_import` (přijmout výsledek importu)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Přijetí importu produkty nemění: ty už v obchodě leží jako koncepty. Zavře ale obrazovku s výsledkem i tlačítko „Zahodit vše“, takže hromadně se toho importu pak zbavit nedá. Kolik produktů to je, v jakém rozpětí mají ceny a jak se jmenují, stojí na kartě níž. Přijetí jde vzít zpět: obrazovka i tlačítko se vrátí.

* `import_from_url` (připravit import z jiného e-shopu)
  * Kredity a platba kartou: ne.
  * Věta o důsledku v potvrzení:

    > Uložení modifikátorů, vlastností, vazeb nebo složení balíčku PŘEPÍŠE celou tu sadu: co v ní není, z produktu zmizí; u kategorií to platí stejně, když je Agent nastavuje najednou. Hromadná změna stavu se provede na VŠECH produktech vypsaných níž, naráz a přesně na nich (jiných se nedotkne): publikování je zveřejní v e-shopu, koncept a archivace je z něj stáhnou zákazníkům i z vyhledávačů. Vrátit to jde jedním krokem přes „vrátit zpět“, celou dávku najednou. Úklid ukázkových produktů vzít zpět nejde: s produkty se smažou i jejich fotky z úložiště a zásoba se odepíše. Týká se jen produktů ze startovního obsahu, kterých se od té doby nikdo nedotkl, a dávku si vybírá sám, takže karta níž NEUKÁŽE ani jejich počet, ani jména: nechte si je před potvrzením vypsat („vyjmenuj ukázkové produkty, které bys smazal“). Spuštění hromadné AI úpravy STOJÍ KREDITY: strhávají se při zadání a nevracejí se, ani když se výsledek nelíbí. Kolik to bude a kolik vám zbývá, stojí na kartě níž. Do produktů se ale nic nezapíše: úprava vyrobí návrhy a čeká, až je v Produktech schválíte vy, a stisknout „Použít“ za vás nemůžu. Přegenerování jednoho návrhu je další kredit a původní návrh přepíše. Zastavení hromadné AI úpravy platí pro tu, která PRÁVĚ BĚŽÍ: doběhne rozpracovaná položka, kredity za ni se nevracejí a znovu se ta úprava nerozjede. Vrácení platí pro POSLEDNÍ dokončenou úpravu a přepíše zpátky jen ty hodnoty, které se pořád rovnají tomu, co napsala AI, takže vaše pozdější úpravy zůstanou; fotky, které úprava k produktům přidala, se ale smažou z úložiště. Žádnou ze čtyř proto vzít zpět nejde. Přijetí importu produkty nemění: ty už v obchodě leží jako koncepty. Zavře ale obrazovku s výsledkem i tlačítko „Zahodit vše“, takže hromadně se toho importu pak zbavit nedá. Kolik produktů to je, v jakém rozpětí mají ceny a jak se jmenují, stojí na kartě níž. Přijetí jde jako jediné z téhle skupiny vzít zpět: obrazovka i tlačítko se vrátí.

Hodnota bez odrážky Věta o důsledku v potvrzení žádnou takovou větu nemá.

## `shopzi_manage_product`: parametry `operation` až `minWholesaleQty` [#shopzi-manage-product-parametry-operation-az-minwholesaleqty]

* `operation` (jedna z hodnot `create`, `update`, `archive`, `assign_category`, `unassign_category`, `set_categories`, `save_modifiers`, `save_attributes`, `save_links`, `save_translation`, `save_bundle`, `save_page_content`, `add_variants`, `update_variants`, `bulk_status`, `set_wholesale_price`, `set_wholesale_terms`, `set_retail_price`, `delete_samples`, `start_ai_run`, `regenerate_ai_item`, `cancel_ai_run`, `revert_ai_run`, `accept_import`, `import_from_url`, `remove_variants`, `set_variant_axes`, `collapse_to_simple` a `set_vat_rate`; povinný): create = založit nový produkt; update = změnit pole existujícího; archive = stáhnout z prodeje (data zůstanou, jde vrátit; SMAZAT produkt nástroj neumí, na žádost o smazání nabídněte archive); assign\_category / unassign\_category = přidat nebo odebrat kategorii; set\_categories = nastavit CELOU sadu kategorií jedním krokem (a hlavní z nich); save\_modifiers / save\_attributes / save\_links / save\_bundle = PŘEPSAT celou danou sadu; save\_translation = uložit jeden jazyk; add\_variants = přidat nové varianty; update\_variants = upravit údaje existujících variant, u jednoduchého produktu jeho jediné základní varianty (bez ceny); bulk\_status = HROMADNĚ přepnout stav vyjmenovaných produktů; set\_wholesale\_price = nastavit velkoobchodní cenu vyjmenovaným variantám; set\_retail\_price = změnit BĚŽNOU cenu (s DPH) vyjmenovaným variantám, i u jednoduchého produktu (ID jeho jediné varianty); set\_wholesale\_terms = nastavit vyjmenovaným produktům zařazení do velkoobchodu a minimální odběr; delete\_samples = uklidit ukázkové produkty ze startovního obsahu (bez ID, bez výběru); start\_ai\_run = SPUSTIT hromadnou AI úpravu vyjmenovaných produktů (`productIds` a k tomu `aiContentFields` nebo `aiImageOps`); stojí to kredity a výsledky pak schvaluje člověk v Produktech; regenerate\_ai\_item = nechat napsat znovu návrh u JEDNOHO produktu (`productId`) v úpravě, která čeká na schválení, volitelně s `note`, co bylo špatně; cancel\_ai\_run = zastavit probíhající hromadnou AI úpravu produktů; revert\_ai\_run = vrátit změny poslední dokončené hromadné AI úpravy produktů; accept\_import = potvrdit výsledek dokončeného importu z cizího e-shopu („Uložit vše“); produkty už v obchodě leží jako koncepty, tímhle se jen zavře obrazovka s výsledkem i tlačítko „Zahodit vše“; import\_from\_url = najít katalog jiného e-shopu podle `sourceUrl` a připravit náhled importu (spouští ho obchodník); remove\_variants (`variantIds`), set\_variant\_axes (`axes`, `baseAxisValues`, `variants`) a collapse\_to\_simple = struktura variant, NEVRATNĚ; set\_vat\_rate = sazba DPH existujícího produktu (`fields.vatRate`).
* `productId` (UUID; nepovinný): ID produktu ze `shopzi_search_products`. Povinné u všeho kromě `create`.
* `categoryId` (UUID; nepovinný): ID kategorie ze `shopzi_list_catalog` (`resource: categories`). Povinné u assign\_category a unassign\_category.
* `categoryIds` (pole, položka: UUID; nepovinný): Jen u `set_categories`: CELÁ sada kategorií, ve kterých má produkt být, ze `shopzi_list_catalog` (`resource: categories`). Kategorie, která tu není, se z produktu ODEBERE; prázdný seznam ho vyřadí ze všech.
* `primaryCategoryId` (UUID; nepovinný): Jen u `set_categories`: která z těch kategorií je hlavní (drobečková navigace a adresa produktu). Musí být mezi `categoryIds`. Vynechané = první ze sady.
* `productIds` (pole, položka: UUID, 1 až 100 položek; nepovinný): U `bulk_status`, `set_wholesale_terms` a `start_ai_run`: ID produktů ze `shopzi_search_products`, vyjmenovaná. Nejvýše 100. Filtr ani „všechny produkty“ tenhle nástroj nepřijímá.
* `aiContentFields` (pole, položka: jedna z hodnot `title`, `short_description`, `description`, `meta_title`, `meta_description`, `geo_summary`, `faq` a `attributes`; nepovinný): Jen `start_ai_run`: která textová pole má AI napsat. `title` = název, `short_description` = krátký popis, `description` = popis, `meta_title` a `meta_description` = SEO, `geo_summary` = shrnutí pro AI vyhledávače, `faq` = časté dotazy, `attributes` = vlastnosti. Aspoň jedno pole nebo aspoň jedna operace s fotkami.
* `aiImageOps` (pole, položka: jedna z hodnot `alt_text`, `image_generate_missing`, `image_upscale` a `image_background`; nepovinný): Jen `start_ai_run`: co s fotkami. `alt_text` = popisky obrázků, `image_generate_missing` = vyrobit fotku produktům, které žádnou nemají, `image_upscale` = převykreslit fotku ve vyšší kvalitě, `image_background` = sjednotit pozadí. VŠECHNY tři obrazové se účtují ZA KAŽDOU FOTKU každého vybraného produktu, takže u velkého výběru vyjdou násobně dráž než texty.
* `aiFillMissingOnly` (`true` nebo `false`; nepovinný): Jen `start_ai_run`: true = doplnit jen pole, která jsou PRÁZDNÁ, a nikdy nepřepsat text, který obchodník napsal sám. Používejte, kdykoli obchodník řekne „doplň“ místo „přepiš“.
* `aiInstructions` (text, nejvýš 600 znaků; nepovinný): Jen `start_ai_run`: pokyn obchodníka k tónu, délce nebo cílovému zákazníkovi, který se přidá ke každému textu. Na fotky se neuplatňuje.
* `note` (text, nejvýš 300 znaků; nepovinný): Jen `regenerate_ai_item`: co bylo na návrhu špatně, aby ho AI napsala jinak.
* `variantIds` (pole, položka: UUID, 1 až 100 položek; nepovinný): Jen u `set_wholesale_price`, `set_retail_price` a `remove_variants`: ID variant ze `shopzi_get_product`, vyjmenovaná. Nejvýše 100. Filtr ani „všechny varianty“ tenhle nástroj nepřijímá.
* `wholesaleNetMinor` (celé číslo nebo `null`; nepovinný): Jen u `set_wholesale_price`: velkoobchodní cena v HALÉŘÍCH (1 200 Kč = 120000), stejná pro celou dávku. Prázdná hodnota cenu z ceníku SMAŽE a varianta pak velkoobchodu prodává za běžnou cenu. Vynechat toto pole nejde: mlčky smazaný ceník je horší než odmítnuté volání.
* `wholesalePriceBasis` (jedna z hodnot `net` a `gross`; nepovinný): Jen u `set_wholesale_price`: v jaké základně je částka zadaná. `net` (výchozí) = bez DPH, `gross` = s DPH. Ukládá se vždy bez DPH; u obchodu, který není plátcem DPH, se částka uloží tak, jak přišla.
* `retailPriceMinor` (celé číslo; nepovinný): Jen u `set_retail_price`: nová BĚŽNÁ cena S DPH v HALÉŘÍCH (999 Kč = 99900), stejná pro celou dávku. Taková, jakou zákazník vidí na e-shopu.
* `retailCompareAtMinor` (celé číslo nebo `null`; nepovinný): Jen u `set_retail_price`: cena před slevou (přeškrtnutá) v haléřích, musí být vyšší než nová cena. Vynechané pole = ponechat, co varianta má; prázdná hodnota = slevu zrušit. Nastavit ji znamená OHLÁSIT SLEVU; na e-shopu se pak ukáže nejnižší cena za 30 dní.
* `wholesaleEnabled` (`true` nebo `false`; nepovinný): Jen u `set_wholesale_terms`: prodávat ty produkty velkoobchodně? Vypnutý produkt vidí velkoobchodní zákazník za běžnou cenu, i když v ceníku cenu má.
* `minWholesaleQty` (celé číslo; nepovinný): Jen u `set_wholesale_terms`: minimální odběr na jeden řádek objednávky pro velkoobchodní zákazníky. 1 znamená, že žádné minimum neplatí.

## `shopzi_manage_product`: parametry `fields` a `modifiers` [#shopzi-manage-product-parametry-fields-a-modifiers]

* `fields` (objekt; nepovinný): Údaje produktu. U `create` to jsou hodnoty nového produktu (včetně ceny, DPH, SKU a URL), u `update` jen pole ke změně (vynechané zůstane beze změny; cena, DPH, URL ani SKU tudy u existujícího produktu neprojdou). U `bulk_status` JEN `status`, u `set_vat_rate` JEN `vatRate`. U ostatních operací se nepoužívá.
* `fields.title` (text; nepovinný): Název produktu. POVINNÝ při zakládání.
* `fields.slug` (text; nepovinný): URL adresa produktu (malá písmena, číslice, pomlčky). Vynechte a odvodí se z názvu. Jde nastavit JEN při zakládání: pozdější změna adresy je přesměrování, ne úprava.
* `fields.subtitle` (text nebo `null`; nepovinný)
* `fields.shortDescription` (text nebo `null`; nepovinný): Krátký prodejní souhrn u nákupního boxu. HTML se čistí.
* `fields.description` (text nebo `null`; nepovinný): Hlavní popis produktu. HTML se čistí (sanitizace).
* `fields.availabilityNote` (text nebo `null`; nepovinný)
* `fields.status` (jedna z hodnot `draft`, `active` a `archived`; nepovinný): Výchozí je `draft` (koncept). `active` znamená rovnou do prodeje, což je rozhodnutí obchodníka.
* `fields.brand` (text nebo `null`; nepovinný): Značka. Jako formulář ji propojí s kartou dodavatele téhož jména, chybějící kartu založí (vrácení ji nesmaže). `null` značku odebere.
* `fields.withdrawalExcluded` (`true` nebo `false`; nepovinný): true = vyloučeno z 14denního odstoupení (§ 1837, např. zboží na míru). Právní rozhodnutí obchodníka, nenastavujte z vlastní úvahy. Reklamaci to neruší.
* `fields.manufacturerName` (text nebo `null`; nepovinný): GPSR: název výrobce.
* `fields.manufacturerAddress` (objekt nebo `null`; nepovinný): GPSR: adresa a e-mail výrobce. Nahrazuje se jako celek.
* `fields.manufacturerAddress.street` (text; nepovinný)
* `fields.manufacturerAddress.city` (text; nepovinný)
* `fields.manufacturerAddress.zip` (text; nepovinný)
* `fields.manufacturerAddress.country` (text; nepovinný)
* `fields.manufacturerAddress.email` (text; nepovinný)
* `fields.responsiblePerson` (objekt nebo `null`; nepovinný): GPSR: odpovědná osoba v EU (výrobce mimo EU). Nahrazuje se jako celek.
* `fields.responsiblePerson.name` (text; nepovinný)
* `fields.responsiblePerson.street` (text; nepovinný)
* `fields.responsiblePerson.city` (text; nepovinný)
* `fields.responsiblePerson.zip` (text; nepovinný)
* `fields.responsiblePerson.country` (text; nepovinný)
* `fields.responsiblePerson.email` (text; nepovinný)
* `fields.ogImageUrl` (text, nejvýš 2000 znaků nebo `null`; nepovinný): Obrázek pro sdílení (Open Graph). Bez něj hlavní fotka.
* `fields.canonicalOverride` (text, nejvýš 2000 znaků nebo `null`; nepovinný): Kanonická adresa, když je originálem JINÁ stránka. Bez důvodu nevyplňujte.
* `fields.productType` (jedna z hodnot `physical`, `digital`, `service`, `gift_card`, `bundle` a `subscription`; nepovinný): Druh zboží, výchozí `physical`. Určuje, jestli se produkt doručuje a hlídá skladem. Jde zvolit JEN při zakládání: pozdější změna přepisuje nastavení všech variant.
* `fields.priceMinor` (číslo; nepovinný): Koncová cena v HALÉŘÍCH, celé číslo (129 Kč = 12900). Nikdy desetinné číslo. Jen při zakládání: pozdější změna ceny zapisuje 30denní historii podle § 12a a dělá se v adminu.
* `fields.compareAtMinor` (číslo; nepovinný): Původní („přeškrtnutá“) cena v haléřích, celé číslo. Uloží se jen když je vyšší než `priceMinor`.
* `fields.vatRate` (číslo; nepovinný): Sazba DPH jako CELÉ PROCENTO: 21, 12 nebo 0. Nikdy 0.21. Při zakládání sazba nového produktu; u existujícího ji mění JEN operace `set_vat_rate`.
* `fields.sku` (text; nepovinný): Katalogové číslo výchozí varianty.
* `fields.ean` (text; nepovinný): Čárový kód (EAN) výchozí varianty.
* `fields.weightGrams` (číslo; nepovinný): Jen při zakládání: hmotnost v GRAMECH, celé číslo. Platí pro výchozí variantu i pro varianty zakládané spolu s produktem (`axes` + `variants`).
* `fields.dimensionsMm` (objekt; nepovinný): Jen při zakládání: rozměry zásilky v MILIMETRECH. Platí stejně jako `weightGrams`.
* `fields.dimensionsMm.l` (číslo; povinný): Délka v milimetrech, celé číslo.
* `fields.dimensionsMm.w` (číslo; povinný): Šířka v milimetrech, celé číslo.
* `fields.dimensionsMm.h` (číslo; povinný): Výška v milimetrech, celé číslo.
* `fields.costMinor` (číslo; nepovinný): Jen při zakládání: nákupní cena BEZ DPH v haléřích, celé číslo. Z ní se počítá marže; zákazník ji nikdy nevidí.
* `fields.customParams` (objekt s libovolnými klíči, hodnota: text; nepovinný): Jen při zakládání: vlastní parametry do tabulky Parametry na detailu produktu, například \{"Materiál":"Kamenina","Objem":"350 ml"}. Nejsou to filtrovatelné vlastnosti.
* `fields.categoryIds` (pole, položka: text; nepovinný): ID kategorií, do kterých produkt patří. První se stane hlavní. Bez kategorie se produkt neobjeví ve výpisech obchodu.
* `fields.metaTitle` (text nebo `null`; nepovinný): SEO titulek. null smaže.
* `fields.metaDescription` (text nebo `null`; nepovinný): SEO popisek (meta description). null smaže.
* `fields.geoSummary` (text nebo `null`; nepovinný): Stručná přímá odpověď pro AI vyhledávače (GEO). Dvě až tři věty. null smaže.
* `fields.noindex` (`true` nebo `false`; nepovinný): true = stránku nemají vyhledávače indexovat.
* `modifiers` (pole objektů; nepovinný): Jen u `save_modifiers`: CELÁ sada skupin modifikátorů. Skupina, která tu není, se z produktu smaže. Současná sada: `shopzi_get_product` s `include: ["modifiers"]`.
* `modifiers[].name` (text; povinný): Název skupiny, například „Doplňky“.
* `modifiers[].modifierType` (jedna z hodnot `addon`, `removal`, `choice` a `other`; nepovinný): addon = doplněk, removal = odebrání součásti, choice = volba z několika, other = ostatní. Výchozí choice.
* `modifiers[].isRequired` (`true` nebo `false`; nepovinný): true = zákazník musí vybrat, než přidá zboží do košíku.
* `modifiers[].minSelections` (číslo; nepovinný): Nejmenší počet vybraných voleb, celé číslo. Výchozí 0.
* `modifiers[].maxSelections` (číslo nebo `null`; nepovinný): Největší povolený počet voleb, celé číslo. null = bez omezení.
* `modifiers[].options` (pole objektů; povinný): Volby ve skupině, v pořadí, v jakém se mají zobrazit.
* `modifiers[].options[].name` (text; povinný): Název volby, například „Bez cibule“.
* `modifiers[].options[].priceDeltaMinor` (číslo; nepovinný): Příplatek v HALÉŘÍCH, celé číslo. Může být záporný (volba, která zlevňuje). Výchozí 0.
* `modifiers[].options[].isDefault` (`true` nebo `false`; nepovinný): true = volba je předvybraná.
* `modifiers[].options[].isActive` (`true` nebo `false`; nepovinný): false = volba se zákazníkovi nenabízí. Výchozí true.

## `shopzi_manage_product`: parametry `attributes` až `pageContent` [#shopzi-manage-product-parametry-attributes-az-pagecontent]

* `attributes` (pole objektů; nepovinný): Jen u `save_attributes`: CELÁ sada filtrovatelných vlastností. Vlastnost, která tu není, se z produktu smaže. Vlastnosti, které u produktu určují varianty, sem nepatří. Současná: `include: ["attributes"]`.
* `attributes[].attributeKey` (text; povinný): Klíč vlastnosti ze `shopzi_list_catalog` (`resource: attributes`), například `material`.
* `attributes[].valueText` (text nebo `null`; nepovinný): Textová hodnota.
* `attributes[].valueNumeric` (číslo nebo `null`; nepovinný): Číselná hodnota, pro filtrování rozsahem.
* `attributes[].valueBool` (`true` nebo `false` nebo `null`; nepovinný): Hodnota ano/ne.
* `attributes[].unit` (text nebo `null`; nepovinný): Jednotka u číselné hodnoty, například `cm`.
* `attributes[].isFilterable` (`true` nebo `false`; nepovinný): false = vlastnost se ukáže v popisu, ale nebude filtrem. Výchozí true.
* `links` (pole objektů; nepovinný): Jen u `save_links`: CELÁ sada vazeb na jiné produkty. Vazba, která tu není, se smaže. Současná: `include: ["links"]`.
* `links[].linkedProductId` (UUID; povinný): ID propojeného produktu ze `shopzi_search_products`.
* `links[].linkType` (jedna z hodnot `related`, `cross_sell`, `up_sell`, `accessory`, `replacement`, `bundle_member` a `variant_of`; povinný): related = související, cross\_sell = k tomu se hodí, up\_sell = dražší alternativa, accessory = příslušenství, replacement = náhrada, bundle\_member = součást balíčku, variant\_of = jiné provedení.
* `translation` (objekt; nepovinný): Jen u `save_translation`: JEDEN jazyk, a to CELÝ: pole, které nepošlete, se v tom jazyce vymaže; prázdná pole překlad v tom jazyce smažou. Ostatní jazyky zůstanou. Současné: `include: ["translations"]`.
* `translation.locale` (jedna z hodnot `en`, `de`, `sk` a `pl`; povinný): Jazyk překladu. Čeština je základ produktu a překládá se přes `update`.
* `translation.title` (text nebo `null`; nepovinný): Název v tomto jazyce.
* `translation.subtitle` (text nebo `null`; nepovinný)
* `translation.description` (text nebo `null`; nepovinný): Popis v tomto jazyce. HTML se čistí (sanitizace).
* `translation.metaTitle` (text nebo `null`; nepovinný)
* `translation.metaDescription` (text nebo `null`; nepovinný)
* `translation.geoSummary` (text nebo `null`; nepovinný)
* `bundle` (pole objektů; nepovinný): Jen u `save_bundle`: CELÉ složení balíčku. Položka, která tu není, se z balíčku smaže. Funguje jen u produktu typu „Balíček“. Současné: `include: ["bundle"]`.
* `bundle[].componentProductId` (UUID; povinný): ID produktu, který je součástí balíčku, ze `shopzi_search_products`.
* `bundle[].quantity` (číslo; povinný): Kolik kusů toho produktu balíček obsahuje. Celé číslo od 1.
* `variants` (pole objektů; nepovinný): U `add_variants`: NOVÉ varianty, které k produktu přibudou (stávající se neposílají a nástroj se jich nedotkne; odebrat ani přecenit variantu tudy nejde). U `create` spolu s `axes`: varianty, se kterými produkt rovnou vznikne, každá kombinace hodnot jednou, první je výchozí. U `set_variant_axes`: nové varianty VEDLE stávající, každá s cenou.
* `variants[].axisValues` (objekt s libovolnými klíči, hodnota: text; povinný): Hodnota KAŽDÉ vlastnosti, která u produktu určuje variantu, klíčovaná jejím klíčem, například \{"velikost":"XL","barva":"Modrá"}. Hodnotu, kterou produkt zatím nemá, nástroj do té vlastnosti doplní.
* `variants[].sku` (text nebo `null`; nepovinný): Katalogové číslo varianty, musí být jedinečné.
* `variants[].ean` (text nebo `null`; nepovinný): Čárový kód varianty.
* `variants[].priceMinor` (číslo; povinný): Koncová cena varianty v HALÉŘÍCH, celé číslo (129 Kč = 12900). Povinná: varianta bez ceny se neprodá.
* `sourceUrl` (text, nejvýš 300 znaků; nepovinný): Jen u `import_from_url`: kořenová adresa e-shopu, ze kterého se mají produkty převzít ([https://obchod.cz](https://obchod.cz), ne adresa kategorie ani produktu).
* `axes` (pole objektů, nejvýš 3 položky; nepovinný): U `create`: vlastnosti, které u nového produktu určují varianty (velikost, barva). Produkt pak vznikne rovnou jako variantní s `variants`. U `set_variant_axes`: totéž pro EXISTUJÍCÍ jednoduchý produkt.
* `axes[].attributeKey` (text; povinný): Klíč vlastnosti, například `velikost` nebo `barva`.
* `axes[].label` (text; povinný): Název pro zákazníka, například Velikost.
* `axes[].values` (pole, položka: text, 1 až 30 položek; povinný): Hodnoty v pořadí, ve kterém se mají nabízet.
* `baseAxisValues` (objekt s libovolnými klíči, hodnota: text; nepovinný): Jen u `set_variant_axes`: hodnota KAŽDÉ vlastnosti z `axes` pro STÁVAJÍCÍ variantu, např. \{"velikost":"M"}. Ta si ponechá cenu, historii, zásobu i SKU a bude výchozí.
* `pageContent` (objekt; nepovinný): Jen u `save_page_content`: pole ke změně; vynechané zůstane beze změny.
* `pageContent.sizeGuideMode` (jedna z hodnot `inherit`, `custom` a `none`; nepovinný): Tabulka velikostí: inherit = podle kategorie, custom = `sizeGuideId`, none = nezobrazovat.
* `pageContent.sizeGuideId` (text nebo `null`; nepovinný): Jen u `sizeGuideMode: custom`: ID ze `shopzi_list_catalog` (`size_guides`).
* `pageContent.descriptionMode` (jedna z hodnot `text` a `builder`; nepovinný): text = pod produktem pole Popis; builder = bloky sestaveného popisu (textový popis dál slouží feedům a vyhledávání).
* `pageContent.descriptionHeadingMode` (jedna z hodnot `inherit`, `custom` a `hidden`; nepovinný): Nadpis nad popisem: podle obchodu, vlastní text, nebo bez nadpisu.
* `pageContent.descriptionHeading` (text, nejvýš 80 znaků nebo `null`; nepovinný): Jen u `descriptionHeadingMode: custom`: text nadpisu.
* `pageContent.contentWidth` (jedna z hodnot `boxed` a `full`; nepovinný): Šířka sestaveného popisu: boxed = v šířce stránky, full = přes celé okno.
* `pageContent.blocks` (pole objektů, nejvýš 40 položek; nepovinný): CELÁ sada bloků sestaveného popisu v pořadí. Blok, který tu není, z popisu zmizí. Prázdné pole popis vyprázdní (stránka pak ukáže textový popis). Současné: `include: ["page_content"]`.
* `pageContent.blocks[].sectionType` (jedna z hodnot `heading`, `rich_text`, `image`, `image_text`, `gallery`, `video`, `banner`, `columns`, `spacer`, `notice`, `usp_strip`, `process_steps`, `faq` a `promo_split`; povinný): Typ bloku, jen obsahové bloky editoru stránek.
* `pageContent.blocks[].config` (objekt s libovolnými klíči; povinný): Nastavení bloku ve tvaru editoru stránek (html se čistí).
* `pageContent.blocks[].isActive` (`true` nebo `false`; nepovinný)
* `pageContent.panelOverrides` (pole objektů; nepovinný): Výjimky informačních panelů u produktu: show = přidat, hide = skrýt, null = podle nastavení panelu. Nahradí celou sadu výjimek.
* `pageContent.panelOverrides[].panelId` (text; povinný)
* `pageContent.panelOverrides[].mode` (jedna z hodnot `show` a `hide`, nebo `null`; povinný)

## `shopzi_manage_product`: parametry `variantUpdates` a `idempotencyKey` [#shopzi-manage-product-parametry-variantupdates-a-idempotencykey]

* `variantUpdates` (pole objektů; nepovinný): Jen u `update_variants`: údaje EXISTUJÍCÍCH variant, každá podle svého ID. Posílají se jen pole ke změně; varianta, o které tu není řeč, zůstane beze změny. Odebrat variantu (na to je `remove_variants`) ani změnit cenu tudy nejde. Současné: `include: ["details"]`.
* `variantUpdates[].variantId` (UUID; povinný): ID varianty ze `shopzi_get_product`. U jednoduchého produktu je to ta jediná, kterou vrací s `is_default: true`.
* `variantUpdates[].sku` (text nebo `null`; nepovinný): Katalogové číslo varianty, musí být jedinečné. Prázdná hodnota ho vymaže.
* `variantUpdates[].ean` (text nebo `null`; nepovinný): Čárový kód varianty.
* `variantUpdates[].gtin` (text nebo `null`; nepovinný): GTIN varianty.
* `variantUpdates[].mpn` (text nebo `null`; nepovinný): Číslo dílu od výrobce (MPN).
* `variantUpdates[].weightGrams` (číslo nebo `null`; nepovinný): Hmotnost v GRAMECH, celé nezáporné číslo (1,2 kg = 1200). Podle ní počítá dopravce cenu zásilky, takže bez ní se doprava nemusí nabídnout.
* `variantUpdates[].dimensionsMm` (objekt nebo `null`; nepovinný): Rozměry zásilky v MILIMETRECH. Dopravci mají na rozměry limity, podle kterých se metoda nabídne, nebo skryje.
* `variantUpdates[].dimensionsMm.l` (číslo; povinný): Délka v milimetrech, celé číslo.
* `variantUpdates[].dimensionsMm.w` (číslo; povinný): Šířka v milimetrech, celé číslo.
* `variantUpdates[].dimensionsMm.h` (číslo; povinný): Výška v milimetrech, celé číslo.
* `variantUpdates[].isDefault` (`true` nebo `false`; nepovinný): `true` označí tuhle variantu jako výchozí (předvybranou na detailu produktu). Výchozí varianta se jen PŘENÁŠÍ: zhasnout ji nejde, stejně jako v administraci.
* `variantUpdates[].lowStockThreshold` (číslo nebo `null`; nepovinný): Vlastní práh nízkého stavu v kusech. `null` nebo 0 = práh obchodu.
* `idempotencyKey` (text, 1 až 200 znaků; nepovinný): Klíč idempotence. Stejný klíč = stejný zápis: opakované volání vrátí původní výsledek a NEZAPÍŠE podruhé. Použijte vlastní náhodný řetězec pro každou zamýšlenou změnu; při opakování po chybě sítě pošlete tentýž.

## `shopzi_manage_category` [#shopzi-manage-category]

Založí, upraví (včetně obrázku kategorie z knihovny médií), přesune, přeskládá nebo smaže kategorii ve stromu o nejvýš třech úrovních. Kategorii s podkategoriemi nebo s produkty smazat odmítne.

* **Oprávnění:** `products:write`, u klíče „Katalog: produkty, kategorie a číselníky (zápis)“.
* **Druh:** zápis, který umí přepsat nebo smazat existující data (`destructiveHint`).
* **Potvrzení přes MCP:** ano: formulář v klientu, který potvrdí ten, kdo drží klíč; jinak odkaz na stránku schválení přes elicitaci URL; jinak odkaz na stránku schválení v odmítnutí `approval_required`. Na stránce schválení rozhoduje vlastník nebo manažer obchodu.
* **Kredity a platba kartou:** ne.
* **Deník změn:** výsledek nese `change_id`. ID záznamu v deníku. Předejte ho do `shopzi_undo_change`.

### `shopzi_manage_category`: operace [#shopzi-manage-category-operace]

* `create` (založit)
* `update` (upravit)
* `move` (přesunout)
* `reorder` (změnit pořadí)
* `delete` (smazat)

## `shopzi_manage_category`: parametry [#shopzi-manage-category-parametry]

* `operation` (jedna z hodnot `create`, `update`, `move`, `reorder` a `delete`; povinný): create = založit; update = změnit pole existující kategorie; move = přesunout ve stromu; reorder = přeskládat sourozence; delete = smazat.
* `categoryId` (text; nepovinný): ID kategorie ze `shopzi_list_catalog`. Povinné u update, move a delete.
* `parentId` (text nebo `null`; nepovinný): Nadřazená kategorie. U `create` kam ji založit, u `move` kam ji přesunout, u `reorder` čí sourozence skládáte. `null` znamená nejvyšší úroveň; vynechané pole u `move` nechá nadřazenou kategorii beze změny.
* `position` (číslo; nepovinný): Pořadí mezi sourozenci po přesunu, celé číslo (0 = první). Jen u `move`.
* `orderedIds` (pole, položka: text; nepovinný): Jen u `reorder`: ID VŠECH kategorií dané úrovně v novém pořadí, každé právě jednou.
* `fields` (objekt; nepovinný): Údaje kategorie. U `create` to jsou hodnoty nové kategorie, u `update` jen pole ke změně (vynechané zůstane beze změny). U `move`, `reorder` a `delete` se nepoužívá.
* `fields.name` (text; nepovinný): Název kategorie. POVINNÝ při zakládání.
* `fields.slug` (text; nepovinný): URL adresa (malá písmena, číslice, pomlčky). Vynechte a odvodí se z názvu. Jen při zakládání: pozdější změna adresy je přesměrování, ne úprava.
* `fields.descriptionHtml` (text nebo `null`; nepovinný): Text nad výpisem produktů. HTML se čistí.
* `fields.descriptionHtmlBottom` (text nebo `null`; nepovinný): SEO text pod výpisem produktů. HTML se čistí.
* `fields.h1Override` (text nebo `null`; nepovinný)
* `fields.isFeatured` (`true` nebo `false`; nepovinný)
* `fields.showInMenu` (`true` nebo `false`; nepovinný)
* `fields.imageUrl` (text nebo `null`; nepovinný): Obrázek kategorie (dlaždice v mřížce kategorií a v megamenu): adresa `/media/…` z knihovny médií tohoto obchodu, třeba z `shopzi_generate_media`. `null` obrázek odebere.
* `fields.metaTitle` (text nebo `null`; nepovinný): SEO titulek. null smaže.
* `fields.metaDescription` (text nebo `null`; nepovinný): SEO popisek (meta description). null smaže.
* `fields.geoSummary` (text nebo `null`; nepovinný): Stručná přímá odpověď pro AI vyhledávače (GEO). Dvě až tři věty. null smaže.
* `fields.noindex` (`true` nebo `false`; nepovinný): true = stránku nemají vyhledávače indexovat.
* `idempotencyKey` (text, 1 až 200 znaků; nepovinný): Klíč idempotence. Stejný klíč = stejný zápis: opakované volání vrátí původní výsledek a NEZAPÍŠE podruhé. Použijte vlastní náhodný řetězec pro každou zamýšlenou změnu; při opakování po chybě sítě pošlete tentýž.

## `shopzi_save_catalog_entity` [#shopzi-save-catalog-entity]

Spravuje značky a výrobce uvedené u produktů (`vendor`), definice vlastností (`attribute`), tabulky velikostí (`size_guide`) a informační panely stránky produktu (`info_panel`): založení, úpravu, kopii, smazání, pořadí, přiřazení kategoriím, šablony vlastností a karty značek podle produktů.

* **Oprávnění:** `products:write`, u klíče „Katalog: produkty, kategorie a číselníky (zápis)“.
* **Druh:** zápis, který umí přepsat nebo smazat existující data (`destructiveHint`).
* **Potvrzení přes MCP:** ano: formulář v klientu, který potvrdí ten, kdo drží klíč; jinak odkaz na stránku schválení přes elicitaci URL; jinak odkaz na stránku schválení v odmítnutí `approval_required`. Na stránce schválení rozhoduje vlastník nebo manažer obchodu.
* **Kredity a platba kartou:** ne.
* **Deník změn:** výsledek nese `change_id`. ID záznamu v deníku. Předejte ho do `shopzi_undo_change`.
* **Věta o důsledku, kterou člověk uvidí v potvrzení:**

  > Smazání vlastnosti NEMAŽE hodnoty u produktů, jen je schová: zmizí filtr ve výpisu i políčko v editoru a vrácení vlastnosti je zase zviditelní. Přeskládání pořadí je jen pořadí a taky se vrací. Smazat značku jde jen tehdy, když ji nemá u sebe ani jeden produkt: jinak nástroj odmítne a řekne kolik jich je. Založení karet ze značek se provede přesně na značkách vypsaných níž a ty produkty na ně naváže; vrátit to jde jedním krokem, celou dávku najednou. Šablona vlastnosti, které obchod už má, nepřepisuje, jen je přeskočí.

### `shopzi_save_catalog_entity`: oblasti [#shopzi-save-catalog-entity-oblasti]

* `vendor` (Značka nebo výrobce)
* `attribute` (Vlastnost produktu)
* `size_guide` (Tabulka velikostí)
* `info_panel` (Informační panel)

### `shopzi_save_catalog_entity`: operace [#shopzi-save-catalog-entity-operace]

* `save` (uložit)
* `delete` (smazat)
* `reorder` (změnit pořadí)
* `create_from_brands` (založit značky podle produktů)
* `apply_preset` (přidat šablonu vlastností)
* `duplicate` (vytvořit kopii)

## `shopzi_save_catalog_entity`: parametry [#shopzi-save-catalog-entity-parametry]

* `resource` (jedna z hodnot `vendor`, `attribute`, `size_guide` a `info_panel`; povinný): Co ukládáte. Pole musí patřit k němu.
* `operation` (jedna z hodnot `save`, `delete`, `reorder`, `create_from_brands`, `apply_preset` a `duplicate`; nepovinný): `save` (výchozí) = založit nebo upravit; `delete` = smazat vlastnost nebo značku, kterou nemá u sebe žádný produkt; `reorder` = přeskládat pořadí vlastností; `apply_preset` = přidat hotovou šablonu vlastností; `create_from_brands` = založit karty značek podle pole Značka u produktů; `duplicate` = kopie tabulky velikostí nebo panelu. `apply_preset` platí jen pro `resource: attribute`, `create_from_brands` jen pro `resource: vendor`, `duplicate` jen pro `size_guide` a `info_panel`; `reorder` pro vlastnost, tabulku velikostí i panel.
* `id` (text; nepovinný): Vynechte pro založení nového. Vyplňte pro úpravu existujícího nebo pro `delete`.
* `orderedIds` (pole, položka: text, nejvýš 200 položek; nepovinný): Jen `reorder`: nové pořadí vlastností. Musí obsahovat VŠECHNY vlastnosti obchodu právě jednou (ze `shopzi_list_catalog` s `resource: attributes`), jinak nástroj zápis odmítne: vynechaná vlastnost by zůstala na starém čísle a pořadí by se zdvojilo.
* `brands` (pole, položka: text, nejvýš 200 znaků, nejvýš 40 položek; nepovinný): Jen `create_from_brands`: názvy značek, které se mají založit, VYJMENOVANÉ. Nabídku i s počty produktů vypíše nástroj sám, když ho zavoláte bez tohohle pole.
* `presetKey` (jedna z hodnot `obleceni`, `elektronika`, `domacnost`, `sport` a `obecne`; nepovinný): Jen `apply_preset`: která šablona vlastností se má přidat. Vlastnosti, které obchod už má, se přeskočí a nepřepisují se.
* `fields` (objekt; nepovinný): Pole k uložení. Vynechané pole zůstane u úpravy beze změny.
* `fields.name` (text; nepovinný): Dodavatel: název. POVINNÝ při zakládání dodavatele.
* `fields.slug` (text; nepovinný): Dodavatel: URL adresa. Vynechte a odvodí se z názvu. Jen při zakládání.
* `fields.perex` (text nebo `null`; nepovinný): Dodavatel: krátký úvod.
* `fields.descriptionHtml` (text nebo `null`; nepovinný): Dodavatel: popis na jeho stránce. HTML se čistí.
* `fields.websiteUrl` (text nebo `null`; nepovinný)
* `fields.email` (text nebo `null`; nepovinný)
* `fields.phone` (text nebo `null`; nepovinný)
* `fields.region` (text nebo `null`; nepovinný): Dodavatel: region či země.
* `fields.position` (číslo; nepovinný): Pořadí ve výpisu, celé číslo (0 = první).
* `fields.isFeatured` (`true` nebo `false`; nepovinný): Dodavatel: vypíchnout ve výpisu.
* `fields.h1Override` (text nebo `null`; nepovinný)
* `fields.label` (text; nepovinný): Vlastnost: název, který uvidí zákazník (Barva, Velikost). POVINNÝ při zakládání.
* `fields.control` (jedna z hodnot `select`, `range`, `boolean` a `swatch`; nepovinný): Vlastnost: typ. select = výběr z hodnot, swatch = barevné vzorky, range = číselný rozsah, boolean = ano/ne.
* `fields.options` (pole objektů; nepovinný): Vlastnost: seznam hodnot. Povinný u select a swatch.
* `fields.options[].value` (text; povinný)
* `fields.options[].color` (text; nepovinný): Jen u swatch: barva vzorku ve tvaru #RRGGBB.
* `fields.unit` (text nebo `null`; nepovinný): Vlastnost: jednotka u typu range, například GB.
* `fields.isFilterable` (`true` nebo `false`; nepovinný): Vlastnost: nabízet ji jako filtr ve výpisu produktů.
* `fields.groupLabel` (text nebo `null`; nepovinný): Vlastnost: název skupiny v parametrech produktu.
* `fields.variantDisplay` (jedna z hodnot `auto`, `badges` a `list`; nepovinný): Vlastnost: jak se hodnoty kreslí u varianty na detailu produktu.
* `fields.isActive` (`true` nebo `false`; nepovinný): Vypnuté se nikde nenabízí.
* `fields.templateKey` (jedna z hodnot `women-tops`, `women-bottoms`, `women-dresses`, `men-tops`, `men-bottoms`, `shoes`, `kids`, `bras`, `rings`, `hats`, `gloves` a `blank`; nepovinný): Tabulka velikostí: založit ze šablony (jen při zakládání). women-tops, women-bottoms, women-dresses, men-tops, men-bottoms, shoes, kids, bras, rings, hats, gloves, blank.
* `fields.table` (objekt; nepovinný): Tabulka velikostí: CELÁ tabulka. `columns` = sloupce (id + název), `rows` = řádky, v každém `cells` = hodnota podle id sloupce. Buňky jsou text („84–88“, „XS“). Míry těla v cm.
* `fields.table.columns` (pole objektů, nejvýš 20 položek; povinný)
* `fields.table.columns[].id` (text; povinný)
* `fields.table.columns[].label` (text; povinný)
* `fields.table.rows` (pole objektů, nejvýš 60 položek; povinný)
* `fields.table.rows[].id` (text; povinný)
* `fields.table.rows[].cells` (objekt s libovolnými klíči, hodnota: text; povinný)
* `fields.introHtml` (text; nepovinný): Tabulka velikostí: úvodní text nad tabulkou (HTML se čistí).
* `fields.measureHtml` (text; nepovinný): Tabulka velikostí: návod Jak měřit (HTML se čistí).
* `fields.imageUrl` (text nebo `null`; nepovinný): Tabulka velikostí: ilustrace měření, adresa z knihovny Médií.
* `fields.categoryIds` (pole, položka: text, nejvýš 200 položek; nepovinný): Tabulka velikostí: CELÁ sada kategorií, které ji mají (podkategorie ji zdědí); kategorie, která tu není, o ni přijde. Informační panel: kategorie, u jejichž produktů se ukáže (jen se `scope: categories`).
* `fields.title` (text; nepovinný): Informační panel: název řádku, který zákazník rozklikne. POVINNÝ při zakládání.
* `fields.bodyHtml` (text; nepovinný): Informační panel: text panelu (HTML se čistí).
* `fields.icon` (jedna z hodnot `info`, `shirt`, `droplets`, `leaf`, `scissors`, `truck`, `undo`, `shield`, `package`, `gift`, `ruler`, `sparkles`, `award` a `map-pin`, nebo `null`; nepovinný): Informační panel: ikona.
* `fields.scope` (jedna z hodnot `all` a `categories`; nepovinný): Informační panel: all = všechny produkty, categories = jen vybrané kategorie.
* `fields.metaTitle` (text nebo `null`; nepovinný): SEO titulek. null smaže.
* `fields.metaDescription` (text nebo `null`; nepovinný): SEO popisek (meta description). null smaže.
* `fields.geoSummary` (text nebo `null`; nepovinný): Stručná přímá odpověď pro AI vyhledávače (GEO). Dvě až tři věty. null smaže.
* `fields.noindex` (`true` nebo `false`; nepovinný): true = stránku nemají vyhledávače indexovat.
* `idempotencyKey` (text, 1 až 200 znaků; nepovinný): Klíč idempotence. Stejný klíč = stejný zápis: opakované volání vrátí původní výsledek a NEZAPÍŠE podruhé. Použijte vlastní náhodný řetězec pro každou zamýšlenou změnu; při opakování po chybě sítě pošlete tentýž.
