{"total":38,"tools":[{"name":"list_products_web","description":"Calls GET /api/products/webProducts on https://app.syspos.ae. Used by frontend-v2 getProducts. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"loc":{"type":"string","description":"Location id, csv, All, or 0. Default session location_id."},"page":{"type":"number","description":""},"limit":{"type":"number","description":">= 10000 returns all"},"k":{"type":"string","description":"Name LIKE"},"addon":{"type":"string","enum":["0","1"],"description":""},"category_id":{"type":"string","description":"Csv ids or All"},"cat":{"type":"string","description":"Csv category names. Used only if category_id absent/All"},"brand_id":{"type":"number","description":""},"label_id":{"type":"number","description":""},"channel_id":{"type":"number","description":""},"is_archive":{"type":"string","description":""}},"required":[]}},{"name":"list_products","description":"Calls GET /api/products on https://app.syspos.ae. Used by frontend-v2 getAddOnList, getSearchProduct. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"loc":{"type":"string","description":""},"addon":{"type":"string","description":"1 = add-ons"},"cat":{"type":"string","description":"Category name LIKE, or All"},"k":{"type":"string","description":""},"brand_id":{"type":"number","description":""},"page_limit":{"type":"number","description":""},"current_page":{"type":"number","description":""}},"required":[]}},{"name":"list_products_pos","description":"Calls GET /api/v2/products on https://app.syspos.ae. Used by web-pos products, productsAddon. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"k":{"type":"string","description":""},"addon":{"type":"string","description":""},"cat":{"type":"string","description":""},"page_limit":{"type":"number","description":""},"current_page":{"type":"number","description":""},"adm":{"type":"string","description":"Non-master: unlocks loc override"},"loc":{"type":"number","description":"Only used when adm is set (non-master)"}},"required":[]}},{"name":"get_product","description":"Calls GET /api/products/:id on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""},"is_archive":{"type":"string","description":""},"loc":{"type":"string","description":""}},"required":["id"]}},{"name":"search_products_for_assign","description":"Calls GET /api/products/search-assign on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"k":{"type":"string","description":"If shorter than 2 after trim, returns { data: [] }"},"loc":{"type":"string","description":""},"limit":{"type":"number","description":""}},"required":["k"]}},{"name":"get_products_from_ids","description":"Calls POST /api/products/products-from-ids on https://app.syspos.ae. Used by invoice-services. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"ids":{"type":"array","items":{"type":"number","description":""},"description":"Must be an array. Empty array → empty products list."},"customer_id":{"type":"number","description":"Required only when unauthenticated. Ignored when JWT present."}},"required":["ids"]}},{"name":"create_product","description":"Calls POST /api/products on https://app.syspos.ae. Used by frontend-v2 createProduct, createAddOn. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"name":{"type":"string","description":"400 if blank. Unique by name, or name+label when product_unique_formula includes label_id."},"description":{"type":"string","description":""},"localize_name":{"type":"string","description":"Sent by frontend create/update. Persist only if products.localize_name column exists (MySQL SET ?)."},"localize_description":{"type":"string","description":""},"actual_price":{"type":"number","description":""},"price":{"type":"number","description":"Ex-VAT / display price"},"combo_price":{"type":"number","description":""},"product_cost":{"type":"number","description":""},"vat":{"type":"number","description":""},"discount_pct":{"type":"number","description":"Forced to 0 if missing, < 0, or > 100"},"stock":{"type":"number","description":""},"preparation_time":{"type":"number","description":"Minutes. Frontend max 1440."},"category_id":{"type":"array","items":{"type":"string","description":""},"description":"Number, csv, or number[]. Arrays joined with comma."},"label_id":{"type":"array","items":{"type":"string","description":""},"description":"Arrays joined with comma. Frontend currently sends Number(label_id[0])."},"tax_id":{"type":"number","description":""},"tax_group_id":{"type":"string","description":"Stripped from product table insert. Not persisted by create/update handlers."},"type":{"type":"string","description":"Category name(s). If omitted, built from category_id names."},"categories":{"type":"array","items":{"type":"string","description":""},"description":"Copied into type if type empty, then deleted before insert."},"location_id":{"type":"array","items":{"type":"string","description":""},"description":"Number, csv, or number[]. Master insert forces location_id=null on the products row; locations live in location_prices."},"location_prices":{"type":"array","items":{"type":"object","properties":{"location_id":{"type":"number","description":""},"location_price":{"type":"number","description":"Preferred price. Falls back to location_actual_price."},"location_actual_price":{"type":"number","description":"Used when location_price is missing/NaN."},"is_available":{"type":"string","description":"Truthy → 1, else 0. Default 1."},"location_name":{"type":"string","description":"Returned on GET; ignored on write."}},"required":["location_id"],"description":"One location price row. Handler skips the row if location_id is missing."},"description":"If omitted and location_id set (non-master), one row per location is built from actual_price. Update: empty array + master deletes all location rows and archives the product."},"modifiers":{"type":"array","items":{"type":"object","properties":{"modifier_id":{"type":"number","description":""},"id":{"type":"number","description":"Existing product_modifiers.id"},"max_allowed":{"type":"number","description":""},"min_allowed":{"type":"number","description":""},"priority":{"type":"number","description":""},"selection_type":{"type":"string","description":""},"auto_selected_modifier_item_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"mandatory_modifier_item_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"unavailable_modifier_item_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"modifier_items_order":{"type":"array","items":{"type":"number","description":""},"description":"Display order of modifier item ids. Default: modifier_Items.priority."}},"required":["modifier_id"],"description":"Product–modifier link. Rows with modifier_id ≤ 0 or NaN are skipped."},"description":"API expects an array. Frontend form is an object keyed by modifier_id with isChecked; client converts before POST/PUT."},"replace_modifiers":{"type":"boolean","description":"true = replace all modifier links for the target locations."},"modifiers_by_location":{"type":"string","description":"Update only. Keys are location ids, values are modifier arrays. If non-empty, used instead of modifiers with replace_modifiers true per location."},"price_level":{"type":"array","items":{"type":"object","properties":{"channel_id":{"type":"number","description":"Also accepted as id"},"id":{"type":"number","description":"Alias for channel_id"},"channel_name":{"type":"string","description":""},"name":{"type":"string","description":"Alias for channel_name"},"channel_price":{"type":"number","description":""},"channel_vat":{"type":"number","description":""},"channel_actual_price":{"type":"number","description":""},"check":{"type":"boolean","description":"Frontend form flag. On update, object form keeps only entries with check=true."}},"required":["channel_id"],"description":"Channel/online price. channel_id or id required or the row is skipped."},"description":"Create path: saveChannelPrices(productId, price_level)."},"channel_price":{"type":"string","description":"Update path: saveChannelPrices uses req.body.channel_price (not price_level)."},"materials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Alias for material_id"},"material_id":{"type":"number","description":""},"qty":{"type":"number","description":""},"avg_price":{"type":"number","description":"Unit cost numerator"},"conversionrate":{"type":"number","description":""},"unit":{"type":"string","description":""},"wastage":{"type":"number","description":""},"name":{"type":"string","description":""}},"required":["material_id"],"description":"Recipe BOM line stored in product_materials."},"description":"Update deletes all existing product_materials then rewrites. Omit/empty = clear."},"recipes":{"type":"array","items":{"type":"object","properties":{"recipe_id":{"type":"number","description":"Also accepted as id on create payload from frontend"},"id":{"type":"number","description":"Alias for recipe_id (frontend)"},"portion_qty":{"type":"number","description":"Frontend sends portion_qty || yield_qty || 1"},"yield_qty":{"type":"number","description":"Stored as portion_qty in product_recipes"},"unit":{"type":"string","description":""},"qty_used":{"type":"number","description":""},"unit_cost":{"type":"number","description":""},"total_cost":{"type":"number","description":"Rolled into product_cost"},"mode":{"type":"string","description":""},"active_from":{"type":"string","description":""},"active_to":{"type":"string","description":""}},"required":["recipe_id"],"description":"Only phantom recipes can be linked. Row skipped if recipe_id missing."},"description":"Update deletes all existing product_recipes then rewrites. Phantom recipes only."},"addons":{"type":"array","items":{"type":"string","description":""},"description":"JSON-stringified onto products.addons. Typically product ids."},"bundle_items":{"type":"array","items":{"type":"string","description":""},"description":"JSON-stringified onto products.bundle_items."},"is_addon":{"type":"string","description":""},"is_open_price":{"type":"string","description":""},"is_weightage_item":{"type":"string","description":""},"is_archive":{"type":"string","description":""},"is_combo":{"type":"string","description":""},"is_disabled":{"type":"string","description":""},"is_stock_product":{"type":"string","description":""},"is_auto_apply":{"type":"string","description":""},"is_manual_cost":{"type":"string","description":"Stripped from product table insert. Frontend sends it."},"sync_deliverect":{"type":"string","description":""},"sync_otter":{"type":"string","description":""},"unit_id":{"type":"string","description":""},"plu":{"type":"string","description":""},"sku_no":{"type":"string","description":"Trimmed. Master + empty → auto global SKU."},"barcode_type":{"type":"string","description":""},"barcode_value":{"type":"string","description":""},"image":{"type":"string","description":"Upload path. Normalized. Overridden by web_image if both set."},"web_image":{"type":"string","description":"Copied onto image, then stripped from table insert."},"calories":{"type":"number","description":""},"menu_sort_order":{"type":"number","description":""},"base_price":{"type":"number","description":""},"localized":{"type":"string","description":""},"new_cost_date":{"type":"string","description":""},"id":{"type":"number","description":"Frontend update mutation also puts id in the body; handler uses path param."}},"required":["name"]}},{"name":"update_product","description":"Calls PUT /api/products/:id on https://app.syspos.ae. Used by frontend-v2 updateProduct, updateAddOn. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""},"name":{"type":"string","description":"400 if blank. Unique by name, or name+label when product_unique_formula includes label_id."},"description":{"type":"string","description":""},"localize_name":{"type":"string","description":"Sent by frontend create/update. Persist only if products.localize_name column exists (MySQL SET ?)."},"localize_description":{"type":"string","description":""},"actual_price":{"type":"number","description":""},"price":{"type":"number","description":"Ex-VAT / display price"},"combo_price":{"type":"number","description":""},"product_cost":{"type":"number","description":""},"vat":{"type":"number","description":""},"discount_pct":{"type":"number","description":"Forced to 0 if missing, < 0, or > 100"},"stock":{"type":"number","description":""},"preparation_time":{"type":"number","description":"Minutes. Frontend max 1440."},"category_id":{"type":"array","items":{"type":"string","description":""},"description":"Number, csv, or number[]. Arrays joined with comma."},"label_id":{"type":"array","items":{"type":"string","description":""},"description":"Arrays joined with comma. Frontend currently sends Number(label_id[0])."},"tax_id":{"type":"number","description":""},"tax_group_id":{"type":"string","description":"Stripped from product table insert. Not persisted by create/update handlers."},"type":{"type":"string","description":"Category name(s). If omitted, built from category_id names."},"categories":{"type":"array","items":{"type":"string","description":""},"description":"Copied into type if type empty, then deleted before insert."},"location_id":{"type":"array","items":{"type":"string","description":""},"description":"Number, csv, or number[]. Master insert forces location_id=null on the products row; locations live in location_prices."},"location_prices":{"type":"array","items":{"type":"object","properties":{"location_id":{"type":"number","description":""},"location_price":{"type":"number","description":"Preferred price. Falls back to location_actual_price."},"location_actual_price":{"type":"number","description":"Used when location_price is missing/NaN."},"is_available":{"type":"string","description":"Truthy → 1, else 0. Default 1."},"location_name":{"type":"string","description":"Returned on GET; ignored on write."}},"required":["location_id"],"description":"One location price row. Handler skips the row if location_id is missing."},"description":"If omitted and location_id set (non-master), one row per location is built from actual_price. Update: empty array + master deletes all location rows and archives the product."},"modifiers":{"type":"array","items":{"type":"object","properties":{"modifier_id":{"type":"number","description":""},"id":{"type":"number","description":"Existing product_modifiers.id"},"max_allowed":{"type":"number","description":""},"min_allowed":{"type":"number","description":""},"priority":{"type":"number","description":""},"selection_type":{"type":"string","description":""},"auto_selected_modifier_item_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"mandatory_modifier_item_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"unavailable_modifier_item_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"modifier_items_order":{"type":"array","items":{"type":"number","description":""},"description":"Display order of modifier item ids. Default: modifier_Items.priority."}},"required":["modifier_id"],"description":"Product–modifier link. Rows with modifier_id ≤ 0 or NaN are skipped."},"description":"API expects an array. Frontend form is an object keyed by modifier_id with isChecked; client converts before POST/PUT."},"replace_modifiers":{"type":"boolean","description":"true = replace all modifier links for the target locations."},"modifiers_by_location":{"type":"string","description":"If non-empty, used instead of modifiers."},"price_level":{"type":"array","items":{"type":"object","properties":{"channel_id":{"type":"number","description":"Also accepted as id"},"id":{"type":"number","description":"Alias for channel_id"},"channel_name":{"type":"string","description":""},"name":{"type":"string","description":"Alias for channel_name"},"channel_price":{"type":"number","description":""},"channel_vat":{"type":"number","description":""},"channel_actual_price":{"type":"number","description":""},"check":{"type":"boolean","description":"Frontend form flag. On update, object form keeps only entries with check=true."}},"required":["channel_id"],"description":"Channel/online price. channel_id or id required or the row is skipped."},"description":"Create path: saveChannelPrices(productId, price_level)."},"channel_price":{"type":"string","description":"Preferred over price_level on update."},"materials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Alias for material_id"},"material_id":{"type":"number","description":""},"qty":{"type":"number","description":""},"avg_price":{"type":"number","description":"Unit cost numerator"},"conversionrate":{"type":"number","description":""},"unit":{"type":"string","description":""},"wastage":{"type":"number","description":""},"name":{"type":"string","description":""}},"required":["material_id"],"description":"Recipe BOM line stored in product_materials."},"description":"Update deletes all existing product_materials then rewrites. Omit/empty = clear."},"recipes":{"type":"array","items":{"type":"object","properties":{"recipe_id":{"type":"number","description":"Also accepted as id on create payload from frontend"},"id":{"type":"number","description":"Alias for recipe_id (frontend)"},"portion_qty":{"type":"number","description":"Frontend sends portion_qty || yield_qty || 1"},"yield_qty":{"type":"number","description":"Stored as portion_qty in product_recipes"},"unit":{"type":"string","description":""},"qty_used":{"type":"number","description":""},"unit_cost":{"type":"number","description":""},"total_cost":{"type":"number","description":"Rolled into product_cost"},"mode":{"type":"string","description":""},"active_from":{"type":"string","description":""},"active_to":{"type":"string","description":""}},"required":["recipe_id"],"description":"Only phantom recipes can be linked. Row skipped if recipe_id missing."},"description":"Update deletes all existing product_recipes then rewrites. Phantom recipes only."},"addons":{"type":"array","items":{"type":"string","description":""},"description":"JSON-stringified onto products.addons. Typically product ids."},"bundle_items":{"type":"array","items":{"type":"string","description":""},"description":"JSON-stringified onto products.bundle_items."},"is_addon":{"type":"string","description":""},"is_open_price":{"type":"string","description":""},"is_weightage_item":{"type":"string","description":""},"is_archive":{"type":"string","description":""},"is_combo":{"type":"string","description":""},"is_disabled":{"type":"string","description":""},"is_stock_product":{"type":"string","description":""},"is_auto_apply":{"type":"string","description":""},"is_manual_cost":{"type":"string","description":"Stripped from product table insert. Frontend sends it."},"sync_deliverect":{"type":"string","description":""},"sync_otter":{"type":"string","description":""},"unit_id":{"type":"string","description":""},"plu":{"type":"string","description":""},"sku_no":{"type":"string","description":"Trimmed. Master + empty → auto global SKU."},"barcode_type":{"type":"string","description":""},"barcode_value":{"type":"string","description":""},"image":{"type":"string","description":"Upload path. Normalized. Overridden by web_image if both set."},"web_image":{"type":"string","description":"Copied onto image, then stripped from table insert."},"calories":{"type":"number","description":""},"menu_sort_order":{"type":"number","description":""},"base_price":{"type":"number","description":""},"localized":{"type":"string","description":""},"new_cost_date":{"type":"string","description":""}},"required":["id","name"]}},{"name":"delete_product","description":"Soft delete: SET is_deleted = 1 Calls DELETE /api/products/:id on https://app.syspos.ae. Safety: destructive. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""}},"required":["id"]}},{"name":"archive_product","description":"Calls PUT /api/products/archive_product/:id on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""},"is_archive":{"type":"string","description":"\"0\" un-archives. Anything else archives."}},"required":["id"]}},{"name":"bulk_archive_products","description":"Calls POST /api/products/bulk-archive on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"location_id":{"type":"array","items":{"type":"string","description":""},"description":"Single id, csv, or number[]. All/empty → 400."},"is_archive":{"type":"string","description":"0 or \"0\" = enable (unarchive). Else disable (1)."}},"required":["product_ids","location_id"]}},{"name":"delete_all_products","description":"Master only. Removes products_locations for loc; archives products with no remaining locations. Calls DELETE /api/products/all on https://app.syspos.ae. Safety: destructive. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"loc":{"type":"number","description":"Default session location_id"}},"required":[]}},{"name":"assign_product_locations","description":"Calls POST /api/products/assign-locations on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"location_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"mode":{"type":"string","enum":["add","replace"],"description":"Anything other than replace is treated as add."}},"required":["product_ids","location_ids"]}},{"name":"bulk_update_prices_preview","description":"Calls POST /api/products/bulk-update-prices/preview on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"adjustment_direction":{"type":"string","enum":["add","subtract"],"description":""},"value":{"type":"number","description":"NaN → 400"},"adjustment_type":{"type":"string","enum":["fixed","percentage"],"description":"Anything other than fixed is percentage."},"location_id":{"type":"string","description":"Location id, or \"all\" / null / omitted."}},"required":["product_ids","adjustment_direction","value"]}},{"name":"bulk_update_prices","description":"Calls POST /api/products/bulk-update-prices on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"adjustment_direction":{"type":"string","enum":["add","subtract"],"description":""},"value":{"type":"number","description":""},"adjustment_type":{"type":"string","enum":["fixed","percentage"],"description":""},"location_id":{"type":"string","description":""}},"required":["product_ids","adjustment_direction","value"]}},{"name":"bulk_update_channel_prices_preview","description":"Calls POST /api/products/bulk-update-channel-prices/preview on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"adjustment_direction":{"type":"string","enum":["add","subtract"],"description":""},"value":{"type":"number","description":""},"adjustment_type":{"type":"string","enum":["fixed","percentage"],"description":""},"channel_id":{"type":"string","description":"Channel id, or \"all\" / null / omitted."}},"required":["product_ids","adjustment_direction","value"]}},{"name":"bulk_update_channel_prices","description":"Calls POST /api/products/bulk-update-channel-prices on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"number","description":""},"description":""},"adjustment_direction":{"type":"string","enum":["add","subtract"],"description":""},"value":{"type":"number","description":""},"adjustment_type":{"type":"string","enum":["fixed","percentage"],"description":""},"channel_id":{"type":"string","description":""}},"required":["product_ids","adjustment_direction","value"]}},{"name":"bulk_update_sort_order","description":"Calls POST /api/products/bulk-update-sort-order on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":""},"menu_sort_order":{"type":"number","description":"Must not be null/undefined. Parsed as int."}},"required":["id","menu_sort_order"],"description":""},"description":""}},"required":["products"]}},{"name":"bulk_update_tax","description":"Calls POST /api/products/bulk-update-tax on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"productIds":{"type":"array","items":{"type":"number","description":""},"description":"camelCase. Not product_ids."},"taxId":{"type":"number","description":"camelCase. Not tax_id."}},"required":["productIds","taxId"]}},{"name":"match_products_by_name","description":"Calls POST /api/products/match-by-name on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"productNames":{"type":"array","items":{"type":"string","description":""},"description":""},"customer_id":{"type":"number","description":"This handler reads body.customer_id (not only JWT). Gateway should inject and ignore client value."},"location_id":{"type":"number","description":"Non-master also filters products.location_id."}},"required":["productNames","customer_id","location_id"]}},{"name":"get_product_pricing_summary","description":"Calls GET /api/products/:id/pricing-summary on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""}},"required":["id"]}},{"name":"get_products_recipe_costs","description":"Also accepts the same fields on JSON body (req.query.x || req.body.x). Calls GET /api/products/recipe-costs on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"product_ids":{"type":"array","items":{"type":"string","description":""},"description":"Csv or number[]. Missing → {}"},"loc":{"type":"string","description":""},"breakdown":{"type":"string","enum":["1","true"],"description":""},"per_location":{"type":"string","enum":["1","true"],"description":""}},"required":[]}},{"name":"get_product_materials","description":"Calls GET /api/products/:id/materials on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""}},"required":["id"]}},{"name":"create_product_materials","description":"Path :id is not read. product_id must be in the body. location_id and customer_id overwritten from JWT. Calls POST /api/products/:id/materials on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":"Unused by handler"},"name":{"type":"string","description":""},"qty":{"type":"number","description":""},"product_id":{"type":"number","description":"Inserted as product_materials.product_id"},"material_id":{"type":"number","description":""},"price":{"type":"number","description":""},"unit":{"type":"string","description":""},"wastage":{"type":"number","description":""}},"required":["product_id","material_id"]}},{"name":"edit_product_materials","description":"Not in the 528 client list. Path :id is the product_materials row id. SQL updates qty, price, wastage only. Calls PUT /api/products/materials/:id on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":"product_materials.id"},"qty":{"type":"number","description":""},"price":{"type":"number","description":""},"wastage":{"type":"number","description":""}},"required":["id"]}},{"name":"upload_product_image","description":"Calls POST /api/products/:productId/upload-image on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"productId":{"type":"number","description":""},"attachment":{"type":"string","description":"Single file. Multer upload.single(\"attachment\")."}},"required":["productId","attachment"]}},{"name":"bulk_upload_product_image","description":"Despite the name, exactly one product id per request. Calls POST /api/products/bulk-image-upload on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"productIds":{"type":"array","items":{"type":"number","description":""},"description":"JSON array or JSON string. Aliases: productsIds, product_ids, ids. Length must be 1."},"attachment":{"type":"string","description":"File field; JSON calls are not supported"}},"required":["productIds","attachment"]}},{"name":"remove_product_image","description":"Path :id is unused. SQL uses body.id. Calls PUT /api/products/remove_image/:id on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":"Unused in SQL"}},"required":[]}},{"name":"verify_product_plu","description":"Calls GET /api/products/unique-verification-plu on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"plu":{"type":"string","description":""},"product_id":{"type":"number","description":"OK if the found product is this id (self)."},"location_id":{"type":"number","description":"Default req.user.location_id"}},"required":[]}},{"name":"get_product_units","description":"Calls GET /api/products/units on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."}},"required":[]}},{"name":"get_product_tax_groups_enhanced","description":"Calls GET /api/products/tax-groups-enhanced on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."}},"required":[]}},{"name":"get_pos_product","description":"Calls GET /api/v2/products/:id on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":""},"is_archive":{"type":"string","description":""},"loc":{"type":"string","description":""}},"required":["id"]}},{"name":"list_products_pos_list","description":"Calls GET /api/v2/products/list on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"k":{"type":"string","description":""},"addon":{"type":"string","description":""},"cat":{"type":"string","description":""},"page_limit":{"type":"number","description":""},"records_per_page":{"type":"number","description":"Alias for page_limit"},"current_page":{"type":"number","description":""}},"required":[]}},{"name":"list_products_pos_web","description":"Calls GET /api/v2/products/web on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"loc":{"type":"string","description":""},"addon":{"type":"string","description":""},"cat":{"type":"string","description":""},"k":{"type":"string","description":""},"page_limit":{"type":"number","description":""},"current_page":{"type":"number","description":""}},"required":[]}},{"name":"get_product_modifier_ordering","description":"Calls GET /api/v2/products/modifier-ordering on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"loc":{"type":"number","description":"Default req.user.location_id. 400 if neither present."}},"required":[]}},{"name":"update_product_availability","description":"Calls POST /api/v2/products/availability on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"itemId":{"type":"string","description":"Product or already-prefixed PRO-{id}. Required unless product_id / item_id / modifier_item_id is sent."},"item_id":{"type":"string","description":"Alias for itemId"},"product_id":{"type":"number","description":"Used as PRO-{id} when itemId/item_id omitted"},"modifier_item_id":{"type":"number","description":"Used as MOD-{id} when itemId/item_id omitted"},"availability":{"type":"string","enum":["AVAILABLE","UNAVAILABLE","HIDDEN"],"description":"Also accepted as status"},"status":{"type":"string","enum":["AVAILABLE","UNAVAILABLE","HIDDEN"],"description":"Alias for availability"},"itemType":{"type":"string","description":"Empty → PRODUCT. Alias item_type."},"item_type":{"type":"string","description":""},"locationId":{"type":"number","description":"Default JWT location_id. Alias location_id."},"location_id":{"type":"number","description":""},"brandId":{"type":"number","description":"Alias brand_id"},"brand_id":{"type":"number","description":""},"menuId":{"type":"string","description":"Grubtech menu id. Alias menu_id. Derived from location if omitted."},"menu_id":{"type":"string","description":""},"storeId":{"type":"string","description":"Alias store_id. Derived from location if omitted."},"store_id":{"type":"string","description":""}},"required":["availability"]}},{"name":"get_top_saled_products","description":"Calls GET /api/v2/products/top-saled on https://app.syspos.ae. Safety: read. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"location_id":{"type":"number","description":""},"page_limit":{"type":"number","description":""},"current_page":{"type":"number","description":""}},"required":[]}},{"name":"quick_update_product","description":"Not in the 528 client list. Path :id unused. SQL uses body.id. No validation. Calls PUT /api/products/:id/quick on https://app.syspos.ae. Safety: write. customer_id is taken from the MCP session — do not send it.","parameters":{"type":"object","properties":{"api_key":{"type":"string","description":"(Legacy) MCP API key. Prefer Authorization: Bearer <key>."},"id":{"type":"number","description":"Unused in SQL"},"name":{"type":"string","description":""},"description":{"type":"string","description":""},"menu_sort_order":{"type":"number","description":""},"is_stock_product":{"type":"string","description":""},"calories":{"type":"number","description":""},"localize_name":{"type":"string","description":""},"localize_description":{"type":"string","description":""}},"required":[]}}]}