# MCP: obsah, média a vzhled

> Nástroje MCP pro stránky, články, bloky stránek, hlavičku a patičku, knihovnu Médií, generování obrázků a vzhled obchodu: oprávnění, potvrzení a parametry.

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

---

Obsah obchodu od stránek a článků (včetně rubrik, autora, pokročilého SEO a GEO a přepočtu skóre SEO) přes bloky stránek, které jde přidávat, upravovat i skrývat po jednom (včetně stránky před spuštěním s formulářem čekací listiny a stránky s poděkováním po přihlášení), hlavičku a patičku (i megamenu sestavené z kategorií a volbu loga) po knihovnu Médií a generování obrázků a videí, a k tomu vzhled: šablona, barvy, písma a logo, nebo celý ucelený vzhled najednou.

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_list_content` [#shopzi-list-content]

Vrátí podle `resource` přehled stránek, článků, rubrik blogu, bloků stránky (bez `pageId` domovské), souborů v Médiích, nebo galerie jednoho produktu. Články filtruje a řadí jako seznam v administraci (text, rubrika, stav, datum vytvoření, řazení i podle čtenosti), soubory v Médiích podle textu a druhu. Tělo stránky ani článku nevrací, to vrací `shopzi_get_content`.

* **Oprávnění:** `content:read`, u klíče „Obsah: stránky, blog, sekce, média (čtení)“.
* **Druh:** čtení (`readOnlyHint`).
* **Potvrzení přes MCP:** ne.
* **Kredity a platba kartou:** ne.

### `shopzi_list_content`: oblasti [#shopzi-list-content-oblasti]

* `pages`
* `blog_posts`
* `blog_categories`
* `home_sections`
* `media` (Soubor v Médiích)
* `product_media` (Obrázek v galerii produktu)

## `shopzi_list_content`: parametry [#shopzi-list-content-parametry]

* `resource` (jedna z hodnot `pages`, `blog_posts`, `blog_categories`, `home_sections`, `media` a `product_media`; povinný)
* `pageId` (UUID; nepovinný): ID stránky ze `shopzi_list_content` s `resource: pages`. Vynechte pro domovskou stránku.
* `productId` (UUID; nepovinný): Jen `product_media`: ID produktu ze `shopzi_search_products`.
* `search` (text, 1 až 120 znaků; nepovinný): Jen `blog_posts` a `media`. U článků text v názvu nebo v těle, u médií v cestě nebo v adrese souboru. Hledá se i uvnitř slova a na pořadí slov nezáleží.
* `categoryId` (UUID; nepovinný): Jen `blog_posts`: ID kategorie blogu ze `shopzi_list_content` s `resource: blog_categories`.
* `status` (jedna z hodnot `published` a `draft`; nepovinný): Jen `blog_posts`: `published` = publikované články, `draft` = koncepty. Vynechané = obojí.
* `dateFrom` (text; nepovinný): Jen `blog_posts`: datum VYTVOŘENÍ od, ve tvaru YYYY-MM-DD (celý den včetně).
* `dateTo` (text; nepovinný): Jen `blog_posts`: datum VYTVOŘENÍ do, ve tvaru YYYY-MM-DD (celý den včetně).
* `sortBy` (jedna z hodnot `title`, `created_at`, `published_at` a `view_count`; nepovinný): Jen `blog_posts`: podle čeho řadit. `view_count` = návštěvnost, `published_at` = datum publikace, `title` = název, `created_at` (výchozí) = datum vytvoření.
* `sortDir` (jedna z hodnot `asc` a `desc`; nepovinný): Jen `blog_posts`: `desc` (výchozí) = sestupně, `asc` = vzestupně. Nejčtenější článek je `sortBy: view_count` a `sortDir: desc`.
* `mediaType` (jedna z hodnot `image`, `video` a `document`; nepovinný): Jen `media`: `image` = obrázky, `video` = videa, `document` = všechno ostatní (PDF a jiné soubory). Vynechané = všechny druhy.
* `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_get_content` [#shopzi-get-content]

Vrátí jednu stránku nebo článek i s celým textem a poli SEO, včetně pokročilého SEO a GEO, u stránky i šířky obsahu a u článku rubriky, autora, úvodního obrázku a strukturovaných dat s FAQ, ve stejném tvaru, v jakém je zapisuje `shopzi_manage_content`. U souboru z Médií vrátí jeho údaje a obrázek přiloží, aby ho model viděl.

* **Oprávnění:** `content:read`, u klíče „Obsah: stránky, blog, sekce, média (čtení)“.
* **Druh:** čtení (`readOnlyHint`).
* **Potvrzení přes MCP:** ne.
* **Kredity a platba kartou:** ne.

### `shopzi_get_content`: oblasti [#shopzi-get-content-oblasti]

* `page` (Stránka)
* `blog_post` (Článek)
* `media` (Soubor v Médiích)

## `shopzi_get_content`: parametry [#shopzi-get-content-parametry]

* `resource` (jedna z hodnot `page`, `blog_post` a `media`; povinný)
* `id` (UUID; nepovinný): Stránka a článek: ID z `shopzi_list_content`. U `media` se nepoužívá.
* `mediaUrl` (text, nejvýš 500 znaků; nepovinný): Jen `media`: adresa obrázku `/media/…`. Nevymýšlejte ji.

## `shopzi_update_appearance` [#shopzi-update-appearance]

Změní vzhled obchodu v jedné sekci: šablonu a barvy, písma, rozvržení (včetně fotky a jejího rozostření v pruhu s nadpisem stránky), animace, logo, logo pro tmavé pozadí a favicon adresou z knihovny Médií, nebo celý ucelený vzhled (šablona a písma spočítané podle oboru a barvy obchodu, s další variantou na požádání).

* **Oprávnění:** `appearance:write`, u klíče „Vzhled: šablona, písmo, barvy (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_update_appearance`: oblasti [#shopzi-update-appearance-oblasti]

* `theme` (Šablona a barvy)
* `typography` (Písma)
* `layout` (Rozložení)
* `motion` (Pohyb a efekty)
* `branding` (Logo a ikonka)
* `look` (Ucelený vzhled (šablona a písma))

## `shopzi_update_appearance`: parametry [#shopzi-update-appearance-parametry]

* `resource` (jedna z hodnot `theme`, `typography`, `layout`, `motion`, `branding` a `look`; povinný): Která část vzhledu. Pole musí patřit do ní.
* `fields` (objekt, schéma připouští i další klíče; nepovinný): Pole ke změně. Vynechané pole zůstane beze změny. U `resource: look` se neposílá.
* `fields.template_name` (jedna z hodnot `default`, `tokio`, `elegance`, `brutalist`, `neon`, `organic`, `heritage`, `onyx`, `noir`, `blossom`, `mono`, `sunset`, `sage`, `azure`, `butter`, `boutique`, `luxe`, `esso`, `terminal`, `vapor`, `aurora`, `bauhaus`, `oro`, `paper` a `kattegate`; nepovinný): Šablona vzhledu obchodu. Šablonu vytvořenou na míru jinému obchodu nástroj odmítne; obchod, který ji už používá, ji smí ponechat. (sekce theme)
* `fields.primary_color` (text se vzorem `^#[0-9a-fA-F]{6}$`; nepovinný): Primární barva obchodu ve tvaru #RRGGBB. Prázdnou hodnotu nelze uložit, obchod musí mít barvu. (sekce theme)
* `fields.secondary_color` (text se vzorem `^(#[0-9a-fA-F]{6})?$`; nepovinný): Sekundární barva ve tvaru #RRGGBB. "" zruší vlastní barvu a použije se barva ze šablony. (sekce theme)
* `fields.accent_color` (text se vzorem `^(#[0-9a-fA-F]{6})?$`; nepovinný): Akcentová barva ve tvaru #RRGGBB. "" zruší vlastní barvu a použije se barva ze šablony. (sekce theme)
* `fields.surface_mode` (jedna z hodnot prázdný text, `light` a `dark`; nepovinný): Světlost povrchů. "" = podle šablony, light = světlý, dark = tmavý. (sekce theme)
* `fields.heading_font` (jedna z hodnot prázdný text, `inter`, `roboto`, `open-sans`, `lato`, `montserrat`, `poppins`, `raleway`, `nunito`, `work-sans`, `dm-sans`, `manrope`, `outfit`, `space-grotesk`, `josefin-sans`, `playfair-display`, `merriweather`, `lora`, `pt-serif`, `roboto-slab`, `cormorant-garamond`, `eb-garamond`, `fraunces`, `oswald`, `dm-serif-display` a `jetbrains-mono`; nepovinný): Písmo nadpisů z katalogu písem. "" = písmo ze šablony. (sekce typography)
* `fields.body_font` (jedna z hodnot prázdný text, `inter`, `roboto`, `open-sans`, `lato`, `montserrat`, `poppins`, `raleway`, `nunito`, `work-sans`, `dm-sans`, `manrope`, `outfit`, `space-grotesk`, `josefin-sans`, `playfair-display`, `merriweather`, `lora`, `pt-serif`, `roboto-slab`, `cormorant-garamond`, `eb-garamond`, `fraunces`, `oswald`, `dm-serif-display` a `jetbrains-mono`; nepovinný): Písmo textu z katalogu písem. "" = písmo ze šablony. (sekce typography)
* `fields.hero_layout` (jedna z hodnot `fullwidth` a `split`; nepovinný): Rozvržení úvodního pruhu: fullwidth (přes celou šířku) nebo split (na dva sloupce). (sekce layout)
* `fields.pdp_sticky_buybox` (`true` nebo `false`; nepovinný): Nákupní box na detailu produktu zůstává při rolování na místě. (sekce layout)
* `fields.hero_band_image_url` (text, nejvýš 500 znaků; nepovinný): Fotka v pruhu s nadpisem stránky. Adresa musí být z knihovny médií tohoto obchodu, ve tvaru /media/… (vezměte ji z nástroje na média, nevymýšlejte ji). Prázdná hodnota obrázek odebere. (sekce layout)
* `fields.hero_band_blur` (jedna z hodnot `none`, `soft` a `strong`; nepovinný): Rozostření fotky v pruhu: none | soft | strong. (sekce layout)
* `fields.welcome_animation_enabled` (`true` nebo `false`; nepovinný): Zobrazit uvítací animaci při první návštěvě. (sekce motion)
* `fields.welcome_animation_style` (jedna z hodnot `fade`, `zoom`, `curtain` a `ring`; nepovinný): Styl uvítací animace. (sekce motion)
* `fields.welcome_animation_duration` (celé číslo od 800 do 6000; nepovinný): Jak dlouho je uvítací animace vidět, v milisekundách (800 až 6000). (sekce motion)
* `fields.welcome_animation_text` (text, nejvýš 120 znaků nebo `null`; nepovinný): Text pod logem v uvítací animaci. (sekce motion)
* `fields.welcome_animation_logo_url` (text, nejvýš 500 znaků; nepovinný): Logo v uvítací animaci. Prázdná hodnota použije logo obchodu. Adresa musí být z knihovny médií tohoto obchodu, ve tvaru /media/… (vezměte ji z nástroje na média, nevymýšlejte ji). Prázdná hodnota obrázek odebere. (sekce motion)
* `fields.page_loader_style` (jedna z hodnot `bar`, `overlay`, `both` a `off`; nepovinný): Indikátor načítání stránky: bar, overlay, both nebo off. (sekce motion)
* `fields.logo_url` (text, nejvýš 500 znaků; nepovinný): Logo obchodu (pro světlé pozadí). Objevuje se v hlavičce, v uvítací animaci a na daňovém dokladu, pokud má obchod zapnuté logo na dokladech; doklad se vykresluje až při stažení, takže se výměna projeví i na dokladech vystavených dřív. Adresa musí být z knihovny médií tohoto obchodu, ve tvaru /media/… (vezměte ji z nástroje na média, nevymýšlejte ji). Prázdná hodnota obrázek odebere. (sekce branding)
* `fields.logo_light_url` (text, nejvýš 500 znaků; nepovinný): Logo pro tmavé pozadí. Použije se tam, kde by tmavé logo zaniklo. Adresa musí být z knihovny médií tohoto obchodu, ve tvaru /media/… (vezměte ji z nástroje na média, nevymýšlejte ji). Prázdná hodnota obrázek odebere. (sekce branding)
* `fields.favicon_url` (text, nejvýš 500 znaků; nepovinný): Favicon, tedy ikona obchodu na záložce prohlížeče. Adresa musí být z knihovny médií tohoto obchodu, ve tvaru /media/… (vezměte ji z nástroje na média, nevymýšlejte ji). Prázdná hodnota obrázek odebere. (sekce branding)
* `look` (objekt; nepovinný): Jen u `resource: look`: ucelený vzhled (šablona a písma) spočítaný podle oboru a barvy obchodu. Barvy ani logo nemění.
* `look.businessType` (jedna z hodnot `moda`, `elektronika`, `kosmetika`, `domacnost`, `sport`, `hracky`, `sperky`, `potraviny` a `jine`; nepovinný): Obor obchodu. Vynechaný = obor uložený v nastavení obchodu.
* `look.variant` (celé číslo od 1 do 20; nepovinný): Která varianta: 1 = nejlépe sedící, 2, 3… další. Výchozí 1.
* `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_page_blocks` [#shopzi-save-page-blocks]

Uloží bloky jedné stránky: přidá, odebere, zkopíruje nebo přesune jeden blok, změní nastavení nebo viditelnost jednoho hotového bloku (`update_block`, ostatních bloků se nedotkne), nebo operací `replace` nahradí celou sadu bloků. Bez `pageId` pracuje s domovskou stránkou, s `prelaunchPage: true` se stránkou před spuštěním, kterou ukazuje závěs místo obchodu, a s `thankYouPage: true` se stránkou s poděkováním po přihlášení k odběru (obě se založí, když ještě nejsou).

* **Oprávnění:** `content:write`, u klíče „Obsah: stránky, blog a média (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í:**

  > Operace „přepsat celou sadu bloků“ nahradí CELOU stránku poslanou sadou: co v ní není, ze stránky zmizí. Přidání, odebrání, zduplikování ani přesun jednoho bloku se ostatních bloků nedotknou. Vrátit to jde v obou případech jedním krokem přes „vrátit zpět“.

### `shopzi_save_page_blocks`: operace [#shopzi-save-page-blocks-operace]

* `replace` (přepsat celou sadu bloků)
* `add_block` (přidat blok)
* `remove_block` (odebrat blok)
* `duplicate_block` (zduplikovat blok)
* `move_block` (přesunout blok)
* `update_block` (upravit blok)

## `shopzi_save_page_blocks`: parametry [#shopzi-save-page-blocks-parametry]

* `operation` (jedna z hodnot `replace`, `add_block`, `remove_block`, `duplicate_block`, `move_block` a `update_block`, výchozí `replace`; nepovinný): Co se stránkou udělat. `replace` = nahradit CELOU sadu bloků polem `blocks` (co v něm není, ze stránky zmizí). `add_block` = přidat jeden nový blok (`sectionType`, volitelně `config`, `isActive`, `position`). `remove_block` = odebrat jeden blok (`blockId`). `duplicate_block` = zkopírovat jeden blok (`blockId`); kopie vznikne hned pod ním a schovaná, stejně jako po kliknutí na Duplikovat v administraci. `move_block` = přesunout jeden blok na jiné pořadí (`blockId`, `position`). `update_block` = změnit jeden hotový blok (`blockId` a aspoň jedno z `config`, `isActive`).
* `pageId` (UUID; nepovinný): ID stránky ze `shopzi_list_content` (resource=pages). Vynechané = domovská stránka.
* `prelaunchPage` (`true` nebo `false`; nepovinný): true = stránka před spuštěním (ukazuje ji závěs místo obchodu); když ještě není, založí se. Nejde kombinovat s `pageId`.
* `thankYouPage` (`true` nebo `false`; nepovinný): true = stránka s poděkováním po přihlášení k odběru (`/odber-novinek/dekujeme`); když ještě není, založí se. Nejde kombinovat s `pageId` ani `prelaunchPage`.
* `blocks` (pole objektů, 1 až 60 položek; nepovinný): Jen pro `replace`: celá sada bloků stránky v cílovém pořadí. Prázdný seznam nástroj nepřijímá: stránku bez jediného bloku smažte raději celou přes `shopzi_manage_content`.
* `blocks[].id` (text; nepovinný): ID existujícího bloku ze `shopzi_list_content` (resource=home\_sections). Vynechejte u nového bloku.
* `blocks[].sectionType` (jedna z hodnot `page_header`, `columns`, `hero`, `heading`, `notice`, `rich_text`, `image`, `image_text`, `gallery`, `video`, `cta`, `spacer`, `usp_strip`, `banner`, `banner_grid`, `product_grid`, `product_carousel`, `category_grid`, `category_buttons`, `vendor_grid`, `search_bar`, `newsletter`, `testimonials`, `logo_carousel`, `card_carousel`, `faq`, `promo_split`, `process_steps`, `person_profile`, `contact_form`, `contact_info`, `billing_info`, `map` a `business_hours`; povinný): Typ bloku. page\_header = Záhlaví stránky, columns = Sloupce, hero = Hero, heading = Nadpis, notice = Aktuální informace, rich\_text = Text, image = Obrázek, image\_text = Obrázek + text, gallery = Galerie, video = Video, cta = Výzva k akci, spacer = Mezera, usp\_strip = Výhody, banner = Banner, banner\_grid = Mozaika bannerů, product\_grid = Mřížka produktů, product\_carousel = Karusel produktů, category\_grid = Mřížka kategorií, category\_buttons = Tlačítka kategorií, vendor\_grid = Mřížka dodavatelů, search\_bar = Vyhledávání, newsletter = Newsletter, testimonials = Reference, logo\_carousel = Loga partnerů, card\_carousel = Karusel karet, faq = Časté dotazy, promo\_split = Promo dlaždice, process\_steps = Postup krok za krokem, person\_profile = Profil osoby, contact\_form = Kontaktní formulář, contact\_info = Kontaktní údaje, billing\_info = Fakturační údaje, map = Mapa, business\_hours = Pracovní doba
* `blocks[].config` (objekt s libovolnými klíči; nepovinný): Nastavení bloku podle jeho typu (nadpis, text, obrázek, odkaz, počet sloupců…). Neznámé pole nebo nepovolená hodnota zápis ODMÍTNE, nic se neuloží napůl. Volitelné `_style` (pozadí, odsazení) a `_responsive` (výjimky pro mobil a tablet) mají vlastní kontrolu.
* `blocks[].isActive` (`true` nebo `false`; nepovinný): false = blok zůstane uložený, ale na stránce se nezobrazí. Výchozí true.
* `blockId` (UUID; nepovinný): Jen pro `remove_block`, `duplicate_block`, `move_block` a `update_block`: ID bloku ze `shopzi_list_content` (resource=home\_sections). Musí patřit té stránce, se kterou pracujete.
* `sectionType` (jedna z hodnot `page_header`, `columns`, `hero`, `heading`, `notice`, `rich_text`, `image`, `image_text`, `gallery`, `video`, `cta`, `spacer`, `usp_strip`, `banner`, `banner_grid`, `product_grid`, `product_carousel`, `category_grid`, `category_buttons`, `vendor_grid`, `search_bar`, `newsletter`, `testimonials`, `logo_carousel`, `card_carousel`, `faq`, `promo_split`, `process_steps`, `person_profile`, `contact_form`, `contact_info`, `billing_info`, `map` a `business_hours`; nepovinný): Jen pro `add_block`: typ nového bloku. page\_header = Záhlaví stránky, columns = Sloupce, hero = Hero, heading = Nadpis, notice = Aktuální informace, rich\_text = Text, image = Obrázek, image\_text = Obrázek + text, gallery = Galerie, video = Video, cta = Výzva k akci, spacer = Mezera, usp\_strip = Výhody, banner = Banner, banner\_grid = Mozaika bannerů, product\_grid = Mřížka produktů, product\_carousel = Karusel produktů, category\_grid = Mřížka kategorií, category\_buttons = Tlačítka kategorií, vendor\_grid = Mřížka dodavatelů, search\_bar = Vyhledávání, newsletter = Newsletter, testimonials = Reference, logo\_carousel = Loga partnerů, card\_carousel = Karusel karet, faq = Časté dotazy, promo\_split = Promo dlaždice, process\_steps = Postup krok za krokem, person\_profile = Profil osoby, contact\_form = Kontaktní formulář, contact\_info = Kontaktní údaje, billing\_info = Fakturační údaje, map = Mapa, business\_hours = Pracovní doba
* `config` (objekt s libovolnými klíči; nepovinný): Pro `add_block`: nastavení nového bloku podle jeho typu. Pro `update_block`: jen měněná pole, sloučí se PO KLÍČÍCH, `null` pole odebere, seznamy (`items[]`) se posílají celé. Platí tatáž kontrola jako u `blocks`: neznámé pole nebo nepovolená hodnota zápis ODMÍTNE, nic se neuloží napůl.
* `isActive` (`true` nebo `false`; nepovinný): false = blok se uloží, ale na stránce se nezobrazí (u `add_block` výchozí true); u `update_block` blok skryje nebo zobrazí.
* `position` (celé číslo od 0 do 59; nepovinný): Pořadí bloku na stránce, počítáno od nuly (0 = úplně nahoře). U `add_block` vynechané znamená na konec stránky; u `move_block` je povinné.
* `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_content` [#shopzi-manage-content]

Zakládá, upravuje a maže stránky, články, rubriky blogu, soubory v Médiích a obrázky v galerii produktu. U stránky i článku mění i pokročilé SEO a GEO, u stránky šířku obsahu, u článku rubriku, autora, úvodní obrázek a strukturovaná data s FAQ. Umí znovu sečíst místo, které obchod zabírá v úložišti, a hned přepočítat skóre SEO a GEO obsahu, které se jinak počítá v noci.

* **Oprávnění:** `content:write`, u klíče „Obsah: stránky, blog a média (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í souboru je TRVALÉ, a platí to i pro fotku odebranou z galerie produktu: soubor se maže z úložiště, takže zmizí i z knihovny médií a všude, kde byl použitý, zůstane prázdné místo. Stránku, článek, rubriku blogu i uspořádání galerie vrátit lze. Přepočet úložiště nic nemaže a místo neuvolní, jen srovná údaj o zabraném místě podle skutečnosti; může tím obchod dostat i přes limit tarifu a zpátky se nevrací.

### `shopzi_manage_content`: oblasti [#shopzi-manage-content-oblasti]

* `page` (Stránka)
* `blog_post` (Článek)
* `blog_category` (Rubrika blogu)
* `media` (Soubor v Médiích)
* `product_media` (Obrázek v galerii produktu)
* `storage` (Úložiště)
* `seo_audit` (SEO skóre)

### `shopzi_manage_content`: operace [#shopzi-manage-content-operace]

* `create` (založit)
* `delete` (smazat)
* `update` (upravit)

## `shopzi_manage_content`: parametry `resource` až `displayOrder` [#shopzi-manage-content-parametry-resource-az-displayorder]

* `resource` (jedna z hodnot `page`, `blog_post`, `blog_category`, `media`, `product_media`, `storage` a `seo_audit`; povinný): Čeho se změna týká: `page` = stránka obchodu, `blog_post` = článek na blogu, `blog_category` = rubrika blogu, `media` = soubor v knihovně médií, `product_media` = galerie jednoho produktu (pořadí, hlavní obrázek, popisky, vazba na barvu), `storage` = přepočet toho, kolik místa obchod v úložišti zabírá (jen s `update`), `seo_audit` = přepočet SEO a GEO skóre stránek, kategorií, článků a produktů (jen s `update`).
* `operation` (jedna z hodnot `create`, `delete` a `update`; povinný): `create` = založit (u média nahrát, u galerie produktu přidat obrázek z knihovny), `delete` = smazat, `update` = změnit. U stránky a článku `update` mění pole v `fields` (titulek, text, SEO, publikaci), u média přepisuje popisky (`alt`, `title`) a u galerie produktu uspořádání.
* `title` (text, 1 až 200 znaků; nepovinný): Jen `create`. Stránka a článek: název (odvodí se z něj i adresa, pokud nepošlete `slug`). Médium: jméno souboru v knihovně; u `media` ho lze poslat i s `update`. U `product_media` s `update` je to popisek obrázku v galerii. U rubriky blogu je to její NÁZEV a posílá se i s `update`.
* `slug` (text, nejvýš 100 znaků; nepovinný): Jen `create` u stránky, článku a rubriky blogu: navrhovaná adresa. Očistí se a případně odduplikuje. Adresu HOTOVÉ stránky, článku ani rubriky tímhle nástrojem změnit nelze.
* `isActive` (`true` nebo `false`; nepovinný): Jen `create` u stránky: true ji rovnou zveřejní. Výchozí false (skrytá). U rubriky blogu zveřejňuje i při `update`; výchozí u nové rubriky je true.
* `isPublished` (`true` nebo `false`; nepovinný): Jen `create` u článku: true ho rovnou publikuje. Výchozí false (rozepsaný).
* `content` (text; nepovinný): Jen `create` u článku: tělo v HTML. Nebezpečné značky se odstraní. Nechcete-li ho psát hned, vynechte ho a doplňte později volánem `update` téhož nástroje.
* `excerpt` (text, nejvýš 1000 znaků; nepovinný): Jen `create` u článku: perex do výpisu. Vynechaný se vytvoří ze začátku těla.
* `categoryId` (text; nepovinný): Jen `create` u článku: ID rubriky ze `shopzi_list_content` (resource=blog\_categories). Hotový článek se přesouvá přes `fields.categoryId` u `update`.
* `featuredImageUrl` (text, nejvýš 1000 znaků; nepovinný): Jen `create` u článku: úvodní obrázek. Použijte adresu z knihovny médií (`shopzi_list_content` s resource=media), ne odkaz na cizí web.
* `authorName` (text, nejvýš 200 znaků; nepovinný): Jen `create` u článku: podepsaný autor. U hotového článku `fields.authorName`.
* `pageId` (text; nepovinný): `update` a `delete` u stránky: ID ze `shopzi_list_content` (resource=pages).
* `postId` (text; nepovinný): `update` a `delete` u článku: ID ze `shopzi_list_content` (resource=blog\_posts).
* `blogCategoryId` (text; nepovinný): `update` a `delete` u rubriky blogu: ID ze `shopzi_list_content` (resource=blog\_categories).
* `description` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Jen rubrika blogu: popisek rubriky. `null` ho smaže.
* `displayOrder` (celé číslo od 0 do 10000; nepovinný): Jen rubrika blogu: pořadí ve výpisu rubrik. Menší číslo je výš.

## `shopzi_manage_content`: parametry `fields` až `idempotencyKey` [#shopzi-manage-content-parametry-fields-az-idempotencykey]

* `fields` (objekt; nepovinný): Jen `update` u stránky a článku: pole ke změně. Zapíše se jen to, co pošlete, `null` pole vymaže. Text se přepisuje CELÝ, takže si nejdřív načtěte současný přes `shopzi_get_content`. U `create`, `delete` a u média se nepoužívá.
* `fields.title` (text; nepovinný)
* `fields.content` (text nebo `null`; nepovinný): Celé tělo v HTML. Nebezpečné značky se odstraní.
* `fields.excerpt` (text nebo `null`; nepovinný): Jen článek: perex do výpisu.
* `fields.featuredImageUrl` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Jen článek: úvodní obrázek. Adresa z knihovny médií (`shopzi_list_content` s resource=media) nebo z `shopzi_generate_media`, tedy `/media/…`; odkaz na cizí web se odmítne. `null` obálku článku odebere.
* `fields.isPublished` (`true` nebo `false`; nepovinný): Jen článek: publikovat nebo skrýt.
* `fields.isActive` (`true` nebo `false`; nepovinný): Jen stránka: zveřejnit nebo skrýt.
* `fields.showInHeader` (`true` nebo `false`; nepovinný): Jen stránka: starý příznak „připnuto do hlavičky“. Menu hlavičky ho UŽ NEČTE, odkazy se skládají v `shopzi_save_storefront_layout` (`header.links`), takže tímhle polem odkaz v hlavičce nepřidáte ani neodeberete. Nastavujte ho jen tehdy, když si obchodník výslovně řekne o ten příznak.
* `fields.categoryId` (UUID nebo `null`; nepovinný): Jen článek: přesunout do rubriky. ID ze `shopzi_list_content` (resource=blog\_categories); `null` článek z rubriky vyřadí.
* `fields.authorName` (text, nejvýš 200 znaků nebo `null`; nepovinný): Jen článek: podepsaný autor. `null` podpis odebere.
* `fields.ogImageUrl` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Obrázek pro sdílení (Open Graph): `/media/…` z knihovny obchodu nebo `https://…`. `null` = výchozí obrázek.
* `fields.canonicalOverride` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Kanonická adresa (`https://…` nebo `/…`), když je originálem jiná stránka; `null` ji zruší. Jen na výslovné přání obchodníka: špatná hodnota stránku vyřadí z vyhledávání.
* `fields.seo` (objekt nebo `null`; nepovinný): Pokročilé SEO a GEO. Slučuje se po klíčích: pošlete jen změny; `null` u klíče = výchozí, `null` za celé `seo` smaže vše. Stav vrací `shopzi_get_content`.
* `fields.seo.focusKeyphrase` (text, nejvýš 200 znaků nebo `null`; nepovinný)
* `fields.seo.ogTitle` (text, nejvýš 200 znaků nebo `null`; nepovinný)
* `fields.seo.ogDescription` (text, nejvýš 500 znaků nebo `null`; nepovinný)
* `fields.seo.twitterTitle` (text, nejvýš 200 znaků nebo `null`; nepovinný)
* `fields.seo.twitterDescription` (text, nejvýš 500 znaků nebo `null`; nepovinný)
* `fields.seo.twitterImage` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Stejná pravidla jako `ogImageUrl`.
* `fields.seo.schemaPageType` (jedna z hodnot `WebPage`, `AboutPage`, `ContactPage`, `CollectionPage` a `ItemPage`, nebo `null`; nepovinný): Typ pro strukturovaná data; `null` = WebPage.
* `fields.seo.robotsAdvanced` (pole, položka: jedna z hodnot `noimageindex`, `noarchive` a `nosnippet` nebo `null`; nepovinný): Pokyny pro roboty, celý seznam.
* `fields.seo.nofollow` (`true` nebo `false` nebo `null`; nepovinný)
* `fields.seo.breadcrumbTitle` (text, nejvýš 120 znaků nebo `null`; nepovinný): Kratší název v drobečkové navigaci.
* `fields.seo.cornerstone` (`true` nebo `false` nebo `null`; nepovinný): true = stěžejní obsah webu.
* `fields.seo.keyFacts` (pole, položka: text, 1 až 300 znaků, nejvýš 20 položek nebo `null`; nepovinný): Klíčová fakta pro AI vyhledávače (GEO), krátké věty. CELÝ seznam.
* `fields.contentWidth` (jedna z hodnot `boxed` a `full`; nepovinný): Jen stránka: `boxed` = sloupec (výchozí), `full` = k okrajům okna.
* `fields.structuredData` (objekt nebo `null`; nepovinný): Jen článek: strukturovaná data a FAQ. Po klíčích; `null` u klíče ho odebere, `null` za celé smaže vše.
* `fields.structuredData.articleType` (jedna z hodnot `Article`, `NewsArticle` a `BlogPosting`, nebo `null`; nepovinný)
* `fields.structuredData.keywords` (text, nejvýš 500 znaků nebo `null`; nepovinný): Klíčová slova oddělená čárkou.
* `fields.structuredData.enableBreadcrumbs` (`true` nebo `false` nebo `null`; nepovinný)
* `fields.structuredData.organizationName` (text, nejvýš 200 znaků nebo `null`; nepovinný)
* `fields.structuredData.organizationLogo` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Logo vydavatele: stejná pravidla jako `ogImageUrl`.
* `fields.structuredData.faqs` (pole objektů, nejvýš 30 položek nebo `null`; nepovinný): FAQ pod článkem (i FAQPage), text bez HTML. CELÝ seznam: co chybí, zmizí. `null` nebo `[]` FAQ odebere.
* `fields.structuredData.faqs[].question` (text, 1 až 300 znaků; povinný)
* `fields.structuredData.faqs[].answer` (text, 1 až 2000 znaků; povinný)
* `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.
* `sourceUrl` (text, nejvýš 2000 znaků; nepovinný): Jen `create` u média: veřejná adresa obrázku, který se má stáhnout do knihovny. Přijímá se JPEG, PNG, WebP a GIF do 5 MB.
* `mediaUrl` (text, nejvýš 1000 znaků; nepovinný): U `media` s `update` a `delete`: adresa souboru ze `shopzi_list_content` (resource=media). U `product_media` s `create`: adresa obrázku z knihovny, který se má k produktu přidat (soubor už musí v obchodě být, třeba z `shopzi_generate_media`).
* `alt` (text, nejvýš 300 znaků; nepovinný): U `media` i `product_media`: alternativní text (co je na obrázku). Čtou ho čtečky pro nevidomé i vyhledávače.
* `productId` (UUID; nepovinný): Jen `product_media`: ID produktu (UUID) ze `shopzi_search_products`.
* `mediaId` (UUID; nepovinný): Jen `product_media`: ID obrázku v galerii (UUID) ze `shopzi_list_content` (resource=product\_media). Potřebné pro `delete` a pro změnu jednoho obrázku.
* `orderedMediaIds` (pole, položka: UUID; nepovinný): Jen `product_media` s `update`: nové pořadí galerie. Musí obsahovat VŠECHNY obrázky produktu právě jednou, jinak nástroj zápis odmítne; jinak by obrázek, který v seznamu chybí, skončil v pořadí kdekoli.
* `isPrimary` (`true` nebo `false`; nepovinný): Jen `product_media` s `update` a `mediaId`: true udělá z obrázku hlavní (ten se ukazuje ve výpisu produktů). Hlavní obrázek nejde zrušit, jen přenést na jiný.
* `optionValueId` (UUID nebo `null`; nepovinný): Jen `product_media`: navázat obrázek na hodnotu volby (například Barva = Červená), takže se ukáže u všech variant s tou hodnotou. `null` vazbu zruší a obrázek je společný pro celý produkt. Hodnoty vrací `shopzi_list_content` s resource=product\_media.
* `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_storefront_layout` [#shopzi-save-storefront-layout]

Změní hlavičku a patičku obchodu: menu (včetně barvy a odznaku odkazu a megamenu sestaveného ze stromu kategorií), tlačítko v liště, oznamovací pruh, barvy, ikony, logo (tmavé nebo světlé logo značky, vlastní obrázek z Médií, v patičce i žádné), sloupce odkazů, sociální sítě a newsletter. Seznamy se nahrazují celé, ostatní pole se slučují s uloženým nastavením; současný stav i s ID vrací `shopzi_get_settings` se sekcí `storefront_layout`.

* **Oprávnění:** `content:write`, u klíče „Obsah: stránky, blog a média (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í:**

  > Seznamy se NAHRAZUJÍ CELÉ: odkazy v menu, sloupce patičky i sociální sítě budou přesně ty vypsané níž a co v nich není, z obchodu zmizí. Ostatní pole (barvy, výška, ikony, oznamovací pruh, newsletter) se slučují s tím, co je uložené, takže se nedotčených hodnot nic netýká. Vrátit to jde jedním krokem přes „vrátit zpět“.

## `shopzi_save_storefront_layout`: parametry `header` a `footer` [#shopzi-save-storefront-layout-parametry-header-a-footer]

* `header` (objekt; nepovinný): Změny hlavičky obchodu.
* `header.design` (objekt; nepovinný)
* `header.design.bgColor` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Barva ve tvaru #RRGGBB.
* `header.design.textColor` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Barva ve tvaru #RRGGBB.
* `header.design.titleColor` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Barva nadpisů sloupců v megamenu.
* `header.design.sticky` (`true` nebo `false`; nepovinný): Hlavička zůstane při rolování nahoře.
* `header.design.bordered` (`true` nebo `false`; nepovinný): Linka pod hlavičkou.
* `header.design.transparent` (`true` nebo `false`; nepovinný): Hlavička splyne se stránkou a text nese jen stín. Vhodné nad hero fotkou.
* `header.design.height` (jedna z hodnot `compact`, `standard` a `tall`; nepovinný)
* `header.design.logoPosition` (jedna z hodnot `left` a `center`; nepovinný): left = logo vlevo a menu vedle něj; center = menu vlevo a logo na střed.
* `header.design.width` (jedna z hodnot `boxed` a `full`; nepovinný): boxed = obsah lišty do 1200 px; full = až k okraji stránky.
* `header.logo` (objekt; nepovinný): Logo v hlavičce.
* `header.logo.source` (jedna z hodnot `brand-dark`, `brand-light` a `custom`; povinný): `brand-*` = logo z Vzhled → Logo, `custom` = vlastní obrázek.
* `header.logo.customUrl` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Jen u `custom`: `/media/…` z knihovny médií obchodu (`shopzi_list_content` resource=media nebo `shopzi_generate_media`). Vynechaná = beze změny, `null` ji odebere.
* `header.cartIcon` (jedna z hodnot `ShoppingCart`, `ShoppingBag` a `ShoppingBasket`; nepovinný): Ikona košíku.
* `header.userIcon` (jedna z hodnot `User`, `UserRound`, `CircleUser` a `Contact`; nepovinný): Ikona účtu.
* `header.search` (objekt; nepovinný): Vyhledávací pole v hlavičce.
* `header.search.enabled` (`true` nebo `false`; povinný)
* `header.announcement` (objekt; nepovinný): Oznamovací pruh nad hlavičkou.
* `header.announcement.enabled` (`true` nebo `false`; nepovinný): Zapnout pruh nad hlavičkou.
* `header.announcement.text` (text, nejvýš 300 znaků; nepovinný): Text pruhu. Prázdný text pruh vypne.
* `header.announcement.href` (text, nejvýš 500 znaků; nepovinný): Kam pruh odkazuje.
* `header.announcement.ctaLabel` (text, nejvýš 80 znaků; nepovinný)
* `header.announcement.countdownTo` (text, nejvýš 40 znaků; nepovinný): Datum a čas konce v ISO tvaru. Po uplynutí pruh sám zmizí.
* `header.announcement.dismissible` (`true` nebo `false`; nepovinný): Návštěvník smí pruh zavřít.
* `header.announcement.tone` (jedna z hodnot `brand`, `dark` a `soft`; nepovinný)
* `header.cta` (objekt; nepovinný): Tlačítko vpravo v liště (např. „Stát se dodavatelem“ → /kontakt). Na mobilu je v menu.
* `header.cta.enabled` (`true` nebo `false`; nepovinný)
* `header.cta.label` (text, nejvýš 40 znaků; nepovinný)
* `header.cta.href` (text, nejvýš 500 znaků; nepovinný)
* `header.links` (pole objektů, nejvýš 7 položek; nepovinný): Celé menu hlavičky v cílovém pořadí (nejvýš 7 položek). Co v seznamu chybí, se z menu odstraní, takže pošlete i odkazy, které mají zůstat.
* `header.links[].id` (text; nepovinný): ID existujícího odkazu. U odkazu typu `mega` je povinné.
* `header.links[].label` (text, 1 až 80 znaků; povinný)
* `header.links[].type` (jedna z hodnot `link`, `dropdown` a `mega`; nepovinný): link = prostý odkaz (`target`); dropdown = rozbalovací seznam (`items`); mega = velké menu s kategoriemi. `mega` s `id` uloženého megamenu ho ZACHOVÁ (obsah se převezme); `mega` s `fromCategories: true` sestaví NOVÉ megamenu z aktuálního stromu kategorií. Výchozí link.
* `header.links[].target` (text, nejvýš 500 znaků; nepovinný): `link`: adresa odkazu. `dropdown` / `mega`: volitelná adresa, kam vede klik na samotný popisek.
* `header.links[].color` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Vlastní barva odkazu (#RRGGBB), např. barva značky partnera.
* `header.links[].badge` (`true` nebo `false`; nepovinný): Zobrazit odkaz jako odznak vyplněný barvou `color` (text se dopočítá pro čitelnost).
* `header.links[].items` (pole objektů, nejvýš 20 položek; nepovinný): Jen `dropdown`: položky rozbalovacího seznamu.
* `header.links[].items[].id` (text; nepovinný)
* `header.links[].items[].label` (text, 1 až 80 znaků; povinný)
* `header.links[].items[].target` (text, nejvýš 500 znaků; povinný): Adresa, kam odkaz vede (např. /produkty).
* `header.links[].fromCategories` (`true` nebo `false`; nepovinný): Jen `mega`: sestavit megamenu z aktuálního stromu kategorií obchodu (nejvýše 4 sloupce, hlavní kategorie s podkategoriemi). Přepíše obsah megamenu s tímto `id`, pokud existuje.
* `footer` (objekt; nepovinný): Změny patičky obchodu.
* `footer.logo` (objekt; nepovinný): Logo v patičce.
* `footer.logo.source` (jedna z hodnot `brand-dark`, `brand-light`, `custom` a `none`; povinný): `none` = jen název obchodu.
* `footer.logo.customUrl` (text, nejvýš 1000 znaků nebo `null`; nepovinný): Jen u `custom`: `/media/…` z knihovny médií obchodu (`shopzi_list_content` resource=media nebo `shopzi_generate_media`). Vynechaná = beze změny, `null` ji odebere.
* `footer.design` (objekt; nepovinný)
* `footer.design.bgColor` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Barva ve tvaru #RRGGBB.
* `footer.design.textColor` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Barva ve tvaru #RRGGBB.
* `footer.design.titleColor` (text se vzorem `^#[0-9A-Fa-f]{6}$`; nepovinný): Barva nadpisů sloupců.
* `footer.description` (text, nejvýš 600 znaků; nepovinný): Odstavec o obchodu v patičce.
* `footer.columns` (pole objektů, nejvýš 6 položek; nepovinný): Celé sloupce odkazů v cílovém pořadí. Co v seznamu chybí, se odstraní.
* `footer.columns[].id` (text; nepovinný)
* `footer.columns[].title` (text, nejvýš 80 znaků; povinný): Nadpis sloupce.
* `footer.columns[].links` (pole objektů, nejvýš 20 položek; povinný)
* `footer.columns[].links[].id` (text; nepovinný)
* `footer.columns[].links[].label` (text, 1 až 80 znaků; povinný)
* `footer.columns[].links[].target` (text, nejvýš 500 znaků; povinný)
* `footer.social` (pole objektů, nejvýš 10 položek; nepovinný): Celý seznam sociálních sítí. Co v seznamu chybí, se odstraní.
* `footer.social[].id` (text; nepovinný)
* `footer.social[].platform` (jedna z hodnot `facebook`, `instagram`, `x`, `youtube`, `linkedin`, `tiktok` a `pinterest`; povinný)
* `footer.social[].url` (text, nejvýš 500 znaků; povinný): Úplná adresa profilu.
* `footer.showContact` (`true` nebo `false`; nepovinný): Zobrazit kontaktní údaje obchodu.
* `footer.newsletter` (objekt; nepovinný): Pruh s přihlášením k newsletteru nad sloupci patičky.
* `footer.newsletter.enabled` (`true` nebo `false`; nepovinný)
* `footer.newsletter.headline` (text, nejvýš 120 znaků; nepovinný)
* `footer.newsletter.text` (text, nejvýš 300 znaků; nepovinný)
* `footer.newsletter.buttonLabel` (text, nejvýš 60 znaků; nepovinný)
* `footer.newsletter.placeholder` (text, nejvýš 80 znaků; nepovinný)
* `footer.newsletter.consentText` (text, nejvýš 400 znaků; nepovinný)

## `shopzi_save_storefront_layout`: parametry `idempotencyKey` [#shopzi-save-storefront-layout-parametry-idempotencykey]

* `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_generate_media` [#shopzi-generate-media]

Vygeneruje obrázek nebo krátké video a uloží ho do knihovny Médií. Video se renderuje na pozadí, takže se volání vrátí hned se stavem `queued`.

* **Oprávnění:** `content:write`, u klíče „Obsah: stránky, blog a média (zápis)“.
* **Druh:** zápis, který jen přidává.
* **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:** strhne kredity obchodu.
* **Deník změn:** výsledek nese `change_id: null`. Vždy null: vygenerovaný soubor se deníkem změn vrátit nedá, protože kredity už jsou utracené. Smazat ho jde v administraci v sekci Média.
* **Věta o důsledku, kterou člověk uvidí v potvrzení:**

  > Generování UTRATÍ kredity obchodu a vracejí se jen při technickém selhání, ne když se výsledek nelíbí. Hotový soubor zůstane v Médiích a jde ho tam smazat.

## `shopzi_generate_media`: parametry [#shopzi-generate-media-parametry]

* `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ýž.
* `kind` (jedna z hodnot `image` a `video`; povinný): `image` pro obrázek, `video` pro krátký klip se zvukem.
* `prompt` (text, 3 až 1500 znaků; povinný): Detailní popis scény anglicky. U videa popište i pohyb kamery, náladu a zvuk. Značku obchodu doplní server sám, žádnou si nevymýšlejte.
* `productId` (text; nepovinný): ID produktu z `shopzi_search_products`, když má být kreativa o konkrétním zboží. Server sám dohledá jeho skutečnou fotku a model z ní vyjde, takže na výsledku bude TO zboží, ne podobné. Adresu obrázku sem neposílejte, nepřijímá se.
* `shape` (jedna z hodnot `square`, `portrait` a `landscape`; nepovinný): Jen obrázek: `portrait` na stories a reels, `landscape` na web a bannery, `square` do feedu. Výchozí `square`.
* `transparent` (`true` nebo `false`; nepovinný): Jen obrázek: PNG s průhledným pozadím (loga, samolepky, překryvy). Stojí několikanásobek běžného obrázku, protože to umí jen dražší model.
* `count` (celé číslo od 1 do 4; nepovinný): Jen obrázek: kolik variant vyrobit (1 až 4). Každá se účtuje zvlášť, takže víc než jednu dělejte jen na výslovné přání. Výchozí 1.
* `durationSeconds` (jedna z hodnot `4`, `6` a `8`; nepovinný): Jen video: povolené jsou POUZE 4, 6 nebo 8 sekund a cena roste s délkou. Výchozí 4.
* `aspectRatio` (jedna z hodnot `9:16` a `16:9`; nepovinný): Jen video: `9:16` na stories, reels a TikTok, `16:9` na web a YouTube. Čtverec model neumí. Výchozí `9:16`.
* `altText` (text, nejvýš 300 znaků; nepovinný): Jen obrázek: český alternativní text do knihovny médií (přístupnost a SEO). Popište, co na obrázku je, ne jak vznikl.
