{
  "serverInfo": {
    "name": "zarla",
    "version": "1.0.0"
  },
  "authentication": {
    "required": true,
    "schemes": [
      "oauth2"
    ]
  },
  "tools": [
    {
      "name": "list_sites",
      "description": "List all websites in your Zarla account. Returns site IDs, names, status (draft/live), and preview URLs. An account with no websites yet returns an empty list plus a message naming create_site as the next step.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get_site",
      "description": "Get the full details of a website, including business info, design tokens, pages, and all block content. Use this to understand what's currently on the site before making edits.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site ID (from create_site or list_sites)"
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get_page",
      "description": "Get the full content of a specific page, including all its blocks. Use page slugs from get_site.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site ID"
          },
          "page_slug": {
            "type": "string",
            "description": "Page slug (e.g., \"/\", \"/about\", \"/services/paint-correction\")"
          }
        },
        "required": [
          "site_id",
          "page_slug"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "list_site_photos",
      "description": "List images the user has previously uploaded to their photo library for this site (the 'My Photos' library at /photos in Zarla — real photos of their work, NOT stock images). ALWAYS check here first when the user asks you to use 'their photos', 'photos of my work', 'pictures from my last job', or similar. Returns the newest 100 image URLs, which you can pass directly to update_block (image / images), update_business_info, or update_seo. If this returns 0 photos, the user hasn't uploaded any yet — at that point, ask if they'd like to upload some via request_image_upload, or fall through to stock imagery.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site this photo library belongs to"
          },
          "status": {
            "description": "Filter by status. Default \"all\". The photo library has no drafts — \"draft\" always returns 0 photos; use \"all\" (or omit).",
            "type": "string",
            "enum": [
              "all",
              "published",
              "draft"
            ]
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "list_industries",
      "description": "List all supported industries grouped by family. Use this to find the right industry identifier for create_site.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "list_block_types",
      "description": "List all available block types with their variants and content fields. Use this to understand what blocks can be added and what content each accepts.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "list_designs",
      "description": "Browse Zarla's marketplace designs (1,200+) — the looks a site can be moved onto with switch_design. Pass site_id to put designs made for that site's industry first (for_your_business: true). Narrow by look (bold, modern, professional, elegant, friendly, warm, luxury, playful), by industry (slug or name) or with a search query; paged 20 at a time (max 50) via offset. Each design carries the schema_key that switch_design takes. For colors/fonts only, use update_design instead — no design change needed.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "description": "Order designs for this site's industry first",
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "query": {
            "description": "Search industry names, keywords and design names",
            "type": "string",
            "maxLength": 80
          },
          "industry": {
            "description": "Industry slug or name (see list_industries)",
            "type": "string",
            "maxLength": 80
          },
          "look": {
            "description": "Filter by look",
            "type": "string",
            "enum": [
              "bold",
              "modern",
              "professional",
              "elegant",
              "friendly",
              "warm",
              "luxury",
              "playful"
            ]
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50
          },
          "offset": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_business_info",
      "description": "Update the business information that appears across the site — name, phone, email, address, hours, services list, etc. Changes propagate to all pages that reference this info.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "name": {
            "description": "Business name",
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "tagline": {
            "description": "Business tagline / slogan",
            "type": "string",
            "maxLength": 300
          },
          "phone": {
            "type": "string",
            "maxLength": 50
          },
          "email": {
            "type": "string",
            "format": "email",
            "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
          },
          "address": {
            "type": "string",
            "maxLength": 500
          },
          "opening_hours": {
            "description": "Structured weekly hours — one entry per day",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "enum": [
                    "monday",
                    "tuesday",
                    "wednesday",
                    "thursday",
                    "friday",
                    "saturday",
                    "sunday"
                  ],
                  "description": "Day of week — lowercase full name: \"monday\", \"tuesday\", … \"sunday\""
                },
                "closed": {
                  "description": "True if closed all day (omit slots)",
                  "type": "boolean"
                },
                "slots": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "open": {
                        "type": "string",
                        "description": "Opening time, 24h \"HH:MM\" (e.g. \"09:00\")"
                      },
                      "close": {
                        "type": "string",
                        "description": "Closing time, 24h \"HH:MM\" (e.g. \"17:00\")"
                      }
                    },
                    "required": [
                      "open",
                      "close"
                    ]
                  }
                }
              },
              "required": [
                "day"
              ]
            }
          },
          "services": {
            "description": "List of services offered",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "license_number": {
            "type": "string",
            "maxLength": 100
          },
          "years_in_business": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_block",
      "description": "Update the content of a specific block on a page. Blocks are the building sections — hero, features, testimonials, FAQ, etc. You can update text, images, items, CTAs, and layout variant.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_slug": {
            "type": "string",
            "description": "Page slug"
          },
          "block_id": {
            "type": "string",
            "description": "Block ID from get_site or get_page (e.g. block-0, block-1)"
          },
          "headline": {
            "type": "string"
          },
          "subheadline": {
            "type": "string"
          },
          "variant": {
            "description": "Layout variant — see list_block_types",
            "type": "string"
          },
          "items": {
            "description": "Repeating items (features, testimonials, FAQ, etc.)",
            "type": "array",
            "items": {
              "type": "object",
              "propertyNames": {
                "type": "string"
              },
              "additionalProperties": {}
            }
          },
          "cta": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string"
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "label",
              "url"
            ]
          },
          "image": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string"
              },
              "alt": {
                "type": "string"
              }
            },
            "required": [
              "url",
              "alt"
            ]
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "alt": {
                  "type": "string"
                }
              },
              "required": [
                "url",
                "alt"
              ]
            }
          },
          "background": {
            "description": "Section background — \"default\" (page colour) | \"alt\" (soft) | \"primary\" (brand colour) | \"dark\" (dark surface). Null clears it. Choosing a preset also clears any custom colour (a custom colour would otherwise win).",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "default",
                  "alt",
                  "primary",
                  "dark"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "background_color": {
            "description": "Custom section colour as a 6-character hex; overrides the preset. Null clears it. Text adapts automatically.",
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "content": {
            "description": "Full content replacement — overrides all above fields",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          }
        },
        "required": [
          "site_id",
          "page_slug",
          "block_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "add_block",
      "description": "Add a new content block to a page. Available types: hero, features, testimonials, faq, gallery, stats, cta, contact, split, process, serviceselector, pricing, video, logobar, numberedfeatures, map, menu, richtext. If content is omitted, sensible defaults are generated.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_slug": {
            "type": "string"
          },
          "block_type": {
            "type": "string",
            "description": "Block type (see list_block_types)"
          },
          "variant": {
            "description": "Layout variant. If omitted, a sensible default is chosen.",
            "type": "string"
          },
          "position": {
            "description": "\"start\", \"end\" (default), or \"after:block-N\"",
            "type": "string"
          },
          "content": {
            "description": "Block content. If omitted, defaults are used.",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          }
        },
        "required": [
          "site_id",
          "page_slug",
          "block_type"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "remove_block",
      "description": "Remove a content block from a page.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_slug": {
            "type": "string"
          },
          "block_id": {
            "type": "string",
            "description": "Block ID to remove"
          }
        },
        "required": [
          "site_id",
          "page_slug",
          "block_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "reorder_blocks",
      "description": "Reorder blocks on a page. Provide the complete list of block IDs in the desired order.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_slug": {
            "type": "string"
          },
          "block_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ordered list of ALL block IDs for this page"
          }
        },
        "required": [
          "site_id",
          "page_slug",
          "block_ids"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_design",
      "description": "Update the visual design — colors, fonts, mood, density. Changes only the tokens you pass and touches nothing else (a contrast pass keeps text readable against a new scheme). To move the whole site onto a different marketplace design — layouts, palette and typography, with the site's content kept — use switch_design instead; this tool never changes layouts. The response includes a \"preview_url\" for the updated draft — share THAT link with the user, do not construct your own.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "mood": {
            "type": "string",
            "enum": [
              "bold",
              "elegant",
              "warm",
              "professional",
              "playful",
              "modern",
              "friendly",
              "luxury"
            ]
          },
          "primary_color": {
            "description": "Hex color (e.g. \"#1a1a2e\")",
            "type": "string"
          },
          "accent_color": {
            "description": "Hex color",
            "type": "string"
          },
          "background_color": {
            "description": "Hex color",
            "type": "string"
          },
          "heading_font": {
            "description": "Google Fonts name",
            "type": "string"
          },
          "body_font": {
            "description": "Google Fonts name",
            "type": "string"
          },
          "density": {
            "type": "string",
            "enum": [
              "compact",
              "comfortable",
              "spacious"
            ]
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "switch_design",
      "description": "Move the site onto a marketplace design from list_designs. FULL REDESIGN: the design's colors, fonts, section layouts and section order come across on the home page AND every internal page, while the site's business details, words, photos, services, forms and pages stay. Sections the design has that the site has no content for are left out (nothing is invented); the site's own sections the design has no spot for are kept. A backup of the current site is saved automatically FIRST — the response reports it under \"backup\" (restorable via Site Backups in the Zarla editor); if backup.created is false with skipped_reason \"snapshot_failed\", warn the user the switch proceeded WITHOUT a backup. The response includes a \"preview_url\" for the updated draft — share THAT link, do not construct your own. Nothing changes on a live site until publish_site. For colors or fonts only, use update_design.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "schema_key": {
            "type": "string",
            "pattern": "^[a-z0-9-]{1,80}$",
            "description": "The design's schema_key from list_designs"
          }
        },
        "required": [
          "site_id",
          "schema_key"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_seo",
      "description": "Update the SEO metadata for a page — title tag, meta description, OG image, and target search term (the keyword the page should rank for).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_slug": {
            "type": "string"
          },
          "title": {
            "description": "Page title tag (under 60 chars ideal)",
            "type": "string",
            "maxLength": 70
          },
          "description": {
            "description": "Meta description (150-160 chars ideal)",
            "type": "string",
            "maxLength": 170
          },
          "og_image": {
            "description": "Open Graph image URL",
            "type": "string"
          },
          "target_search_term": {
            "description": "The search phrase this page targets, e.g. \"emergency plumber austin tx\" — shown as Target Search Term in Get Found. Give each page its OWN term; two pages targeting the same phrase compete against each other in Google. Pass \"\" to clear.",
            "type": "string",
            "maxLength": 100
          }
        },
        "required": [
          "site_id",
          "page_slug"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_header",
      "description": "Update the site header — navigation, CTA button, layout variant, announcement bar, logo size, background colour. The header appears on every page.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "variant": {
            "type": "string",
            "enum": [
              "classic",
              "centered",
              "centered-no-cta",
              "stacked",
              "minimal",
              "cta-bar",
              "mega",
              "landing",
              "boutique"
            ]
          },
          "nav_items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "children": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string"
                      },
                      "url": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "label",
                      "url"
                    ]
                  }
                }
              },
              "required": [
                "label",
                "url"
              ]
            }
          },
          "cta": {
            "description": "Header CTA button (e.g. \"Get a Free Quote\")",
            "type": "object",
            "properties": {
              "label": {
                "type": "string"
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "label",
              "url"
            ]
          },
          "show_phone": {
            "description": "Show phone number in header",
            "type": "boolean"
          },
          "logo_size": {
            "description": "Header logo size — \"small\" | \"medium\" (default) | \"large\". Sizes the logo image or business-name text on every layout, desktop and phones. \"Bigger\" = one step up from the current size (read_site → header.logo_size).",
            "type": "string",
            "enum": [
              "small",
              "medium",
              "large"
            ]
          },
          "background": {
            "description": "Header background (ZAR-2060) — \"default\" (the page colour) | \"alt\" (soft) | \"primary\" (the brand colour) | \"dark\" (dark surface). Null clears it back to the page colour. Choosing a preset also clears any custom colour (a custom colour would otherwise win). Links, the phone, the logo text and the phone menu adapt automatically. A see-through / transparent header is not supported.",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "default",
                  "alt",
                  "primary",
                  "dark"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "background_color": {
            "description": "Custom header colour as a 6-character hex (e.g. \"#0f172a\"); overrides the preset. Null clears it. Text adapts automatically (read_site → header.background / header.background_color).",
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "announcement_items": {
            "description": "Announcement strip shown above the header on every page, e.g. [\"Free shipping over $80\", \"Ships Australia-wide\"]. Null or empty clears it.",
            "anyOf": [
              {
                "maxItems": 5,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 80
                }
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_footer",
      "description": "Update the site footer — layout, social links, tagline, background colour.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "variant": {
            "type": "string",
            "enum": [
              "simple",
              "columns",
              "centered",
              "fat",
              "minimal"
            ]
          },
          "social_links": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "platform": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                }
              },
              "required": [
                "platform",
                "url"
              ]
            }
          },
          "tagline": {
            "description": "Footer tagline or description",
            "type": "string",
            "maxLength": 300
          },
          "background": {
            "description": "Footer background — \"default\" (the page colour) | \"alt\" (soft) | \"primary\" (the brand colour) | \"dark\" (dark surface). Null clears it (the classic brand-coloured footer). Choosing a preset also clears any custom colour.",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "default",
                  "alt",
                  "primary",
                  "dark"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "background_color": {
            "description": "Custom footer colour as a 6-character hex; overrides the preset. Null clears it. Text adapts automatically.",
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "add_page",
      "description": "Add a new page to the site with default content blocks. Supported types: \"service\", \"location\", \"about\", \"contact\", \"custom\", \"landing\", \"blog\".",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_type": {
            "type": "string",
            "enum": [
              "service",
              "location",
              "about",
              "contact",
              "custom",
              "landing",
              "blog"
            ]
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Page title (e.g. \"Ceramic Coating\", \"Parramatta\")"
          },
          "description": {
            "description": "Brief description to guide content generation",
            "type": "string",
            "maxLength": 500
          },
          "slug": {
            "description": "URL slug. Auto-generated from title if omitted.",
            "type": "string"
          }
        },
        "required": [
          "site_id",
          "page_type",
          "title"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "remove_page",
      "description": "Remove a page from the site. Cannot remove the home page. A backup of the current site is saved automatically before every removal (restorable via Site Backups in the Zarla editor) — the response reports it under \"backup\"; if backup.created is false with skipped_reason \"snapshot_failed\", warn the user the removal is NOT backed up.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "page_slug": {
            "type": "string",
            "description": "Page slug to remove"
          }
        },
        "required": [
          "site_id",
          "page_slug"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "create_site",
      "description": "Generate a website from business information. Builds the site's home page (roughly 10 sections) and creates the site in draft state with a shareable preview URL; the services and service areas you pass are saved to the site's business info. Additional pages — about, services, contact, and dedicated per-service or per-location pages — are NOT generated by this call today; add them afterwards with add_page. Takes 15-30 seconds. Use list_industries to find valid industry identifiers. Cost: the initial build is free — it spends no AI credits (later AI work such as add_page does) — but every site counts toward the account's site limit (5 sites on the Free plan, 100 on paid plans); at the limit the call fails with a plan-limit message instead of generating.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "business_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The business name"
          },
          "industry": {
            "type": "string",
            "minLength": 1,
            "description": "Industry identifier (e.g. \"car-detailing\", \"electrician\", \"restaurant\")"
          },
          "location": {
            "type": "object",
            "properties": {
              "city": {
                "type": "string",
                "minLength": 1
              },
              "state": {
                "type": "string",
                "minLength": 1
              },
              "country": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "city",
              "state",
              "country"
            ],
            "description": "Business location"
          },
          "description": {
            "description": "Brief business description — the more detail, the better the content",
            "type": "string",
            "maxLength": 2000
          },
          "services": {
            "description": "List of services offered",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "service_areas": {
            "description": "Suburbs/neighborhoods served (for local SEO pages)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "phone": {
            "type": "string",
            "maxLength": 50
          },
          "email": {
            "type": "string"
          },
          "address": {
            "type": "string",
            "maxLength": 500
          },
          "opening_hours": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "enum": [
                    "monday",
                    "tuesday",
                    "wednesday",
                    "thursday",
                    "friday",
                    "saturday",
                    "sunday"
                  ],
                  "description": "Day of week — lowercase full name: \"monday\", \"tuesday\", … \"sunday\""
                },
                "open": {
                  "type": "string",
                  "description": "Opening time, 24h \"HH:MM\" (e.g. \"09:00\")"
                },
                "close": {
                  "type": "string",
                  "description": "Closing time, 24h \"HH:MM\" (e.g. \"17:00\")"
                }
              },
              "required": [
                "day",
                "open",
                "close"
              ]
            }
          },
          "years_in_business": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "license_number": {
            "type": "string",
            "maxLength": 100
          },
          "language": {
            "description": "Site language (default: \"en\"). Supports 27 languages.",
            "type": "string",
            "maxLength": 10
          }
        },
        "required": [
          "business_name",
          "industry",
          "location"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "publish_site",
      "description": "Publish the site to make it live on the web. Generates final HTML, optimizes for production, and deploys to CDN. Takes 5-15 seconds. This replaces whatever is currently live at the site's URL with the current draft — the previous live version is not kept. Publishing is a paid feature: if this site's plan doesn't allow it yet, the call returns code UPGRADE_REQUIRED with an upgrade_url — share that link with the user so they can upgrade (don't retry the call).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site ID to publish"
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "show_site_preview",
      "description": "Show the user's website inside the chat as a live preview panel (on AI apps that support interactive panels; elsewhere it returns a preview link to share). Renders the CURRENT DRAFT — call it when the user asks to see their site, or once after finishing a batch of edits so they can see the result; every edit tool already returns a fresh preview_url, so prefer ONE preview call after several edits over one per edit. Refreshing re-renders the draft preview (the same staging refresh every edit performs). The response includes the page list and publish readiness: when publishing needs a paid plan, upgrade_url carries the checkout link — share it if the user wants to go live (don't retry publish_site).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site to preview"
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "set_logo",
      "description": "Make an image the site's logo (header, footer AND favicon — the favicon pair is generated automatically, transparency is detected, and the logo's dominant brand colors come back as suggested_colors). image_url must be one of THIS site's own images: something the user uploaded via request_image_upload + finalize_image_upload, or an existing photo from list_site_photos — any other URL is rejected. A solid-background (non-transparent) image works but looks best as a transparent PNG; the response says which was detected. suggested_colors are ONLY suggestions — offer them to the user (\"want the site to match your logo?\") and apply via update_design if they say yes; never apply unprompted. The response includes a fresh preview_url — share that link.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "image_url": {
            "type": "string",
            "maxLength": 2048,
            "format": "uri",
            "description": "URL of an image in THIS site's photo library (from finalize_image_upload or list_site_photos)"
          }
        },
        "required": [
          "site_id",
          "image_url"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "remove_logo",
      "description": "Remove the uploaded logo and go back to the text logotype (the business name in the site's heading font — every site's default, a legitimate finished look). The favicon falls back to the automatic monogram. The user's photo-library image is left untouched (this call deletes nothing), so a JPEG/PNG/WebP logo can be set again later with set_logo. Already on the text logotype? The call reports that and changes nothing.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "request_image_upload",
      "description": "Upload an image attached to the conversation — logos, photos, banners, anything the user has shown you. Returns a one-time URL the caller's runtime PUTs the raw bytes to (handles any size up to 50MB). Workflow: (1) call this tool, (2) PUT raw image bytes to the returned upload_url with Content-Type header (raw binary, NOT base64), (3) call finalize_image_upload with the returned asset_id. The URL expires in 5 minutes — issue this immediately before your PUT, not at the start of a long reasoning chain. JPEG/PNG/WebP only; no SVG. If the user is asking about photos they've already uploaded to their Zarla photo library, use list_site_photos first instead.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site this image belongs to"
          },
          "mime": {
            "type": "string",
            "enum": [
              "image/jpeg",
              "image/png",
              "image/webp"
            ],
            "description": "Image MIME type. JPEG/PNG/WebP only — SVG is not supported."
          },
          "byte_size": {
            "description": "Optional byte size for upfront cap check (max 50MB).",
            "type": "integer",
            "minimum": 1,
            "maximum": 52428800
          },
          "alt": {
            "description": "Accessibility alt text. Stored when finalize_image_upload returns.",
            "type": "string",
            "maxLength": 300
          }
        },
        "required": [
          "site_id",
          "mime"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "finalize_image_upload",
      "description": "Confirm and validate an image that was PUT to a request_image_upload URL. Call this AFTER your PUT to upload_url completes. Server downloads the staged bytes, validates magic bytes (rejects non-JPEG/PNG/WebP), enforces 8000×8000 dim cap, strips EXIF, promotes to the public bucket, and saves the image to the site's photo library (it will appear in My Photos and list_site_photos). Pass `folder` to also file it into a media-library folder — the way to make the photo show up in a gallery that's bound to that folder (editor updates immediately; the live site picks it up at the next publish_site). Returns {url, media_item_id, folder, mime, bytes, width, height} — pass the URL to update_block, update_business_info, or update_seo. Single-use: each asset_id can be finalized exactly once.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "asset_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The asset_id returned by request_image_upload"
          },
          "alt": {
            "description": "Accessibility alt text — overrides what was passed to request_image_upload.",
            "type": "string",
            "maxLength": 300
          },
          "folder": {
            "description": "Media-library folder NAME to file the photo into (e.g. \"Projects\"). Matched case-insensitively against the site's existing folders; created if it doesn't exist. Use the folder a gallery is bound to when the user wants the photo to appear in that gallery.",
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "asset_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "request_product_file_upload",
      "description": "Upload a digital-product file (PDF, video, ZIP, audio, etc.) for a product the user is creating. Workflow: (1) call this with the original file_name, (2) PUT raw bytes to the returned upload_url with Content-Type header, (3) call finalize_product_file_upload — its response includes file_path / file_name / file_size that you pass to create_product (type: 'download'). Up to 100MB. Executable file types (.exe, .bat, .sh, .msi, .app, .dmg, .pkg, .deb, .rpm, .ps1, .scr, .cmd, .com) are rejected at request time. URL expires in 5 minutes — issue immediately before your PUT.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site this product file belongs to"
          },
          "file_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Original filename (preserved through to the buyer's download email — choose well)."
          },
          "mime": {
            "description": "Optional MIME type. Defaults to application/octet-stream. Pass a real MIME (e.g. application/pdf, video/mp4, application/zip) when you know it.",
            "type": "string",
            "maxLength": 120
          },
          "byte_size": {
            "description": "Optional byte size for upfront cap check (max 100MB).",
            "type": "integer",
            "minimum": 1,
            "maximum": 104857600
          }
        },
        "required": [
          "site_id",
          "file_name"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "finalize_product_file_upload",
      "description": "Confirm a product file that was PUT to a request_product_file_upload URL. Call this AFTER your PUT completes. Returns {file_path, file_name, file_size, mime} — pass these directly into create_product when type is 'download'. Single-use: each asset_id can be finalized exactly once.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "asset_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The asset_id returned by request_product_file_upload"
          }
        },
        "required": [
          "asset_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get_payments_status",
      "description": "Check whether the site is ready to accept payments via Stripe Connect. Returns {connected, status, country, currency, onboarding_needed, setup_url, message}. ALWAYS call this BEFORE create_product / update_product to know if the merchant can actually receive sales — when onboarding_needed is true, surface the setup_url to the user instead of staging products that buyers can't pay for.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The site to check"
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "list_products",
      "description": "List products on a site. Returns paginated results with prices in both cents and dollars. Use this before suggesting product edits. Note: a product block with no content.productIds automatically shows every active product — you only need product IDs when curating a featured subset.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "description": "Filter by status. Default: all.",
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "type": {
            "description": "Filter by type. Default: all.",
            "type": "string",
            "enum": [
              "download",
              "shipped"
            ]
          },
          "search": {
            "description": "Substring match on product name (case-insensitive)",
            "type": "string",
            "maxLength": 200
          },
          "page": {
            "description": "1-indexed page number. Default: 1.",
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "per_page": {
            "description": "Page size. Default: 20, max: 100.",
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get_product",
      "description": "Fetch a single product by its product_id (the UUID returned in list_products responses, NOT the product name).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "required": [
          "product_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get_product_settings",
      "description": "Get the site's product settings — currency (e.g. 'usd', 'aud'), default shipping fee, download limit, download expiry, notification email, order prefix. Currency derives from the merchant's country and applies to every product on the site.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "list_orders",
      "description": "List orders on a site. Returns paginated results with full line items. Pass status='pending' to include pre-checkout abandoned carts (otherwise excluded). Use this to answer 'did anyone buy?', 'who's bought X?', or 'show me last week's sales' questions.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "description": "Filter by order status. Omit for all (excluding pending).",
            "type": "string",
            "enum": [
              "pending",
              "new",
              "fulfilled",
              "partial",
              "cancelled",
              "refunded"
            ]
          },
          "search": {
            "description": "Substring match on buyer name, buyer email, or order_number.",
            "type": "string",
            "maxLength": 200
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "per_page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "site_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get_order",
      "description": "Fetch a single order by its order_id (the UUID, NOT the human-readable order_number). Returns the order plus its line items.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          }
        },
        "required": [
          "order_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "create_product",
      "description": "Create a new product on a site. For digital downloads (type: 'download'), file_path / file_name / file_size are REQUIRED — get them by running request_product_file_upload → PUT → finalize_product_file_upload first. For shipped products, set shipping_type: 'flat_rate' (with shipping_fee in cents) or 'pickup'. Single-dimension variants supported via variant_label + variants — each option may carry its OWN price (e.g. sizes at different prices: [{option: '2ml', price: 625}, {option: '100ml', price: 25000}]); options without a price sell at the base price. Prices are in the smallest currency unit (cents for USD/AUD/EUR, paise for INR, etc.) — $40 → 4000. Optional merchandising fields: brand, badge, image_urls (gallery, first = cover). Returns the created product plus a warnings[] array — when `PAYMENTS_NOT_SET_UP` appears, surface the setup_url to the user; the product still saves but buyers can't pay until setup finishes. New products appear automatically in any existing product block — do NOT set content.productIds unless the user wants a hand-picked featured subset (a pinned list freezes the block: later products won't show until re-pinned). If the site has no product block yet, add one via add_block (block_type: 'product') and leave content.productIds unset.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "site_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "download",
              "shipped"
            ]
          },
          "price": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991,
            "description": "Price in the smallest currency unit (cents). $40 → 4000."
          },
          "compare_at_price": {
            "description": "Original/MSRP price for \"was $X, now $Y\" display. Same unit as `price`.",
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "description": "Cover image URL (use request_image_upload + finalize_image_upload to get one). Prefer image_urls for multiple images.",
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          },
          "image_urls": {
            "description": "Product image gallery, up to 8 URLs — the FIRST is the cover. Get URLs via request_image_upload + finalize_image_upload.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 8,
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "brand": {
            "description": "Brand line shown above the product name, e.g. \"Louis Vuitton\".",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ]
          },
          "badge": {
            "description": "Single badge chip shown on the product image, e.g. \"Designer\" or \"Best Seller\".",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 30
              },
              {
                "type": "null"
              }
            ]
          },
          "variant_label": {
            "description": "Single-dimension variant label, e.g. \"Size\" or \"Colour\". Required if variants is set.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ]
          },
          "variants": {
            "description": "Variant options with optional per-option prices, e.g. [{\"option\": \"2ml\", \"price\": 625}, {\"option\": \"100ml\", \"price\": 25000}]. Required if variant_label is set.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 20,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "option": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "price": {
                      "description": "Optional per-option price in the smallest currency unit ($12.50 → 1250). Omit/null = sells at the product's base price.",
                      "anyOf": [
                        {
                          "type": "integer",
                          "exclusiveMinimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "option"
                  ]
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "variant_options": {
            "description": "DEPRECATED — use variants. Plain option names; accepted for backwards compatibility and treated as variants without per-option prices.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 20,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "specs": {
            "description": "Product-details table rows shown on the /products/<slug> page, e.g. [{\"label\": \"Top notes\", \"value\": \"Raspberry · Bergamot\"}]. Up to 12.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 12,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "value": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 300
                    }
                  },
                  "required": [
                    "label",
                    "value"
                  ]
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "file_path": {
            "description": "REQUIRED for download products. Get from finalize_product_file_upload.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ]
          },
          "file_name": {
            "description": "REQUIRED for download products. Original filename (shown in the buyer's download email).",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "file_size": {
            "description": "REQUIRED for download products. File size in bytes.",
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "shipping_type": {
            "description": "For shipped products: 'flat_rate' (charges shipping_fee at checkout) or 'pickup' (free, customer collects).",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "flat_rate",
                  "pickup"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "shipping_fee": {
            "description": "Flat shipping fee in cents (only when shipping_type='flat_rate').",
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "sort_order": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "site_id",
          "name",
          "type",
          "price"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "update_product",
      "description": "Update an existing product. All fields are optional — only the ones you pass get updated. Changes affect a LIVE shop: checkout always charges the currently stored price, so price and status changes reach buyers immediately, while the published storefront keeps showing the previously published details until the next publish_site — republish after changing prices so what buyers see matches what they are charged. Status changes (active ↔ inactive) hide/show the product on published sites without deleting order history. To remove a product from sale, set status: 'inactive' (don't try to delete).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "The product to update (from list_products / get_product / create_product)."
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "download",
              "shipped"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "price": {
            "description": "Price in the smallest currency unit (cents).",
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "compare_at_price": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          },
          "image_urls": {
            "description": "Gallery, up to 8 URLs — first is the cover.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 8,
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "brand": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ]
          },
          "badge": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 30
              },
              {
                "type": "null"
              }
            ]
          },
          "variant_label": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ]
          },
          "variants": {
            "description": "Variant options with optional per-option prices in cents (null = base price).",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 20,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "option": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    },
                    "price": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "exclusiveMinimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "option"
                  ]
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "variant_options": {
            "description": "DEPRECATED — use variants.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 20,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "specs": {
            "description": "Product-details table rows for the detail page (≤12); null clears.",
            "anyOf": [
              {
                "minItems": 1,
                "maxItems": 12,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "value": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 300
                    }
                  },
                  "required": [
                    "label",
                    "value"
                  ]
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "file_path": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ]
          },
          "file_name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "file_size": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "shipping_type": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "flat_rate",
                  "pickup"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "shipping_fee": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "sort_order": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "product_id"
        ],
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    }
  ],
  "resources": [],
  "prompts": []
}