{"server":"vendor-store-manager","version":"0.5.0","connector_url":"https://mcp.vendorecommerce.com/s/<store-id>/mcp","totals":{"tools":104,"read":42,"change":47,"replace":15},"groups":[{"id":"sales","title":"Sales and orders","blurb":"Ask how the store is doing and look into any order.","tools":[{"name":"get_sales_overview","summary":"KPI snapshot for a period: orders, revenue, fulfilment and customers.","description":"KPI snapshot for a period: orders, revenue, fulfilment and customers. The first thing to call for \"how did the store do\".","kind":"read","needs_approval":false,"inputs":["period"]},{"name":"compare_periods","summary":"Period-vs-period KPI comparison: current, previous and the delta.","description":"Period-vs-period KPI comparison: current, previous and the delta. Use it for \"better or worse than last month\".","kind":"read","needs_approval":false,"inputs":["period"]},{"name":"get_top","summary":"Top-N ranking for one dimension, by the requested metric.","description":"Top-N ranking for one dimension, by the requested metric. Use it to pick products for a homepage block, or to answer \"what sells\".","kind":"read","needs_approval":false,"inputs":["dimension","metric","limit","period"]},{"name":"list_orders","summary":"Admin order list with filters.","description":"Admin order list with filters. Use it to triage: unpaid, stuck, or a date window.","kind":"read","needs_approval":false,"inputs":["status","created_at_from","created_at_to","page","per_page"]},{"name":"get_order","summary":"One order in full.","description":"One order in full. The payload carries `available_actions` — every admin action with whether it is available, a reason when locked, and exactly one flagged `primary` (the recommended next step). Read that instead of reasoning about the lifecycle yourself.","kind":"read","needs_approval":false,"inputs":["id"]}]},{"id":"catalogue","title":"Catalogue","blurb":"Find, create and correct products, brands, categories and attributes.","tools":[{"name":"search_products","summary":"Search the catalog.","description":"Search the catalog. Filters are POSITIVE only — there is no \"missing brand\" or \"no image\" filter, so to find gaps you must page through and inspect.","kind":"read","needs_approval":false,"inputs":["keyword","sku","brand_ids","category_ids","status","visibility","min_price","max_price","order_by","order","page","per_page"]},{"name":"get_product","summary":"One product or variation in full, by id, slug or SKU.","description":"One product or variation in full, by id, slug or SKU.","kind":"read","needs_approval":false,"inputs":["type","value"]},{"name":"audit_catalog","summary":"Sweep the catalogue for the gaps that keep products from selling: no brand, no category, no image, no description, no price, no SEO title.","description":"Sweep the catalogue for the gaps that keep products from selling: no brand, no category, no image, no description, no price, no SEO title. The API has no \"missing X\" filter, so this pages through and inspects — keep the sample modest on a large catalogue.","kind":"read","needs_approval":false,"inputs":["max_products","status"]},{"name":"create_product","summary":"Create a product with its variations, prices and opening stock.","description":"Create a product with its variations, prices and opening stock. One variation is still required for a simple product — that is where the SKU, the price and the stock live. Set import.create_missing_brand or create_missing_attribute_options to let the backend fill gaps rather than failing.","kind":"change","needs_approval":true,"inputs":["title","slug","status","visibility","brand_id","brand_title","categories","description","short_description","seo","is_featured","related_product_ids","upsell_product_ids","crosssell_product_ids","thumbnail_media_id","media_gallery","variations","create_missing_brand","create_missing_attribute_options"]},{"name":"add_variation","summary":"Add a variation to an existing product — another size, colour or pack.","description":"Add a variation to an existing product — another size, colour or pack. Needs its own SKU, price and stock.","kind":"change","needs_approval":true,"inputs":["product_id","sku","title","regular_price","sale_price","availability","attributes","stock"]},{"name":"fix_product","summary":"Correct fields on one product — title, description, brand, categories, status, visibility, SEO.","description":"Correct fields on one product — title, description, brand, categories, status, visibility, SEO. Shows a before/after diff before writing.","kind":"change","needs_approval":true,"inputs":["id","changes"]},{"name":"set_product_relations","summary":"Set related, upsell and cross-sell products.","description":"Set related, upsell and cross-sell products. Each list replaces the previous one, so send the full set you want.","kind":"change","needs_approval":true,"inputs":["product_id","related_product_ids","upsell_product_ids","crosssell_product_ids"]},{"name":"create_categories","summary":"Create categories, optionally several at once as a tree.","description":"Create categories, optionally several at once as a tree. Build the structure before importing products, or every product lands uncategorised and has to be fixed afterwards.","kind":"change","needs_approval":true,"inputs":["categories"]},{"name":"create_brand","summary":"Create a brand.","description":"Create a brand. Products reference it by id, so create brands before importing a catalogue that mentions them.","kind":"change","needs_approval":true,"inputs":["title","slug","description","link","visibility"]},{"name":"create_attribute","summary":"Create an attribute and its options — size, colour, material.","description":"Create an attribute and its options — size, colour, material. Attributes do double duty: they are the axes variations differ on and the filters shoppers use, so is_filterable is worth a thought.","kind":"change","needs_approval":true,"inputs":["title","slug","type","is_filterable","split_listing","options"]},{"name":"create_smart_collection","summary":"Create a smart archive — a collection defined by a saved query rather than a fixed list, so it stays current as the catalogue changes.","description":"Create a smart archive — a collection defined by a saved query rather than a fixed list, so it stays current as the catalogue changes. Manual include and exclude lists override the rules.","kind":"change","needs_approval":true,"inputs":["name","title","slug","description","rules","include_product_ids","exclude_product_ids","visibility"]},{"name":"reindex_catalog","summary":"Rebuild the search index.","description":"Rebuild the search index. Needed after bulk catalog changes or a new locale, otherwise search keeps serving the old data.","kind":"change","needs_approval":true,"inputs":["target","locale"]}]},{"id":"bulk","title":"Bulk changes","blurb":"Change many rows with one plan and one approval.","tools":[{"name":"bulk_update","summary":"Update up to 40 products, variations, categories or brands in ONE call, each row with its own changes — descriptions, titles, SEO, status, brand, categories, prices, SKUs.","description":"Update up to 40 products, variations, categories or brands in ONE call, each row with its own changes — descriptions, titles, SEO, status, brand, categories, prices, SKUs. Use this instead of calling fix_product / set_seo row by row: the plan covers every row and the owner approves once. For the SAME value on many rows chosen by a filter, bulk_fix_products is cheaper. A job larger than 40 rows is several calls of this tool.","kind":"replace","needs_approval":true,"inputs":["entity","items","reindex"]},{"name":"bulk_create_products","summary":"Create up to 25 products in ONE call, each with its variations, prices and opening stock — the same fields as create_product.","description":"Create up to 25 products in ONE call, each with its variations, prices and opening stock — the same fields as create_product. Use it when loading a catalogue: the plan lists every product and the owner approves once. Brands, categories and attributes must exist first (or pass create_missing_brand / create_missing_attribute_options per product).","kind":"change","needs_approval":true,"inputs":["products","reindex"]},{"name":"get_bulk_change_options","summary":"The authoritative list of what a bulk change can set and what it can select on, straight from the backend.","description":"The authoritative list of what a bulk change can set and what it can select on, straight from the backend. Call this before bulk_fix_products: the filter keys are not guessable, and the negative ones (without_brand, without_category, without_media, without_description) are what turn an audit finding into one operation.","kind":"read","needs_approval":false,"inputs":[]},{"name":"bulk_fix_products","summary":"Change one field across many products, selected by filter.","description":"Change one field across many products, selected by filter. The backend dry-runs this for real, so the plan is an exact count rather than an estimate.","kind":"replace","needs_approval":true,"inputs":["field","verb","value","filters"]}]},{"id":"stock","title":"Stock","blurb":"See what is running out. Stock itself is changed in the dashboard or by your ERP.","tools":[{"name":"get_stock_summary","summary":"Inventory KPIs: counter totals, alert counts and a 30-day movements trend.","description":"Inventory KPIs: counter totals, alert counts and a 30-day movements trend.","kind":"read","needs_approval":false,"inputs":[]},{"name":"list_stock_levels","summary":"Per-variation stock levels.","description":"Per-variation stock levels. Pass status=low to answer \"what is running out\".","kind":"read","needs_approval":false,"inputs":["status","search","page","per_page"]}]},{"id":"pages","title":"Pages and homepage","blurb":"Build and publish the homepage, landing pages, forms and legal pages.","tools":[{"name":"list_pages","summary":"CMS pages.","description":"CMS pages. Filter tag=front-page to find the homepage (it is also the row with is_default=true).","kind":"read","needs_approval":false,"inputs":["tag","locale","status","is_default","per_page"]},{"name":"get_page_document","summary":"One page with its page-builder document.","description":"One page with its page-builder document. `template: \"designed\"` plus a pageBuilder object with a `content` array means a Puck (v2) page; a bare array is a legacy v1 document and must not be edited in place.","kind":"read","needs_approval":false,"inputs":["id"]},{"name":"describe_page_blocks","summary":"The page-builder block catalog: every block type, its props, and the document shape.","description":"The page-builder block catalog: every block type, its props, and the document shape. Read this BEFORE authoring or editing any page document — the props are not guessable and a wrong key is silently dropped. Pass `type` to get one block in full: every field with its kind, its allowed option values, the fields of its list items, and its defaults.","kind":"read","needs_approval":false,"inputs":["group","type"]},{"name":"list_homepage_templates","summary":"The 27 ready-made homepage starter templates (9 industries × classic / catalog / products).","description":"The 27 ready-made homepage starter templates (9 industries × classic / catalog / products). Fetch one to see its full document before proposing it.","kind":"read","needs_approval":false,"inputs":[]},{"name":"create_homepage_from_template","summary":"Replace the storefront homepage with one of the 27 starter templates, published immediately.","description":"Replace the storefront homepage with one of the 27 starter templates, published immediately. Destructive: it overwrites the current homepage document.","kind":"replace","needs_approval":true,"inputs":["template_key"]},{"name":"write_page_document","summary":"Replace a page's builder document.","description":"Replace a page’s builder document. Use for \"rebuild my homepage\" once you know what you want: author the content array from describe_page_blocks. Fetch the current document first with get_page_document so you do not discard sections by accident.","kind":"replace","needs_approval":true,"inputs":["page_id","document","publish"]},{"name":"create_page","summary":"Create a CMS page — an About, a landing page, a contact page.","description":"Create a CMS page — an About, a landing page, a contact page. For a contact page, create the form first with create_contact_form and put its id in a Contact Form block.","kind":"change","needs_approval":true,"inputs":["title","permalink","document","tag","locale","publish"]},{"name":"publish_page","summary":"Publish or unpublish a page, and purge the storefront so the change is visible.","description":"Publish or unpublish a page, and purge the storefront so the change is visible.","kind":"change","needs_approval":true,"inputs":["page_id","status"]},{"name":"create_contact_form","summary":"Create a ready-to-use contact form (name, email, phone, subject, message) and return its id for a Contact Form block.","description":"Create a ready-to-use contact form (name, email, phone, subject, message) and return its id for a Contact Form block. Pass fields to override the default set.","kind":"change","needs_approval":true,"inputs":["title","fields","locale"]},{"name":"list_legal_templates","summary":"The ready-made legal policy templates — privacy, terms, returns, shipping, cookies, GDPR.","description":"The ready-made legal policy templates — privacy, terms, returns, shipping, cookies, GDPR. Each is markdown carrying {{tokens}} that the storefront fills from store settings at render time.","kind":"read","needs_approval":false,"inputs":[]},{"name":"create_legal_pages","summary":"Publish legal pages from the platform templates.","description":"Publish legal pages from the platform templates. The {{tokens}} in them resolve from your company and policy settings, so fill those first with configure_company_identity and configure_policies — otherwise the pages publish with holes in them.","kind":"change","needs_approval":true,"inputs":["policies","locale","publish"]}]},{"id":"blocks","title":"Custom blocks, header and footer","blurb":"Author your own page sections, product card, header and footer.","tools":[{"name":"list_block_primitives","summary":"Everything a custom page-builder block may use: the Liquid objects, filters and tags the storefront supports, the setting types, data sources and limits.","description":"Everything a custom page-builder block may use: the Liquid objects, filters and tags the storefront supports, the setting types, data sources and limits. Read this BEFORE writing a block template — anything not listed here will not render.","kind":"read","needs_approval":false,"inputs":[]},{"name":"validate_block","summary":"Check a block locally with the same Liquid engine the storefront uses: parses it, renders it with sample settings, and reports errors and warnings.","description":"Check a block locally with the same Liquid engine the storefront uses: parses it, renders it with sample settings, and reports errors and warnings. Writes nothing. Run it before save_block_version and fix every error.","kind":"read","needs_approval":false,"inputs":["template","css","snippets","schema","data_sources"]},{"name":"list_custom_blocks","summary":"The store's custom page-builder blocks with their version summaries (draft / published / retired).","description":"The store’s custom page-builder blocks with their version summaries (draft / published / retired).","kind":"read","needs_approval":false,"inputs":["s","status"]},{"name":"get_custom_block","summary":"One custom block.","description":"One custom block. Pass version_id to also get that version’s template, snippets and schema — read it before proposing a change to it.","kind":"read","needs_approval":false,"inputs":["id","version_id"]},{"name":"create_custom_block","summary":"Register a new custom block (its identity only — no code yet).","description":"Register a new custom block (its identity only — no code yet). The key is permanent. Follow with save_block_version.","kind":"change","needs_approval":true,"inputs":["key","label","description","group","enabled_on"]},{"name":"save_block_version","summary":"Save a block's code as a DRAFT version: creates a new draft when given `version`, or updates an existing draft when given `version_id`.","description":"Save a block’s code as a DRAFT version: creates a new draft when given `version`, or updates an existing draft when given `version_id`. The source is checked locally first and refused if it has errors. A draft is not visible anywhere until published.","kind":"change","needs_approval":true,"inputs":["block_id","version","version_id","template","css","snippets","schema","data_sources","notes"]},{"name":"publish_block_version","summary":"Publish a draft version.","description":"Publish a draft version. It becomes immutable and appears in the editor palette. It still shows nowhere on the storefront until it is placed on a page with write_page_document.","kind":"change","needs_approval":true,"inputs":["block_id","version_id"]},{"name":"retire_block_version","summary":"Retire a published version: it leaves the editor palette but keeps rendering on pages already pinned to it.","description":"Retire a published version: it leaves the editor palette but keeps rendering on pages already pinned to it.","kind":"replace","needs_approval":true,"inputs":["block_id","version_id"]},{"name":"get_block_theme_css","summary":"The store's shared stylesheet for custom blocks: brand type, colour variables and utility classes that every custom block can use.","description":"The store’s shared stylesheet for custom blocks: brand type, colour variables and utility classes that every custom block can use. Read it before writing a block so you reuse what is there instead of repeating it.","kind":"read","needs_approval":false,"inputs":[]},{"name":"write_block_theme_css","summary":"Replace the store's shared stylesheet for custom blocks.","description":"Replace the store’s shared stylesheet for custom blocks. Put here what several blocks share (CSS variables for brand colours, type classes, buttons) so each block’s own stylesheet stays small. It applies to every custom block on the store, and to nothing else.","kind":"replace","needs_approval":true,"inputs":["css"]},{"name":"get_product_card","summary":"Which product card the store uses wherever products are listed: the built-in one, or a custom card block (with the settings it was given).","description":"Which product card the store uses wherever products are listed: the built-in one, or a custom card block (with the settings it was given).","kind":"read","needs_approval":false,"inputs":[]},{"name":"set_product_card","summary":"Use a custom block as the product card EVERYWHERE products are listed (shop, categories, search, product carousels), or go back to the built-in card.","description":"Use a custom block as the product card EVERYWHERE products are listed (shop, categories, search, product carousels), or go back to the built-in card. The block must be published and created with \"card\" in enabled_on. Its template reads the product as `product` (see list_block_primitives → product_card).","kind":"replace","needs_approval":true,"inputs":["card","settings"]},{"name":"get_site_region","summary":"The store's custom header or footer, if it has one: its status and page-builder document.","description":"The store’s custom header or footer, if it has one: its status and page-builder document. \"built-in\" means the store uses the storefront’s own header or footer.","kind":"read","needs_approval":false,"inputs":["region"]},{"name":"write_site_region","summary":"Replace the store's header or footer with a page-builder document, on EVERY page.","description":"Replace the store’s header or footer with a page-builder document, on EVERY page. It may contain ONLY custom blocks created with that region in enabled_on, at the top level: no Row and no built-in blocks. A store has ONE saved header and ONE saved footer (no separate draft beside a live one): when the current one is live, writing it changes what visitors see now unless publish is false, and publish: false takes the live one down (visitors see the built-in one) until it is published again. Read the current one with get_site_region first.","kind":"replace","needs_approval":true,"inputs":["region","document","publish"]},{"name":"reset_site_region","summary":"Remove a custom header or footer so the storefront shows its built-in one again.","description":"Remove a custom header or footer so the storefront shows its built-in one again.","kind":"replace","needs_approval":true,"inputs":["region"]},{"name":"export_blocks","summary":"Export the store's custom blocks as one portable JSON bundle: the latest published version of each block, plus (optionally) the shared block stylesheet and the custom header and footer.","description":"Export the store’s custom blocks as one portable JSON bundle: the latest published version of each block, plus (optionally) the shared block stylesheet and the custom header and footer. The bundle carries no ids, so import_blocks can load it into any store. Writes nothing.","kind":"read","needs_approval":false,"inputs":["keys","include_theme_css","include_regions"]},{"name":"import_blocks","summary":"Load a bundle made by export_blocks into this store: registers the blocks it does not have, adds the versions it is missing and publishes them.","description":"Load a bundle made by export_blocks into this store: registers the blocks it does not have, adds the versions it is missing and publishes them. A version the store already has is never overwritten; when the code differs, the incoming block gets the next free version. Every block is checked with the storefront’s Liquid engine first, and nothing is written if any of them fails.","kind":"replace","needs_approval":true,"inputs":["bundle","namespace","theme_css","regions"]}]},{"id":"shipping","title":"Shipping","blurb":"Where the store delivers, how, and what it costs.","tools":[{"name":"get_shipping_setup","summary":"The store's whole shipping setup in one call: zones (where it delivers), delivery methods, and rates (what each costs and when), with the problems that stop shoppers from getting a price…","description":"The store’s whole shipping setup in one call: zones (where it delivers), delivery methods, and rates (what each costs and when), with the problems that stop shoppers from getting a price — a zone with no rate, a rate that can never be reached. Read this before any shipping change.","kind":"read","needs_approval":false,"inputs":[]},{"name":"set_up_shipping","summary":"Set up shipping in one step, for a store that has none or is adding countries: a zone per country, a \"Standard delivery\" method, a flat price per order, and optionally free delivery…","description":"Set up shipping in one step, for a store that has none or is adding countries: a zone per country, a \"Standard delivery\" method, a flat price per order, and optionally free delivery above a cart total. Safe to run again — what already exists is kept. Use the single-piece tools afterwards for anything more specific.","kind":"change","needs_approval":true,"inputs":["countries","flat_price","free_over"]},{"name":"create_shipping_zone","summary":"Create a delivery zone — an area the store delivers to, by country and optionally by city or postcode.","description":"Create a delivery zone — an area the store delivers to, by country and optionally by city or postcode. A zone offers nothing until it has a rate: follow with create_shipping_rate.","kind":"change","needs_approval":true,"inputs":["title","countries","cities","postcodes","postcode_mode","priority","is_active"]},{"name":"create_shipping_method","summary":"Create a delivery method — what the shopper chooses at checkout: courier delivery, pickup in store.","description":"Create a delivery method — what the shopper chooses at checkout: courier delivery, pickup in store. A method is only offered where it has a rate that fits the cart.","kind":"change","needs_approval":true,"inputs":["title","type","checkout_label","checkout_description","is_default","carrier_id"]},{"name":"set_zone_methods","summary":"Choose which delivery methods a zone offers, and in what order.","description":"Choose which delivery methods a zone offers, and in what order. The list REPLACES the zone’s current one. A zone with no methods chosen falls back to the store’s default methods.","kind":"replace","needs_approval":true,"inputs":["zone_id","method_ids"]},{"name":"create_shipping_rate","summary":"Create a rate — what a delivery method costs, and for which carts.","description":"Create a rate — what a delivery method costs, and for which carts. Leave zone_id out for a rate that applies everywhere. Order matters: rates on the same method and zone are tried lowest priority number first and the first that fits wins, so \"free above 3000\" needs a LOWER number than the flat rate it sits beside.","kind":"change","needs_approval":true,"inputs":["shipping_method_id","shipping_zone_id","title","calculation_type","condition_type","price","priority","min_cart_total","max_cart_total","min_weight","max_weight","min_items","max_items","min_quantity","max_quantity","free_shipping_threshold","per_item_amount","per_weight_amount","step_weight","per_volume_amount","step_volume","currency"]},{"name":"update_shipping","summary":"Change a zone, a delivery method or a rate: a price, a limit, a priority, the countries of a zone, or switch it off with is_active false.","description":"Change a zone, a delivery method or a rate: a price, a limit, a priority, the countries of a zone, or switch it off with is_active false. Nothing is deleted through the assistant — switching off is how a zone, method or rate is retired.","kind":"change","needs_approval":true,"inputs":["entity","id","changes"]}]},{"id":"media","title":"Images and files","blurb":"Bring product photos, logos and banners into the store, from the web or from a computer, and find the ones already there.","tools":[{"name":"list_media","summary":"Images and files already in the store's media library, newest first: id, address, size and alt text.","description":"Images and files already in the store’s media library, newest first: id, address, size and alt text. Use it to find the id of a photo or logo before placing it on a product, a page or a setting.","kind":"read","needs_approval":false,"inputs":["search","type","limit","page"]},{"name":"upload_media","summary":"Bring up to 10 images or PDFs into the store's media library from public web addresses — product photos, a logo, a banner.","description":"Bring up to 10 images or PDFs into the store’s media library from public web addresses — product photos, a logo, a banner. Each is fetched and stored by the store, which returns its id and its new address. Use the id on products (thumbnail_media_id, media_gallery) and the new address in settings and page blocks; never keep pointing at the original address. Only upload what the owner has the right to use.","kind":"change","needs_approval":true,"inputs":["items","purpose"]},{"name":"start_file_upload","summary":"Upload files that are on a computer, not on the web: product photos in a folder, a logo on the desktop.","description":"Upload files that are on a computer, not on the web: product photos in a folder, a logo on the desktop. For up to 10 files this returns a one-time upload address and the exact command that sends each file there. Run the commands if you have a shell; otherwise give them to the owner to run. Then call finish_file_upload with the tickets. The addresses stop working after 15 minutes. Without a shell and without an owner willing to run a command, the file has to be uploaded in the dashboard.","kind":"change","needs_approval":true,"inputs":["files","purpose"]},{"name":"finish_file_upload","summary":"Register files sent with start_file_upload: the store checks each one arrived, adds it to the media library and returns its id and address.","description":"Register files sent with start_file_upload: the store checks each one arrived, adds it to the media library and returns its id and address. Call it once the upload commands have run. A ticket whose file did not arrive is reported, and the others still register.","kind":"change","needs_approval":false,"inputs":["files"]}]},{"id":"content","title":"Blog and custom content","blurb":"Post types, taxonomies and entries: a blog, a podcast, recipes.","tools":[{"name":"create_content_type","summary":"Register a custom post type — blog, podcast, recipes, case studies.","description":"Register a custom post type — blog, podcast, recipes, case studies. The key is immutable once created: it is baked into entry URLs, cache keys and SDK filters.","kind":"change","needs_approval":true,"inputs":["key","label","label_plural","archive_base","description","editor","is_public"]},{"name":"create_content_taxonomy","summary":"Add a classification axis to one or more post types — category, tag, guest, topic.","description":"Add a classification axis to one or more post types — category, tag, guest, topic. The storefront ANDs across axes and ORs within one.","kind":"change","needs_approval":true,"inputs":["key","label","label_plural","type_keys","is_hierarchical","is_multiple","is_public"]},{"name":"create_content_terms","summary":"Add terms to a taxonomy.","description":"Add terms to a taxonomy. A term keeps one identity across locales and translates its fields, so do not create one per language.","kind":"change","needs_approval":true,"inputs":["taxonomy_id","terms"]},{"name":"write_post","summary":"Write an entry of a custom post type — a blog article, a podcast episode.","description":"Write an entry of a custom post type — a blog article, a podcast episode. Entries are per-locale rows, so a translation is a separate entry joined by translation_group_id.","kind":"change","needs_approval":true,"inputs":["type","title","slug","excerpt","content","locale","term_ids","featured_media_id","seo","is_featured","publish"]}]},{"id":"i18n","title":"Translations and SEO","blurb":"Translate what is missing and set search and social metadata.","tools":[{"name":"find_missing_translations","summary":"Which rows of a model have no translation for a locale.","description":"Which rows of a model have no translation for a locale. Start every translation job here — it is the difference between translating what is missing and re-translating everything.","kind":"read","needs_approval":false,"inputs":["model","locale","limit"]},{"name":"write_translations","summary":"Store translations for one (model, locale).","description":"Store translations for one (model, locale). You do the translating — this only persists it. Keep brand names, SKUs, sizes and units untranslated.","kind":"change","needs_approval":true,"inputs":["model","locale","items"]},{"name":"set_seo","summary":"Set the SEO / social overlay on a product, category or brand.","description":"Set the SEO / social overlay on a product, category or brand. The whole object is replaced, so include every key you want kept.","kind":"change","needs_approval":true,"inputs":["entity","id","seo"]}]},{"id":"setup","title":"Store setup","blurb":"Everything a store needs before it opens.","tools":[{"name":"get_feature_map","summary":"The store's effective feature map.","description":"The store's effective feature map. Call this first in a session: it says which capabilities the plan unlocks, so you never offer something the store cannot do.","kind":"read","needs_approval":false,"inputs":[]},{"name":"get_store_readiness","summary":"Onboarding readiness: 15 steps across essentials / ecommerce / catalog / go-live, each satisfied or not.","description":"Onboarding readiness: 15 steps across essentials / ecommerce / catalog / go-live, each satisfied or not. Use it to answer \"is my store ready to launch\" and \"what is still missing\".","kind":"read","needs_approval":false,"inputs":[]},{"name":"get_store_config","summary":"The store's whole configuration in one call: every reserved setting with its label, current value, type and allowed options, grouped by area.","description":"The store’s whole configuration in one call: every reserved setting with its label, current value, type and allowed options, grouped by area. Read this before configuring anything — it is the difference between setting a value and guessing a key.","kind":"read","needs_approval":false,"inputs":["area"]},{"name":"get_settings_schema","summary":"The reserved-settings schema: which keys exist, their types and defaults.","description":"The reserved-settings schema: which keys exist, their types and defaults. Read it before writing any setting — a typo in a key silently creates a setting nothing reads.","kind":"read","needs_approval":false,"inputs":[]},{"name":"configure_essentials","summary":"Currency, language and timezone — the first three readiness steps, and what blocks creating products and going live.","description":"Currency, language and timezone — the first three readiness steps, and what blocks creating products and going live. Nothing else in the store behaves correctly until these are set.","kind":"change","needs_approval":true,"inputs":["currency","currency_symbol_position","currency_space","decimal_separator","thousands_separator","default_language","enabled_languages","timezone","store_country"]},{"name":"configure_company_identity","summary":"Who the store legally is: name, registration and VAT numbers, address, contact email.","description":"Who the store legally is: name, registration and VAT numbers, address, contact email. These fill the store-identity readiness step and are substituted into the legal policy templates, so getting them right once fixes the footer, invoices and policy pages together.","kind":"change","needs_approval":true,"inputs":["site_title","display_name","legal_name","company_id","vat","address","zip","city","country","website","contact_email"]},{"name":"configure_policies","summary":"Returns, delivery and data-protection details.","description":"Returns, delivery and data-protection details. These are the values the legal policy templates interpolate, so a shop with blank fields publishes policy pages with holes in them.","kind":"change","needs_approval":true,"inputs":["returns_address","returns_email","return_window_days","refund_period_days","order_processing_time","delivery_timeframe","delivery_partners","free_shipping_note","delivery_areas_note","data_controller_name","data_controller_email","data_controller_phone","data_controller_address","privacy_email","data_request_response_days","data_retention_period","supervisory_authority_name","supervisory_authority_url"]},{"name":"configure_order_handling","summary":"How orders are processed and who hears about them: fulfilment mode, the operational-flow preset, notification recipients, whether tax is charged.","description":"How orders are processed and who hears about them: fulfilment mode, the operational-flow preset, notification recipients, whether tax is charged. Call get_store_config first — store_operational_flow_preset is an enum and its options are the only legal values.","kind":"change","needs_approval":true,"inputs":["fulfillment_mode","operational_flow_preset","charges_tax","primary_notifications_recipient","secondary_notifications_recipient","notifications_bcc_recipient","express_checkout_enabled"]},{"name":"configure_commerce_mode","summary":"Whether the store sells or only displays: catalog mode, price visibility, and members-only sale pricing.","description":"Whether the store sells or only displays: catalog mode, price visibility, and members-only sale pricing. Catalog mode turns a shop into a brochure — say so plainly before switching it on.","kind":"change","needs_approval":true,"inputs":["catalog_mode","show_prices","sale_price_members_only","sale_price_members_note"]},{"name":"configure_appearance","summary":"Storefront layout and styling: boxed or full-width pages, max width, background, button styles, archive headers.","description":"Storefront layout and styling: boxed or full-width pages, max width, background, button styles, archive headers. Enum values come from get_store_config — invented ones are refused rather than silently stored.","kind":"change","needs_approval":true,"inputs":["page_layout_mode","page_max_width","page_custom_width","page_bg_color","page_box_bg_color","archive_header_enabled","archive_header_bg_color","archive_header_text_color","checkout_btn_style","add_to_cart_btn_style","product_card_btn_style"]},{"name":"configure_product_listing","summary":"Category and search page defaults: which filters appear, sidebar behaviour, grid density, brand bar.","description":"Category and search page defaults: which filters appear, sidebar behaviour, grid density, brand bar. This is the single biggest lever on how a catalogue feels to shop.","kind":"change","needs_approval":true,"inputs":["sidebar","sidebar_mode","tree_scope","filter_module","filter_price","filter_brands","filter_categories","filter_attributes","filter_stock","filter_collection","brand_bar","view","grid_columns","cols_base","cols_lg"]},{"name":"write_settings","summary":"Write store settings in one batch.","description":"Write store settings in one batch. Check get_settings_schema first: an unrecognised key is stored but read by nothing, which looks like a setting that does not work.","kind":"change","needs_approval":true,"inputs":["settings","public"]},{"name":"create_location","summary":"Create a store, warehouse or pickup point.","description":"Create a store, warehouse or pickup point. Stock lives per location, so a store needs at least one before inventory means anything — this is the default_location readiness gate.","kind":"change","needs_approval":true,"inputs":["title","code","type","city","country","zip","email","phone_number","is_default"]},{"name":"list_tax_classes","summary":"The tax classes a rate can attach to, and that products group under.","description":"The tax classes a rate can attach to, and that products group under.","kind":"read","needs_approval":false,"inputs":[]},{"name":"create_tax_rule","summary":"Create a tax rate and attach it to a tax class.","description":"Create a tax rate and attach it to a tax class. Products resolve their rate through the class, so the class matters more than the number — this is the tax readiness gate.","kind":"change","needs_approval":true,"inputs":["title","value","tax_class_id","applies_to_shipping"]},{"name":"enable_payment_method","summary":"Add a payment method.","description":"Add a payment method. Credentials go in `secrets` and are stored encrypted — they are never echoed back, and this tool never prints them. Without at least one method a store can reach checkout and go no further.","kind":"change","needs_approval":true,"inputs":["title","code","driver","provider","category","checkout_label","checkout_description","is_active","is_default","sort_order","environment","requires_redirect","supports_refund","fee_type","fee_amount","secrets"]},{"name":"get_menus","summary":"The store's navigation menus.","description":"The store’s navigation menus. Pass a location for one menu with its items; omit it to list them all.","kind":"read","needs_approval":false,"inputs":["location"]},{"name":"set_menu","summary":"Create a menu, or replace an existing one's items wholesale.","description":"Create a menu, or replace an existing one’s items wholesale. Items link to real entities by reference_type + reference_id rather than hardcoded URLs, so they survive a slug change. Replacing is destructive — the previous item tree is gone.","kind":"replace","needs_approval":true,"inputs":["location","title","items","locale"]},{"name":"rebuild_menu_from_categories","summary":"Regenerate a menu from the category tree.","description":"Regenerate a menu from the category tree. Fast way to a sane primary nav on a fresh store — and destructive, since it replaces whatever is in that menu.","kind":"replace","needs_approval":true,"inputs":["menu_id"]}]},{"id":"domains","title":"Domains and email sending","blurb":"Connect the shop domain and the domain emails are sent from.","tools":[{"name":"list_domains","summary":"The store's custom domains and their current status.","description":"The store’s custom domains and their current status.","kind":"read","needs_approval":false,"inputs":[]},{"name":"connect_domain","summary":"Provision a merchant domain on Cloudflare and return the DNS records to publish.","description":"Provision a merchant domain on Cloudflare and return the DNS records to publish. Nothing works until those records exist at the registrar, so hand them over and expect to wait.","kind":"change","needs_approval":true,"inputs":["domain"]},{"name":"verify_domain","summary":"Re-poll Cloudflare for a domain's hostname and SSL status.","description":"Re-poll Cloudflare for a domain’s hostname and SSL status. Use it after the DNS records have been published; it is a read, so call it as often as needed.","kind":"change","needs_approval":false,"inputs":["custom_domain_id"]},{"name":"list_sender_domains","summary":"Sending domains attached to this store and their verification state.","description":"Sending domains attached to this store and their verification state.","kind":"read","needs_approval":false,"inputs":[]},{"name":"connect_sender_domain","summary":"Attach a sending domain for transactional email and return its DKIM records.","description":"Attach a sending domain for transactional email and return its DKIM records. Until this verifies, order confirmations go out from the platform default rather than the store’s own domain.","kind":"change","needs_approval":true,"inputs":["domain"]},{"name":"verify_sender_domain","summary":"Re-sync a sender domain from AWS — DKIM status and records.","description":"Re-sync a sender domain from AWS — DKIM status and records. A read, safe to repeat.","kind":"change","needs_approval":false,"inputs":["sender_domain_id"]}]},{"id":"migrate","title":"Imports and migration","blurb":"Move a store from WooCommerce or the old Vendor platform, and keep it in sync until switch-over.","tools":[{"name":"get_v1_migration_contract","summary":"The contract for migrating a store from the old Vendor platform (v1): the order of work, every import step and its options, the field-by-field mapping, the settings mapping, the known…","description":"The contract for migrating a store from the old Vendor platform (v1): the order of work, every import step and its options, the field-by-field mapping, the settings mapping, the known faults and how to check for each, and the verification that ends a migration. Read the overview before the first import; read a section again before you act on it.","kind":"read","needs_approval":false,"inputs":["section"]},{"name":"read_v1_source","summary":"Read from the old (v1) store: how many taxes, brands, categories, attributes, products, coupons, customers and orders it holds, or one page of a v1 resource (its settings, shipping…","description":"Read from the old (v1) store: how many taxes, brands, categories, attributes, products, coupons, customers and orders it holds, or one page of a v1 resource (its settings, shipping methods, a sample of products). Read-only on both sides. The counts are what a finished migration is checked against.","kind":"read","needs_approval":false,"inputs":["base_url","token","vendor_tenant","resource","page","per_page"]},{"name":"find_v1_changes","summary":"What is new or changed in the old (v1) store since it was last imported, for one kind of record: which v1 rows are not here yet, which were edited in v1 after their import, which failed…","description":"What is new or changed in the old (v1) store since it was last imported, for one kind of record: which v1 rows are not here yet, which were edited in v1 after their import, which failed to import, and which source pages they sit on — so the next import can be limited to exactly those pages. Read-only on both sides. This is the first step of every re-sync; read get_v1_migration_contract section delta_sync for what to do with the answer.","kind":"read","needs_approval":false,"inputs":["base_url","token","vendor_tenant","entity","start_page","max_pages"]},{"name":"compare_v1_migration","summary":"After an import: the old store's counts next to the new store's, entity by entity, with the failed rows of the latest v1 run.","description":"After an import: the old store’s counts next to the new store’s, entity by entity, with the failed rows of the latest v1 run. This is the check that ends a migration — do not call it done on the run status alone.","kind":"read","needs_approval":false,"inputs":["base_url","token","vendor_tenant"]},{"name":"import_from_vendor_v1","summary":"Queue an import from an old Vendor (v1) store.","description":"Queue an import from an old Vendor (v1) store. Steps run in a fixed order: taxes, brands, categories, attributes, products, price_sync, stock_sync, coupons, customers, orders, pages, menus, seed_defaults. Long-running; it writes into the live catalogue, pages and menus. Read get_v1_migration_contract first — it says which steps to run together and what to check after each.","kind":"replace","needs_approval":true,"inputs":["base_url","token","vendor_tenant","only","skip","from_step","products","price_sync","stock_sync","categories","coupons","customers","orders"]},{"name":"import_from_woocommerce","summary":"Queue an import from a WooCommerce store: taxes, brands, categories, attributes, products.","description":"Queue an import from a WooCommerce store: taxes, brands, categories, attributes, products. Long-running and hard to undo — it writes into the live catalog.","kind":"replace","needs_approval":true,"inputs":["store_url","consumer_key","consumer_secret","type","only","skip"]},{"name":"get_import_run","summary":"Status and counters for one import run.","description":"Status and counters for one import run. Poll this after queueing an import instead of assuming it finished.","kind":"read","needs_approval":false,"inputs":["id"]},{"name":"list_import_runs","summary":"Import runs, newest first: migrations, CSV imports, bulk changes, customer-login runs.","description":"Import runs, newest first: migrations, CSV imports, bulk changes, customer-login runs. Use it to see whether something is still running before starting another, and to find the run a migration should be resumed from.","kind":"read","needs_approval":false,"inputs":["source","status","limit"]},{"name":"list_import_mappings","summary":"The row-level record of an import: which source record became which row here, and which failed and why.","description":"The row-level record of an import: which source record became which row here, and which failed and why. Filter by status \"failed\" after a migration — each failed row carries the source record and an _error.","kind":"read","needs_approval":false,"inputs":["source","entity_type","status","import_id","old_id","limit","page"]},{"name":"provision_customer_logins","summary":"Give imported customers a login.","description":"Give imported customers a login. After a migration, customers exist in the store but cannot sign in; this creates their accounts silently — no email is sent — and each customer sets a password the first time they try to log in. Safe to repeat: run it after every customer import or re-sync, and only the customers still without a login are touched.","kind":"change","needs_approval":true,"inputs":["imported_only","emails","limit"]}]}],"ungrouped":[]}