[
  {
    "name": "cosmetics_ingredient_lookup",
    "title": "Ingredient lookup by INCI, CAS or text",
    "description": "Substances (by legal-glossary or CosIng INCI name, CAS number or chemical name) with every rule that lists them, by market: EU, GB, US federal and 8 US states, with citations to the official text. (Quota cost: 1 unit.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "inci": {
          "type": "string",
          "maxLength": 200
        },
        "cas": {
          "type": "string",
          "maxLength": 20
        },
        "q": {
          "type": "string",
          "minLength": 3,
          "maxLength": 200
        },
        "limit": {
          "type": "integer",
          "minimum": 1,
          "maximum": 50,
          "default": 10
        }
      },
      "required": [],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_ingredient_get",
    "title": "Get a substance by id",
    "description": "One substance (cas:<CAS>, ec:<EC>, inci:<INCI>, name:<name>) with its rules in every market and linked identifiers. (Quota cost: 1 unit.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^(cas|ec|inci|name|class):[^/]{1,190}$"
        }
      },
      "required": [
        "id"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_rules_by_market",
    "title": "Rules by market",
    "description": "Machine-readable rules of a market: status (prohibited, restricted, allowed colorant/preservative/UV filter, labelling threshold, state ban), each clause with its product-type scope, limits (numbers copied by code from the legal text), conditions and warnings, dates (placing on the market, sell-through), citations with verbatim quotes, and how disagreements between the two extraction passes were resolved. (Quota cost: 1 unit.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "market": {
          "type": "string",
          "enum": [
            "EU",
            "GB",
            "US",
            "US-CA",
            "US-CO",
            "US-MD",
            "US-ME",
            "US-MN",
            "US-OR",
            "US-VT",
            "US-WA"
          ],
          "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
        },
        "inci": {
          "type": "string",
          "maxLength": 200
        },
        "cas": {
          "type": "string",
          "maxLength": 20
        },
        "status": {
          "type": "string",
          "enum": [
            "prohibited",
            "restricted",
            "labelling_threshold",
            "allowed_colorant",
            "allowed_preservative",
            "allowed_uv_filter",
            "state_ban"
          ]
        },
        "limit": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        },
        "offset": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000,
          "default": 0
        }
      },
      "required": [
        "market"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_compare_markets",
    "title": "Compare an ingredient's rules across markets",
    "description": "Every rule that lists an ingredient, market by market (a US state also shows US federal rules), with status, dates, clause limits copied by code and the entry citation; plus EU/GB divergences entry by entry. (Quota cost: 1 unit.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "inci": {
          "type": "string",
          "maxLength": 200
        },
        "cas": {
          "type": "string",
          "maxLength": 20
        },
        "markets": {
          "type": "string",
          "maxLength": 120,
          "description": "Comma-separated markets (default: all), e.g. EU,GB,US-CA"
        }
      },
      "required": [],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_categories",
    "title": "Product categories",
    "description": "The product categories the checks accept, each with its product tags. (Quota cost: free.)",
    "inputSchema": {
      "type": "object",
      "properties": {},
      "required": [],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_formula_check",
    "title": "Check a formula against market rules",
    "description": "For each market: PASS, FAIL, NEEDS_ATTENTION or NOT_MODELLED per ingredient and overall. Bans, maximum concentrations by product type (including on-head limits after mixing for oxidative hair dyes, group limits and limits 'calculated as'), positive lists for preservatives, UV filters and colorants, dates (placing on the market or making available), US state class bans and contaminant limits. Unmodelled wording never gives PASS, and an ingredient that resolves to no known substance (no rule, CosIng inventory INCI name, CAS or EC number) is NOT_MODELLED; a missing concentration is never treated as zero. (Quota cost: 10 units.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "markets": {
          "type": "array",
          "minItems": 1,
          "maxItems": 11,
          "items": {
            "type": "string",
            "enum": [
              "EU",
              "GB",
              "US",
              "US-CA",
              "US-CO",
              "US-MD",
              "US-ME",
              "US-MN",
              "US-OR",
              "US-VT",
              "US-WA"
            ],
            "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
          }
        },
        "product_category": {
          "type": "string",
          "maxLength": 64,
          "description": "GET /v1/cosmetics/categories"
        },
        "as_of": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "YYYY-MM-DD"
        },
        "mode": {
          "type": "string",
          "enum": [
            "placing",
            "making_available"
          ],
          "default": "placing"
        },
        "children_under_3": {
          "type": "boolean"
        },
        "professional_use": {
          "type": "boolean"
        },
        "mixing_ratio": {
          "type": "string",
          "pattern": "^\\s*\\d+(\\.\\d+)?\\s*:\\s*\\d+(\\.\\d+)?\\s*$",
          "description": "Oxidative hair or eyelash dye: product:developer, e.g. '1:1'"
        },
        "formaldehyde_released_pct": {
          "type": [
            "number",
            "string",
            "null"
          ],
          "description": "Maximum theoretical releasable formaldehyde of the whole product, from every source, percent w/w. Settles the 'releases formaldehyde' label and the Annex II bans that apply only at or above 0,1 % (II/1605-1607). null or omitted = not known: never treated as 0"
        },
        "contaminants_ppm": {
          "type": "object",
          "additionalProperties": {
            "type": [
              "number",
              "string"
            ]
          },
          "description": "Measured contaminants, e.g. {\"lead\": 2, \"1,4-dioxane\": 1}"
        },
        "ingredients": {
          "type": "array",
          "minItems": 1,
          "maxItems": 200,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "inci": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "description": "INCI name as on the label"
              },
              "cas": {
                "type": "string",
                "pattern": "^\\d{2,7}-\\d{2}-\\d$",
                "description": "CAS number"
              },
              "ec": {
                "type": "string",
                "pattern": "^\\d{3}-\\d{3}-\\d$",
                "description": "EC (EINECS / ELINCS) number"
              },
              "name": {
                "type": "string",
                "maxLength": 200,
                "description": "Other name (chemical name)"
              },
              "pct": {
                "type": [
                  "number",
                  "string",
                  "null"
                ],
                "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
              },
              "function": {
                "type": "string",
                "maxLength": 40,
                "description": "What the ingredient does in this formula (e.g. preservative, uv_filter, colorant, ph_adjuster, solvent, denaturant, fragrance_ingredient). Settles entries tied to a use; if omitted they come back NEEDS_ATTENTION."
              },
              "basis": {
                "type": "string",
                "maxLength": 60,
                "description": "Basis of pct when a limit is 'calculated as' something (e.g. 'free base', 'zinc')"
              },
              "intentionally_added": {
                "type": "boolean",
                "description": "false for trace/contaminant presence (threshold rules)"
              },
              "flags": {
                "type": "array",
                "maxItems": 5,
                "items": {
                  "type": "string",
                  "enum": [
                    "pfas",
                    "ortho_phthalate",
                    "formaldehyde_releaser"
                  ]
                },
                "description": "Class membership you know (class bans cannot be settled from a name)"
              }
            }
          }
        }
      },
      "required": [
        "markets",
        "product_category",
        "ingredients"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_formula_check_batch",
    "title": "Check many formulas",
    "description": "Up to 50 formulas in one call, each as POST /v1/cosmetics/formula-check takes it (plus an optional id), with at most 1,000 ingredient rows and 5,000 ingredient-market checks (ingredients x markets) in all; each answers with its verdicts or its own error, and the summary counts verdicts. (Quota cost: 10 units per formula.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "formulas": {
          "type": "array",
          "minItems": 1,
          "maxItems": 50,
          "items": {
            "type": "object",
            "required": [
              "markets",
              "product_category",
              "ingredients"
            ],
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string",
                "maxLength": 60
              },
              "markets": {
                "type": "array",
                "minItems": 1,
                "maxItems": 11,
                "items": {
                  "type": "string",
                  "enum": [
                    "EU",
                    "GB",
                    "US",
                    "US-CA",
                    "US-CO",
                    "US-MD",
                    "US-ME",
                    "US-MN",
                    "US-OR",
                    "US-VT",
                    "US-WA"
                  ],
                  "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
                }
              },
              "product_category": {
                "type": "string",
                "maxLength": 64
              },
              "as_of": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "description": "YYYY-MM-DD"
              },
              "mode": {
                "type": "string",
                "enum": [
                  "placing",
                  "making_available"
                ]
              },
              "children_under_3": {
                "type": "boolean"
              },
              "professional_use": {
                "type": "boolean"
              },
              "mixing_ratio": {
                "type": "string",
                "pattern": "^\\s*\\d+(\\.\\d+)?\\s*:\\s*\\d+(\\.\\d+)?\\s*$"
              },
              "formaldehyde_released_pct": {
                "type": [
                  "number",
                  "string",
                  "null"
                ],
                "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
              },
              "contaminants_ppm": {
                "type": "object",
                "additionalProperties": {
                  "type": [
                    "number",
                    "string"
                  ]
                }
              },
              "ingredients": {
                "type": "array",
                "minItems": 1,
                "maxItems": 200,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "inci": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "description": "INCI name as on the label"
                    },
                    "cas": {
                      "type": "string",
                      "pattern": "^\\d{2,7}-\\d{2}-\\d$",
                      "description": "CAS number"
                    },
                    "ec": {
                      "type": "string",
                      "pattern": "^\\d{3}-\\d{3}-\\d$",
                      "description": "EC (EINECS / ELINCS) number"
                    },
                    "name": {
                      "type": "string",
                      "maxLength": 200,
                      "description": "Other name (chemical name)"
                    },
                    "pct": {
                      "type": [
                        "number",
                        "string",
                        "null"
                      ],
                      "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                    },
                    "function": {
                      "type": "string",
                      "maxLength": 40,
                      "description": "What the ingredient does in this formula (e.g. preservative, uv_filter, colorant, ph_adjuster, solvent, denaturant, fragrance_ingredient). Settles entries tied to a use; if omitted they come back NEEDS_ATTENTION."
                    },
                    "basis": {
                      "type": "string",
                      "maxLength": 60,
                      "description": "Basis of pct when a limit is 'calculated as' something (e.g. 'free base', 'zinc')"
                    },
                    "intentionally_added": {
                      "type": "boolean",
                      "description": "false for trace/contaminant presence (threshold rules)"
                    },
                    "flags": {
                      "type": "array",
                      "maxItems": 5,
                      "items": {
                        "type": "string",
                        "enum": [
                          "pfas",
                          "ortho_phthalate",
                          "formaldehyde_releaser"
                        ]
                      },
                      "description": "Class membership you know (class bans cannot be settled from a name)"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "required": [
        "formulas"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_allergen_label",
    "title": "Allergen label calculation",
    "description": "Which fragrance allergens must be named in the ingredient list (EU and GB): concentrations from a fragrance composition and dose or given directly, isomers and group members summed (e.g. geranial + neral = Citral), leave-on and rinse-off thresholds, dated by placing on the market (the 2023 EU allergen list applies from its dates). (Quota cost: 10 units.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "markets": {
          "type": "array",
          "minItems": 1,
          "maxItems": 2,
          "items": {
            "type": "string",
            "enum": [
              "EU",
              "GB"
            ]
          }
        },
        "product_category": {
          "type": "string",
          "maxLength": 64
        },
        "exposure": {
          "type": "string",
          "enum": [
            "leave_on",
            "rinse_off"
          ],
          "description": "If no product_category"
        },
        "as_of": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "YYYY-MM-DD"
        },
        "fragrance": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "dose_pct": {
              "type": [
                "number",
                "string",
                "null"
              ],
              "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
            },
            "composition": {
              "type": "array",
              "maxItems": 300,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "inci": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "cas": {
                    "type": "string",
                    "maxLength": 20
                  },
                  "pct_in_fragrance": {
                    "type": [
                      "number",
                      "string",
                      "null"
                    ],
                    "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                  }
                }
              }
            }
          }
        },
        "allergens": {
          "type": "array",
          "maxItems": 300,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "inci": {
                "type": "string",
                "maxLength": 200
              },
              "name": {
                "type": "string",
                "maxLength": 200
              },
              "cas": {
                "type": "string",
                "maxLength": 20
              },
              "pct_in_product": {
                "type": [
                  "number",
                  "string",
                  "null"
                ],
                "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
              }
            }
          }
        }
      },
      "required": [
        "markets"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_label_check",
    "title": "Validate an INCI ingredient list",
    "description": "Checks an ingredient list as printed (EU, GB or US): descending order above 1 % (with concentrations), fragrance term, nano and CI formats, prohibited ingredients for the product type, allergens that must be named, 'may contain' use; each finding cites Article 19 of Regulation 1223/2009 (or the GB text) or 21 CFR 701.3. (Quota cost: 10 units.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "market": {
          "type": "string",
          "enum": [
            "EU",
            "GB",
            "US",
            "US-CA",
            "US-CO",
            "US-MD",
            "US-ME",
            "US-MN",
            "US-OR",
            "US-VT",
            "US-WA"
          ],
          "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 5000,
          "description": "Ingredient list as printed, e.g. 'Ingredients: Aqua, Glycerin, ...'"
        },
        "product_category": {
          "type": "string",
          "maxLength": 64
        },
        "as_of": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "YYYY-MM-DD"
        },
        "children_under_3": {
          "type": "boolean"
        },
        "formula": {
          "type": "array",
          "maxItems": 200,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "inci": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "description": "INCI name as on the label"
              },
              "cas": {
                "type": "string",
                "pattern": "^\\d{2,7}-\\d{2}-\\d$",
                "description": "CAS number"
              },
              "ec": {
                "type": "string",
                "pattern": "^\\d{3}-\\d{3}-\\d$",
                "description": "EC (EINECS / ELINCS) number"
              },
              "name": {
                "type": "string",
                "maxLength": 200,
                "description": "Other name (chemical name)"
              },
              "pct": {
                "type": [
                  "number",
                  "string",
                  "null"
                ],
                "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
              },
              "function": {
                "type": "string",
                "maxLength": 40,
                "description": "What the ingredient does in this formula (e.g. preservative, uv_filter, colorant, ph_adjuster, solvent, denaturant, fragrance_ingredient). Settles entries tied to a use; if omitted they come back NEEDS_ATTENTION."
              },
              "basis": {
                "type": "string",
                "maxLength": 60,
                "description": "Basis of pct when a limit is 'calculated as' something (e.g. 'free base', 'zinc')"
              },
              "intentionally_added": {
                "type": "boolean",
                "description": "false for trace/contaminant presence (threshold rules)"
              },
              "flags": {
                "type": "array",
                "maxItems": 5,
                "items": {
                  "type": "string",
                  "enum": [
                    "pfas",
                    "ortho_phthalate",
                    "formaldehyde_releaser"
                  ]
                },
                "description": "Class membership you know (class bans cannot be settled from a name)"
              }
            }
          },
          "description": "Concentrations (enables the order and allergen checks)"
        }
      },
      "required": [
        "market",
        "label"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  },
  {
    "name": "cosmetics_changes",
    "title": "Rule change feed",
    "description": "Dated events of the rules, newest first: entries into force, placing-on-the-market dates, last days for non-compliant stock, adopted rules not yet in force, renumbering and replaced texts. Filter by date range, market and event. (Quota cost: 1 unit.)",
    "inputSchema": {
      "type": "object",
      "properties": {
        "since": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "YYYY-MM-DD"
        },
        "until": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "YYYY-MM-DD"
        },
        "market": {
          "type": "string",
          "enum": [
            "EU",
            "GB",
            "US",
            "US-CA",
            "US-CO",
            "US-MD",
            "US-ME",
            "US-MN",
            "US-OR",
            "US-VT",
            "US-WA"
          ],
          "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
        },
        "event": {
          "type": "string",
          "enum": [
            "in_force",
            "placing_on_market_ban_or_limit_applies",
            "last_day_non_compliant_stock_may_be_made_available",
            "pending_not_yet_in_force",
            "requirement_applies_from",
            "renumbered",
            "text_replaced"
          ]
        },
        "limit": {
          "type": "integer",
          "minimum": 1,
          "maximum": 500,
          "default": 100
        },
        "offset": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000,
          "default": 0
        }
      },
      "required": [
        "since"
      ],
      "additionalProperties": false
    },
    "annotations": {
      "readOnlyHint": true,
      "destructiveHint": false,
      "idempotentHint": true,
      "openWorldHint": false
    }
  }
]
