{
  "name": "Hopi",
  "schema_version": "1.0",
  "webmcp_api": "document.modelContext",
  "discovery": "/webmcp.json",
  "description": "Free client-side calculators, converters and generators. Each tool below is callable via WebMCP (document.modelContext) on its own page: open the url, discover the registered tool, then invoke the named tool. Each entry includes the tool's inputSchema so arguments can be planned and validated before opening the page.",
  "site": "https://hopi.co.uk",
  "count": 185,
  "tools": [
    {
      "name": "hopi_cmyk_to_rgb",
      "title": "CMYK to RGB converter",
      "url": "https://hopi.co.uk/cmyk-to-rgb/",
      "category": "colour",
      "description": "Convert print CMYK values (each 0 to 100) to on-screen RGB and hex, or convert RGB (each 0 to 255) the other way to CMYK. Uses the standard device-independent conversion.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "cmyk_to_rgb",
              "rgb_to_cmyk"
            ],
            "description": "Direction of conversion"
          },
          "c": {
            "type": "number",
            "description": "Cyan 0 to 100 (for cmyk_to_rgb)"
          },
          "m": {
            "type": "number",
            "description": "Magenta 0 to 100 (for cmyk_to_rgb)"
          },
          "y": {
            "type": "number",
            "description": "Yellow 0 to 100 (for cmyk_to_rgb)"
          },
          "k": {
            "type": "number",
            "description": "Key/black 0 to 100 (for cmyk_to_rgb)"
          },
          "r": {
            "type": "integer",
            "description": "Red 0 to 255 (for rgb_to_cmyk)"
          },
          "g": {
            "type": "integer",
            "description": "Green 0 to 255 (for rgb_to_cmyk)"
          },
          "b": {
            "type": "integer",
            "description": "Blue 0 to 255 (for rgb_to_cmyk)"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_colour_name_finder",
      "title": "Colour name finder",
      "url": "https://hopi.co.uk/colour-name-finder/",
      "category": "colour",
      "description": "Find the named CSS colour that exactly or most closely matches a hex code, using straight-line distance in RGB space across the 148 named CSS colours.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "hex": {
            "type": "string",
            "description": "Hex colour code, e.g. #DC143C or #F00"
          }
        },
        "required": [
          "hex"
        ]
      }
    },
    {
      "name": "hopi_colour_palette_generator",
      "title": "Colour palette generator",
      "url": "https://hopi.co.uk/colour-palette-generator/",
      "category": "colour",
      "description": "Generate a five-swatch colour palette from a base hex colour using a chosen scheme: analogous, complementary, triadic or mixed. Supporting swatches carry a small random variation, so results vary slightly each call.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "hex": {
            "type": "string",
            "description": "Base colour as a six-digit hex code, e.g. #1F8A70"
          },
          "scheme": {
            "type": "string",
            "enum": [
              "analogous",
              "complementary",
              "triadic",
              "mixed"
            ],
            "description": "Colour scheme (default analogous)"
          }
        },
        "required": [
          "hex"
        ]
      }
    },
    {
      "name": "hopi_colour_picker",
      "title": "Colour picker",
      "url": "https://hopi.co.uk/colour-picker/",
      "category": "colour",
      "description": "Given a six-digit hex colour code (with or without a leading #), return its hex, RGB and HSL values.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "hex": {
            "type": "string",
            "description": "Six-digit hex colour code, e.g. #1F8A70"
          }
        },
        "required": [
          "hex"
        ]
      }
    },
    {
      "name": "hopi_colour_shades_generator",
      "title": "Shades & tints generator",
      "url": "https://hopi.co.uk/colour-shades-generator/",
      "category": "colour",
      "description": "From a base hex colour, generate five progressively lighter tints (mixed towards white) and five progressively darker shades (mixed towards black), each in five equal steps of one sixth.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "hex": {
            "type": "string",
            "description": "Base colour as a six-digit hex code, e.g. #1F8A70"
          }
        },
        "required": [
          "hex"
        ]
      }
    },
    {
      "name": "hopi_contrast_checker",
      "title": "Contrast checker",
      "url": "https://hopi.co.uk/contrast-checker/",
      "category": "colour",
      "description": "Work out the WCAG contrast ratio between a foreground (text) colour and a background colour, both as hex codes, and report whether it passes AA and AAA for normal and large text.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "foreground": {
            "type": "string",
            "description": "Text colour as a six-digit hex code, e.g. #767676"
          },
          "background": {
            "type": "string",
            "description": "Background colour as a six-digit hex code, e.g. #FFFFFF"
          }
        },
        "required": [
          "foreground",
          "background"
        ]
      }
    },
    {
      "name": "hopi_css_gradient_generator",
      "title": "CSS gradient generator",
      "url": "https://hopi.co.uk/css-gradient-generator/",
      "category": "colour",
      "description": "Build a ready-to-use CSS gradient from two colours. Choose a linear gradient with an angle in degrees, or a radial gradient. Returns the gradient value and a full background declaration.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "colour1": {
            "type": "string",
            "description": "First colour, e.g. #FF512F"
          },
          "colour2": {
            "type": "string",
            "description": "Second colour, e.g. #DD2476"
          },
          "type": {
            "type": "string",
            "enum": [
              "linear",
              "radial"
            ],
            "description": "Gradient type (default linear)"
          },
          "angle": {
            "type": "number",
            "description": "Angle in degrees for a linear gradient (default 90)"
          }
        },
        "required": [
          "colour1",
          "colour2"
        ]
      }
    },
    {
      "name": "hopi_hex_to_rgb",
      "title": "Hex to RGB converter",
      "url": "https://hopi.co.uk/hex-to-rgb/",
      "category": "colour",
      "description": "Convert a hex colour code (3, 6 or 8 digits, with or without a leading #) to its RGB and HSL values.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "hex": {
            "type": "string",
            "description": "Hex colour code, e.g. #D7263D or F0C"
          }
        },
        "required": [
          "hex"
        ]
      }
    },
    {
      "name": "hopi_hsl_converter",
      "title": "HSL converter",
      "url": "https://hopi.co.uk/hsl-converter/",
      "category": "colour",
      "description": "Convert a hex colour code to hue, saturation and lightness (HSL), or convert HSL values to hex and RGB.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "hex_to_hsl",
              "hsl_to_hex"
            ],
            "description": "Direction of conversion"
          },
          "hex": {
            "type": "string",
            "description": "Hex colour code, e.g. #1FE85C (for hex_to_hsl)"
          },
          "h": {
            "type": "number",
            "description": "Hue 0 to 360 (for hsl_to_hex)"
          },
          "s": {
            "type": "number",
            "description": "Saturation 0 to 100 (for hsl_to_hex)"
          },
          "l": {
            "type": "number",
            "description": "Lightness 0 to 100 (for hsl_to_hex)"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_random_colour_generator",
      "title": "Random colour generator",
      "url": "https://hopi.co.uk/random-colour-generator/",
      "category": "colour",
      "description": "Generate a random colour and return its hex, RGB and HSL values. Each of the red, green and blue channels gets an independent value from 0 to 255.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    },
    {
      "name": "hopi_rgb_to_hex",
      "title": "RGB to hex converter",
      "url": "https://hopi.co.uk/rgb-to-hex/",
      "category": "colour",
      "description": "Convert red, green and blue values (each a whole number from 0 to 255) to an uppercase hex colour code.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "r": {
            "type": "integer",
            "description": "Red, 0 to 255"
          },
          "g": {
            "type": "integer",
            "description": "Green, 0 to 255"
          },
          "b": {
            "type": "integer",
            "description": "Blue, 0 to 255"
          }
        },
        "required": [
          "r",
          "g",
          "b"
        ]
      }
    },
    {
      "name": "hopi_angle_converter",
      "title": "Angle converter",
      "url": "https://hopi.co.uk/angle-converter/",
      "category": "convert",
      "description": "Convert an angle from one unit to another. Units: deg (degrees), rad (radians), grad (gradians), turn (full turns).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The angle value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "deg",
              "rad",
              "grad",
              "turn"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "deg",
              "rad",
              "grad",
              "turn"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_area_converter",
      "title": "Area converter",
      "url": "https://hopi.co.uk/area-converter/",
      "category": "convert",
      "description": "Convert an area from one unit to another. Units: sqm (square metres), sqft (square feet), sqyd (square yards), acre (acres), ha (hectares), sqkm (square kilometres), sqmi (square miles).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The area value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "sqm",
              "sqft",
              "sqyd",
              "acre",
              "ha",
              "sqkm",
              "sqmi"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "sqm",
              "sqft",
              "sqyd",
              "acre",
              "ha",
              "sqkm",
              "sqmi"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_aspect_ratio_calculator",
      "title": "Aspect ratio calculator",
      "url": "https://hopi.co.uk/aspect-ratio-calculator/",
      "category": "convert",
      "description": "Aspect ratio helper. In 'simplify' mode, give width and height to get the simplified W:H ratio, decimal ratio and nearest common ratio. In 'solve' mode, give a ratio (ratioW:ratioH) plus one of width or height to get the missing side.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "simplify",
              "solve"
            ],
            "description": "'simplify' a width and height, or 'solve' a missing side from a ratio"
          },
          "width": {
            "type": "number",
            "description": "Width in pixels or units (simplify mode, or the known side in solve mode)"
          },
          "height": {
            "type": "number",
            "description": "Height in pixels or units (simplify mode, or the known side in solve mode)"
          },
          "ratioW": {
            "type": "number",
            "description": "Ratio width part, e.g. 16 (solve mode)"
          },
          "ratioH": {
            "type": "number",
            "description": "Ratio height part, e.g. 9 (solve mode)"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_celsius_to_fahrenheit",
      "title": "Temperature converter",
      "url": "https://hopi.co.uk/celsius-to-fahrenheit/",
      "category": "convert",
      "description": "Convert a temperature between Celsius and Fahrenheit. Also returns Kelvin. Set direction to 'c-to-f' or 'f-to-c'.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The temperature value to convert"
          },
          "direction": {
            "type": "string",
            "enum": [
              "c-to-f",
              "f-to-c"
            ],
            "description": "'c-to-f' converts Celsius to Fahrenheit, 'f-to-c' converts Fahrenheit to Celsius"
          }
        },
        "required": [
          "value",
          "direction"
        ]
      }
    },
    {
      "name": "hopi_cm_to_feet",
      "title": "Cm to feet converter",
      "url": "https://hopi.co.uk/cm-to-feet/",
      "category": "convert",
      "description": "Convert a height between centimetres and feet/inches. Direction 'cm-to-feet' takes cm and returns feet and inches. Direction 'feet-to-cm' takes feet and inches and returns cm.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "direction": {
            "type": "string",
            "enum": [
              "cm-to-feet",
              "feet-to-cm"
            ],
            "description": "Which way to convert"
          },
          "cm": {
            "type": "number",
            "description": "Centimetres (for cm-to-feet)"
          },
          "feet": {
            "type": "number",
            "description": "Feet (for feet-to-cm)"
          },
          "inches": {
            "type": "number",
            "description": "Inches (for feet-to-cm, optional)"
          }
        },
        "required": [
          "direction"
        ]
      }
    },
    {
      "name": "hopi_cups_to_grams",
      "title": "Cups to grams converter",
      "url": "https://hopi.co.uk/cups-to-grams/",
      "category": "convert",
      "description": "Convert US cups of a common baking ingredient to grams (approximate). Ingredients: flour (plain flour), caster (caster sugar), brown (packed brown sugar), butter, cocoa (cocoa powder), oats, rice (uncooked rice), icing (icing sugar).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "cups": {
            "type": "number",
            "description": "Number of US cups"
          },
          "ingredient": {
            "type": "string",
            "enum": [
              "flour",
              "caster",
              "brown",
              "butter",
              "cocoa",
              "oats",
              "rice",
              "icing"
            ],
            "description": "The ingredient"
          }
        },
        "required": [
          "cups",
          "ingredient"
        ]
      }
    },
    {
      "name": "hopi_data_size_converter",
      "title": "Data size converter",
      "url": "https://hopi.co.uk/data-size-converter/",
      "category": "convert",
      "description": "Convert a digital storage size between units. Units: B (bytes), KB, MB, GB, TB. By default 1 KB = 1000 bytes (decimal, as storage is sold). Set binary to true for 1 KB = 1024 bytes (as Windows reports drive sizes).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The size value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "B",
              "KB",
              "MB",
              "GB",
              "TB"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "B",
              "KB",
              "MB",
              "GB",
              "TB"
            ],
            "description": "Unit to convert to"
          },
          "binary": {
            "type": "boolean",
            "description": "Use binary units (1 KB = 1024 bytes) instead of decimal (default false)"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_download_time_calculator",
      "title": "Download time calculator",
      "url": "https://hopi.co.uk/download-time-calculator/",
      "category": "convert",
      "description": "Estimate how long a download takes. Give a file size with its unit (MB, GB, TB) and a connection speed with its unit (Mbps or Gbps in bits per second, or MBps in bytes per second). Returns a human-readable duration and the time in seconds.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "size": {
            "type": "number",
            "description": "File size value"
          },
          "sizeUnit": {
            "type": "string",
            "enum": [
              "MB",
              "GB",
              "TB"
            ],
            "description": "File size unit"
          },
          "speed": {
            "type": "number",
            "description": "Connection speed value"
          },
          "speedUnit": {
            "type": "string",
            "enum": [
              "Mbps",
              "MBps",
              "Gbps"
            ],
            "description": "Speed unit: Mbps/Gbps are bits per second, MBps is megabytes per second"
          }
        },
        "required": [
          "size",
          "sizeUnit",
          "speed",
          "speedUnit"
        ]
      }
    },
    {
      "name": "hopi_kg_to_stone",
      "title": "Kg to stone converter",
      "url": "https://hopi.co.uk/kg-to-stone/",
      "category": "convert",
      "description": "Convert a weight in kilograms to UK stone and pounds. Returns whole stone plus remaining pounds, and the totals in pounds and decimal stone.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "kilograms": {
            "type": "number",
            "description": "Weight in kilograms"
          }
        },
        "required": [
          "kilograms"
        ]
      }
    },
    {
      "name": "hopi_length_converter",
      "title": "Length converter",
      "url": "https://hopi.co.uk/length-converter/",
      "category": "convert",
      "description": "Convert a length from one unit to another. Units: mm, cm, m, km, in (inches), ft (feet), yd (yards), mi (miles).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The length value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "mm",
              "cm",
              "m",
              "km",
              "in",
              "ft",
              "yd",
              "mi"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "mm",
              "cm",
              "m",
              "km",
              "in",
              "ft",
              "yd",
              "mi"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_litres_to_pints",
      "title": "Litres to pints converter",
      "url": "https://hopi.co.uk/litres-to-pints/",
      "category": "convert",
      "description": "Convert between litres and pints. Direction 'litres-to-pints' takes litres and returns UK pints, US pints and millilitres. Direction 'pints-to-litres' takes UK pints and returns litres.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The value to convert (litres or UK pints depending on direction)"
          },
          "direction": {
            "type": "string",
            "enum": [
              "litres-to-pints",
              "pints-to-litres"
            ],
            "description": "Which way to convert"
          }
        },
        "required": [
          "value",
          "direction"
        ]
      }
    },
    {
      "name": "hopi_miles_to_km",
      "title": "Miles to km converter",
      "url": "https://hopi.co.uk/miles-to-km/",
      "category": "convert",
      "description": "Convert between miles and kilometres. Direction 'miles-to-km' takes miles and returns kilometres. Direction 'km-to-miles' takes kilometres and returns miles.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The distance value to convert"
          },
          "direction": {
            "type": "string",
            "enum": [
              "miles-to-km",
              "km-to-miles"
            ],
            "description": "Which way to convert"
          }
        },
        "required": [
          "value",
          "direction"
        ]
      }
    },
    {
      "name": "hopi_military_time_converter",
      "title": "Military time converter",
      "url": "https://hopi.co.uk/military-time-converter/",
      "category": "convert",
      "description": "Convert between 24-hour (military) time and 12-hour clock time. Direction '24h-to-12h' takes a 24-hour time like '1430' or '14:30'. Direction '12h-to-24h' takes a 12-hour time like '2:30' with a meridiem of am or pm (the meridiem can also be written in the time string).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "time": {
            "type": "string",
            "description": "The time to convert, e.g. '1430', '14:30', '2:30 pm'"
          },
          "direction": {
            "type": "string",
            "enum": [
              "24h-to-12h",
              "12h-to-24h"
            ],
            "description": "Which way to convert"
          },
          "meridiem": {
            "type": "string",
            "enum": [
              "am",
              "pm"
            ],
            "description": "am or pm for 12h-to-24h when not in the time string (default pm)"
          }
        },
        "required": [
          "time",
          "direction"
        ]
      }
    },
    {
      "name": "hopi_mpg_converter",
      "title": "MPG converter",
      "url": "https://hopi.co.uk/mpg-converter/",
      "category": "convert",
      "description": "Convert fuel economy between UK miles per gallon and litres per 100 km. Direction 'mpg-to-l100' takes UK mpg. Direction 'l100-to-mpg' takes litres per 100 km. Also returns US mpg, km per litre and miles per litre.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The fuel economy value (UK mpg or L/100km depending on direction)"
          },
          "direction": {
            "type": "string",
            "enum": [
              "mpg-to-l100",
              "l100-to-mpg"
            ],
            "description": "Which way to convert"
          }
        },
        "required": [
          "value",
          "direction"
        ]
      }
    },
    {
      "name": "hopi_number_to_words",
      "title": "Number to words converter",
      "url": "https://hopi.co.uk/number-to-words/",
      "category": "convert",
      "description": "Convert a number into written English words. Set currency to true to write it as UK pounds and pence (cheque style, ending 'only'). Supports up to 999,999,999,999 with decimals to two places.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "description": "The number to spell out, e.g. '1234.5' or '19.99'. May include commas."
          },
          "currency": {
            "type": "boolean",
            "description": "Write as UK pounds and pence (default false)"
          }
        },
        "required": [
          "value"
        ]
      }
    },
    {
      "name": "hopi_oven_temperature_converter",
      "title": "Oven temperature converter",
      "url": "https://hopi.co.uk/oven-temperature-converter/",
      "category": "convert",
      "description": "Convert an oven temperature. Scale 'c' is conventional Celsius, 'fan' is fan/convection Celsius, 'f' is Fahrenheit, 'gas' is UK gas mark (1 to 9). Returns conventional Celsius, fan Celsius, Fahrenheit and the nearest gas mark.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The temperature value (or gas mark 1 to 9 when scale is 'gas')"
          },
          "scale": {
            "type": "string",
            "enum": [
              "c",
              "fan",
              "f",
              "gas"
            ],
            "description": "The scale of the input value"
          }
        },
        "required": [
          "value",
          "scale"
        ]
      }
    },
    {
      "name": "hopi_power_converter",
      "title": "Power converter",
      "url": "https://hopi.co.uk/power-converter/",
      "category": "convert",
      "description": "Convert power from one unit to another. Units: w (watts), kw (kilowatts), hp (mechanical horsepower), ps (metric horsepower, PS).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The power value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "w",
              "kw",
              "hp",
              "ps"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "w",
              "kw",
              "hp",
              "ps"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_pressure_converter",
      "title": "Pressure converter",
      "url": "https://hopi.co.uk/pressure-converter/",
      "category": "convert",
      "description": "Convert pressure from one unit to another. Units: bar, psi (pounds per square inch), kpa (kilopascals), atm (atmospheres).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The pressure value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "bar",
              "psi",
              "kpa",
              "atm"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "bar",
              "psi",
              "kpa",
              "atm"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_ring_size_converter",
      "title": "Ring size converter",
      "url": "https://hopi.co.uk/ring-size-converter/",
      "category": "convert",
      "description": "Convert a ring size between UK, US and millimetre scales. Mode 'uk' takes a UK letter F to Z (add 1/2 for half sizes, e.g. 'N' or 'N 1/2'). Mode 'us' takes a US number 2.75 to 12.75. Mode 'mm' takes an inside circumference in mm (about 44 to 69). Returns UK size, US size, circumference and inside diameter.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "description": "The ring size to convert: a UK letter (uk mode), or a number (us or mm mode)"
          },
          "mode": {
            "type": "string",
            "enum": [
              "uk",
              "us",
              "mm"
            ],
            "description": "Which scale the value is in"
          }
        },
        "required": [
          "value",
          "mode"
        ]
      }
    },
    {
      "name": "hopi_shoe_size_converter",
      "title": "Shoe size converter",
      "url": "https://hopi.co.uk/shoe-size-converter/",
      "category": "convert",
      "description": "Convert a UK shoe size to approximate EU and US sizes. Set sex to 'men' (UK 5 to 13) or 'women' (UK 2 to 9). UK size must be in whole or half steps.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "ukSize": {
            "type": "number",
            "description": "UK shoe size (whole or half, e.g. 8 or 8.5)"
          },
          "sex": {
            "type": "string",
            "enum": [
              "men",
              "women"
            ],
            "description": "Which sizing chart to use"
          }
        },
        "required": [
          "ukSize",
          "sex"
        ]
      }
    },
    {
      "name": "hopi_speed_converter",
      "title": "Speed converter",
      "url": "https://hopi.co.uk/speed-converter/",
      "category": "convert",
      "description": "Convert a speed from one unit to another. Units: mph (miles per hour), kmh (kilometres per hour), ms (metres per second), kn (knots), mach (Mach, at 340.29 m/s).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The speed value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "mph",
              "kmh",
              "ms",
              "kn",
              "mach"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "mph",
              "kmh",
              "ms",
              "kn",
              "mach"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_volume_converter",
      "title": "Volume converter",
      "url": "https://hopi.co.uk/volume-converter/",
      "category": "convert",
      "description": "Convert a volume from one unit to another. Units: ml (millilitres), l (litres), ukpt (UK pints), ukgal (UK gallons), usgal (US gallons), ukfloz (UK fluid ounces), usfloz (US fluid ounces), m3 (cubic metres).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The volume value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "ml",
              "l",
              "ukpt",
              "ukgal",
              "usgal",
              "ukfloz",
              "usfloz",
              "m3"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "ml",
              "l",
              "ukpt",
              "ukgal",
              "usgal",
              "ukfloz",
              "usfloz",
              "m3"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_weight_converter",
      "title": "Weight converter",
      "url": "https://hopi.co.uk/weight-converter/",
      "category": "convert",
      "description": "Convert a weight from one unit to another. Units: g (grams), kg (kilograms), oz (ounces), lb (pounds), st (stone).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "The weight value to convert"
          },
          "from": {
            "type": "string",
            "enum": [
              "g",
              "kg",
              "oz",
              "lb",
              "st"
            ],
            "description": "Unit to convert from"
          },
          "to": {
            "type": "string",
            "enum": [
              "g",
              "kg",
              "oz",
              "lb",
              "st"
            ],
            "description": "Unit to convert to"
          }
        },
        "required": [
          "value",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_bitcoin_address_validator",
      "title": "Bitcoin address validator",
      "url": "https://hopi.co.uk/bitcoin-address-validator/",
      "category": "crypto",
      "description": "Check whether a Bitcoin address is valid by verifying its checksum and structure. Supports legacy Base58Check (P2PKH, P2SH) and Bech32/Bech32m SegWit and Taproot addresses, on mainnet and testnet. Does not query the blockchain or check balances.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "The Bitcoin address to validate"
          }
        },
        "required": [
          "address"
        ]
      }
    },
    {
      "name": "hopi_crypto_profit_calculator",
      "title": "Crypto profit calculator",
      "url": "https://hopi.co.uk/crypto-profit-calculator/",
      "category": "crypto",
      "description": "Work out profit or loss on a crypto trade from buy price, quantity and an optional per-side fee percentage. Returns breakeven price always, and profit, return percentage and total fees once a sell price is given. All figures are treated as GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "buy": {
            "type": "number",
            "description": "Buy price per unit"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity of coin traded"
          },
          "sell": {
            "type": "number",
            "description": "Sell price per unit (optional; omit to see breakeven only)"
          },
          "fee": {
            "type": "number",
            "description": "Fee percentage charged on each side (default 0, must be 0 to under 100)"
          }
        },
        "required": [
          "buy",
          "quantity"
        ]
      }
    },
    {
      "name": "hopi_dca_calculator",
      "title": "Crypto DCA calculator",
      "url": "https://hopi.co.uk/dca-calculator/",
      "category": "crypto",
      "description": "Work out the average cost basis across a series of pound-cost-averaged buys. Each buy is an amount of money spent and the price paid per unit. Returns total invested, coins acquired and average cost, plus current value and unrealised profit or loss if a current price is given. Figures are treated as GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "buys": {
            "type": "array",
            "description": "The list of buys",
            "items": {
              "type": "object",
              "properties": {
                "amount": {
                  "type": "number",
                  "description": "Money spent on this buy"
                },
                "price": {
                  "type": "number",
                  "description": "Price paid per unit on this buy"
                }
              },
              "required": [
                "amount",
                "price"
              ]
            }
          },
          "currentPrice": {
            "type": "number",
            "description": "Current price per unit (optional), to value the position now"
          }
        },
        "required": [
          "buys"
        ]
      }
    },
    {
      "name": "hopi_eth_address_checksum",
      "title": "Ethereum address checksum",
      "url": "https://hopi.co.uk/eth-address-checksum/",
      "category": "crypto",
      "description": "Validate an Ethereum address's EIP-55 capitalisation checksum and return the correctly checksummed form. Reports whether the input is already checksummed, lacks a checksum (all one case), or fails the checksum. Uses keccak-256 exactly as EIP-55 specifies.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "The Ethereum address, with or without a 0x prefix"
          }
        },
        "required": [
          "address"
        ]
      }
    },
    {
      "name": "hopi_eth_unit_converter",
      "title": "ETH unit converter",
      "url": "https://hopi.co.uk/eth-unit-converter/",
      "category": "crypto",
      "description": "Convert an amount given in wei, gwei or ETH into all three units, using exact 18-decimal integer maths (no floating point error). 1 ETH is 1e18 wei; 1 gwei is 1e9 wei.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "string",
            "description": "The amount to convert, as a plain number (string preferred to keep full precision), e.g. \"1.5\""
          },
          "unit": {
            "type": "string",
            "enum": [
              "wei",
              "gwei",
              "eth"
            ],
            "description": "The unit the amount is given in"
          }
        },
        "required": [
          "amount",
          "unit"
        ]
      }
    },
    {
      "name": "hopi_market_cap_calculator",
      "title": "Market cap calculator",
      "url": "https://hopi.co.uk/market-cap-calculator/",
      "category": "crypto",
      "description": "Calculate a coin's market cap (price times circulating supply) and fully diluted valuation, or work backwards to the price implied by a target market cap. Works in any currency; nothing is looked up.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "market_cap",
              "implied_price"
            ],
            "description": "market_cap: price times supply. implied_price: target cap divided by supply."
          },
          "price": {
            "type": "number",
            "description": "Current price per coin (for market_cap)"
          },
          "supply": {
            "type": "number",
            "description": "Circulating supply (for both modes)"
          },
          "maxSupply": {
            "type": "number",
            "description": "Maximum or total supply for FDV (optional, market_cap mode)"
          },
          "target": {
            "type": "number",
            "description": "Target market cap (for implied_price)"
          },
          "current": {
            "type": "number",
            "description": "Current price per coin, to show the multiple (optional, implied_price mode)"
          }
        },
        "required": [
          "mode",
          "supply"
        ]
      }
    },
    {
      "name": "hopi_position_size_calculator",
      "title": "Position size calculator",
      "url": "https://hopi.co.uk/position-size-calculator/",
      "category": "crypto",
      "description": "Work out how large a position to take so that hitting the stop-loss loses only a chosen percentage of the account. Enter account size, risk percentage, entry price and stop-loss price. Returns units to buy, position value, amount at risk and stop distance. Figures are treated as GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "account": {
            "type": "number",
            "description": "Total account size"
          },
          "risk": {
            "type": "number",
            "description": "Percentage of the account to risk on this trade (above 0, up to 100)"
          },
          "entry": {
            "type": "number",
            "description": "Entry price per unit"
          },
          "stop": {
            "type": "number",
            "description": "Stop-loss price per unit"
          }
        },
        "required": [
          "account",
          "risk",
          "entry",
          "stop"
        ]
      }
    },
    {
      "name": "hopi_satoshi_converter",
      "title": "Satoshi to BTC converter",
      "url": "https://hopi.co.uk/satoshi-converter/",
      "category": "crypto",
      "description": "Convert satoshis to BTC, mBTC and bits, or convert BTC to satoshis, mBTC and bits. Uses exact whole-satoshi integer maths. 1 BTC is 100,000,000 satoshis.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "sats_to_btc",
              "btc_to_sats"
            ],
            "description": "Direction of conversion"
          },
          "value": {
            "type": "string",
            "description": "The amount to convert: whole satoshis for sats_to_btc, or a BTC amount for btc_to_sats"
          }
        },
        "required": [
          "mode",
          "value"
        ]
      }
    },
    {
      "name": "hopi_staking_calculator",
      "title": "Staking rewards calculator",
      "url": "https://hopi.co.uk/staking-calculator/",
      "category": "crypto",
      "description": "Turn a quoted staking rate into a final balance and rewards earned. For an APR rate, choose daily or monthly compounding; for an APY rate, compounding is already included. Returns the final balance, rewards earned and the effective APY. Figures are treated as GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "principal": {
            "type": "number",
            "description": "Amount staked"
          },
          "rate": {
            "type": "number",
            "description": "Quoted rate as a percentage (0 to 1000)"
          },
          "years": {
            "type": "number",
            "description": "Term in years (above 0, up to 100)"
          },
          "rateType": {
            "type": "string",
            "enum": [
              "apr",
              "apy"
            ],
            "description": "Whether the rate is APR (needs compounding) or APY (default apr)"
          },
          "compounding": {
            "type": "string",
            "enum": [
              "daily",
              "monthly"
            ],
            "description": "Compounding frequency for APR (default daily)"
          }
        },
        "required": [
          "principal",
          "rate",
          "years"
        ]
      }
    },
    {
      "name": "hopi_add_working_days",
      "title": "Add working days",
      "url": "https://hopi.co.uk/add-working-days/",
      "category": "date",
      "description": "Add or subtract a number of working days (Monday to Friday) from a start date, optionally skipping England and Wales bank holidays. Dates use the YYYY-MM-DD format. Bank holiday data covers 2026 and 2027 only, so outside those years just weekends are skipped.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "description": "Start date in YYYY-MM-DD format"
          },
          "days": {
            "type": "integer",
            "description": "Number of working days to move (0 to 100000)"
          },
          "direction": {
            "type": "string",
            "enum": [
              "add",
              "sub"
            ],
            "description": "'add' to count forwards, 'sub' to count backwards (default 'add')"
          },
          "bankHolidays": {
            "type": "boolean",
            "description": "Also skip England and Wales bank holidays, not just weekends (default true)"
          }
        },
        "required": [
          "start",
          "days"
        ]
      }
    },
    {
      "name": "hopi_age_calculator",
      "title": "Age calculator",
      "url": "https://hopi.co.uk/age-calculator/",
      "category": "date",
      "description": "Work out an exact age from a date of birth, as of today or an optional 'as of' date. Dates use the YYYY-MM-DD format. Returns the age in years, months and days, the total days lived, and the next birthday.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "dob": {
            "type": "string",
            "description": "Date of birth in YYYY-MM-DD format"
          },
          "asOf": {
            "type": "string",
            "description": "Optional date to measure the age at, in YYYY-MM-DD format (defaults to today)"
          }
        },
        "required": [
          "dob"
        ]
      }
    },
    {
      "name": "hopi_cat_age_calculator",
      "title": "Cat age calculator",
      "url": "https://hopi.co.uk/cat-age-calculator/",
      "category": "date",
      "description": "Convert a cat's age in years to an approximate human age, using the standard 15, 24, then 4 a year chart. Returns the human-equivalent age and the cat's life stage.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "catAge": {
            "type": "number",
            "description": "The cat's age in years (0 to 40)"
          }
        },
        "required": [
          "catAge"
        ]
      }
    },
    {
      "name": "hopi_date_calculator",
      "title": "Date calculator",
      "url": "https://hopi.co.uk/date-calculator/",
      "category": "date",
      "description": "Add or subtract a number of days, weeks, months or years from a date. Dates use the YYYY-MM-DD format. Months and years are clamped to the last day of the target month where needed. Returns the resulting date.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Start date in YYYY-MM-DD format"
          },
          "amount": {
            "type": "integer",
            "description": "How many units to move (0 to 100000)"
          },
          "direction": {
            "type": "string",
            "enum": [
              "add",
              "subtract"
            ],
            "description": "'add' to move forwards, 'subtract' to move backwards (default 'add')"
          },
          "unit": {
            "type": "string",
            "enum": [
              "days",
              "weeks",
              "months",
              "years"
            ],
            "description": "Unit to move by (default 'days')"
          }
        },
        "required": [
          "date",
          "amount"
        ]
      }
    },
    {
      "name": "hopi_day_of_week_calculator",
      "title": "Day of the week finder",
      "url": "https://hopi.co.uk/day-of-week-calculator/",
      "category": "date",
      "description": "Find which day of the week a given date falls on. Dates use the YYYY-MM-DD format. Also reports which weekday that same day and month falls on in the current year.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "The date in YYYY-MM-DD format"
          }
        },
        "required": [
          "date"
        ]
      }
    },
    {
      "name": "hopi_days_between_dates",
      "title": "Days between dates calculator",
      "url": "https://hopi.co.uk/days-between-dates/",
      "category": "date",
      "description": "Count the number of days between two dates, with the total also shown in weeks and in weekdays (Monday to Friday). Dates use the YYYY-MM-DD format. Set inclusive to true to count both end days.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "Start date in YYYY-MM-DD format"
          },
          "to": {
            "type": "string",
            "description": "End date in YYYY-MM-DD format"
          },
          "inclusive": {
            "type": "boolean",
            "description": "Count both end days rather than excluding the end day (default false)"
          }
        },
        "required": [
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_days_until_christmas",
      "title": "Days until Christmas",
      "url": "https://hopi.co.uk/days-until-christmas/",
      "category": "date",
      "description": "Count the number of sleeps until the next Christmas Day (25 December). Uses today's date by default, or an optional 'from' date in YYYY-MM-DD format.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "Optional date to count from, in YYYY-MM-DD format (defaults to today)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_dog_age_calculator",
      "title": "Dog age calculator",
      "url": "https://hopi.co.uk/dog-age-calculator/",
      "category": "date",
      "description": "Convert a dog's age in years to an approximate human age, using the standard veterinary chart. The later rate depends on the dog's size: small, medium or large. Returns the human-equivalent age.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "dogAge": {
            "type": "number",
            "description": "The dog's age in years (0 to 30)"
          },
          "size": {
            "type": "string",
            "enum": [
              "small",
              "medium",
              "large"
            ],
            "description": "Dog size band (default 'medium')"
          }
        },
        "required": [
          "dogAge"
        ]
      }
    },
    {
      "name": "hopi_hours_calculator",
      "title": "Hours calculator",
      "url": "https://hopi.co.uk/hours-calculator/",
      "category": "date",
      "description": "Work out the hours worked between a start time and an end time, minus an optional unpaid break. Times use 24-hour HH:MM format. Handles overnight shifts where the end time is earlier than the start. Returns the worked time as hours and minutes and as decimal hours.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "description": "Start time in 24-hour HH:MM format, e.g. 09:00"
          },
          "end": {
            "type": "string",
            "description": "End time in 24-hour HH:MM format, e.g. 17:30"
          },
          "breakMinutes": {
            "type": "number",
            "description": "Unpaid break in minutes (default 0)"
          }
        },
        "required": [
          "start",
          "end"
        ]
      }
    },
    {
      "name": "hopi_leap_year_checker",
      "title": "Leap year checker",
      "url": "https://hopi.co.uk/leap-year-checker/",
      "category": "date",
      "description": "Check whether a year is a leap year, applying the divisible-by-4, century, and divisible-by-400 rules. Returns the verdict, the divisibility tests, and the next and previous leap years.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "year": {
            "type": "integer",
            "description": "The year to check (1 to 9999)"
          }
        },
        "required": [
          "year"
        ]
      }
    },
    {
      "name": "hopi_minutes_to_hours",
      "title": "Minutes to hours converter",
      "url": "https://hopi.co.uk/minutes-to-hours/",
      "category": "date",
      "description": "Convert a number of minutes into hours and minutes, or convert hours (plus optional extra minutes) into total minutes. Set mode to 'minutesToHours' or 'hoursToMinutes'. Returns a clock-style breakdown and decimal hours.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "minutesToHours",
              "hoursToMinutes"
            ],
            "description": "Direction of the conversion"
          },
          "minutes": {
            "type": "number",
            "description": "Minutes to convert (used when mode is 'minutesToHours', 0 to 10000000)"
          },
          "hours": {
            "type": "number",
            "description": "Hours to convert (used when mode is 'hoursToMinutes', 0 to 100000)"
          },
          "extraMinutes": {
            "type": "number",
            "description": "Extra minutes to add to the hours (used when mode is 'hoursToMinutes', default 0)"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_moon_phase_calculator",
      "title": "Moon phase calculator",
      "url": "https://hopi.co.uk/moon-phase-calculator/",
      "category": "date",
      "description": "Work out the moon phase for a date, based on the synodic month since a known new moon. Dates use the YYYY-MM-DD format and default to today. Returns the phase name, illuminated percentage, moon age in days, and the next full and new moons.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Optional date in YYYY-MM-DD format (defaults to today)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_star_sign_calculator",
      "title": "Star sign calculator",
      "url": "https://hopi.co.uk/star-sign-calculator/",
      "category": "date",
      "description": "Find the western zodiac star sign for a date of birth. Dates use the YYYY-MM-DD format (only the month and day matter). Returns the sign, its symbol, date range and element.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Date of birth in YYYY-MM-DD format"
          }
        },
        "required": [
          "date"
        ]
      }
    },
    {
      "name": "hopi_time_calculator",
      "title": "Time calculator",
      "url": "https://hopi.co.uk/time-calculator/",
      "category": "date",
      "description": "Add or subtract two durations, each given as hours and minutes. Returns the total as an H:MM clock value, as decimal hours, and as total minutes. Results can be negative when subtracting.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "hours1": {
            "type": "number",
            "description": "Hours of the first duration (default 0)"
          },
          "minutes1": {
            "type": "number",
            "description": "Minutes of the first duration (default 0)"
          },
          "hours2": {
            "type": "number",
            "description": "Hours of the second duration (default 0)"
          },
          "minutes2": {
            "type": "number",
            "description": "Minutes of the second duration (default 0)"
          },
          "operation": {
            "type": "string",
            "enum": [
              "add",
              "subtract"
            ],
            "description": "Add or subtract the second duration from the first (default 'add')"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_time_zone_converter",
      "title": "Time zone converter",
      "url": "https://hopi.co.uk/time-zone-converter/",
      "category": "date",
      "description": "Convert a wall-clock date and time from one time zone to another, using the browser's IANA time zone data (so daylight saving is handled). Date uses YYYY-MM-DD and time uses 24-hour HH:MM. Zones are IANA identifiers such as Europe/London or America/New_York. Returns the converted time, the day difference, and both UTC offsets.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "The date in the source zone, YYYY-MM-DD format"
          },
          "time": {
            "type": "string",
            "description": "The time in the source zone, 24-hour HH:MM format"
          },
          "fromZone": {
            "type": "string",
            "description": "Source IANA time zone, e.g. Europe/London",
            "enum": [
              "UTC",
              "Europe/London",
              "Europe/Paris",
              "Europe/Berlin",
              "Europe/Madrid",
              "Europe/Athens",
              "Europe/Moscow",
              "Asia/Dubai",
              "Asia/Kolkata",
              "Asia/Bangkok",
              "Asia/Singapore",
              "Asia/Hong_Kong",
              "Asia/Shanghai",
              "Asia/Tokyo",
              "Australia/Sydney",
              "Pacific/Auckland",
              "America/New_York",
              "America/Chicago",
              "America/Denver",
              "America/Los_Angeles",
              "America/Sao_Paulo"
            ]
          },
          "toZone": {
            "type": "string",
            "description": "Target IANA time zone, e.g. America/New_York",
            "enum": [
              "UTC",
              "Europe/London",
              "Europe/Paris",
              "Europe/Berlin",
              "Europe/Madrid",
              "Europe/Athens",
              "Europe/Moscow",
              "Asia/Dubai",
              "Asia/Kolkata",
              "Asia/Bangkok",
              "Asia/Singapore",
              "Asia/Hong_Kong",
              "Asia/Shanghai",
              "Asia/Tokyo",
              "Australia/Sydney",
              "Pacific/Auckland",
              "America/New_York",
              "America/Chicago",
              "America/Denver",
              "America/Los_Angeles",
              "America/Sao_Paulo"
            ]
          }
        },
        "required": [
          "date",
          "time",
          "fromZone",
          "toZone"
        ]
      }
    },
    {
      "name": "hopi_week_number",
      "title": "What week number is it?",
      "url": "https://hopi.co.uk/week-number/",
      "category": "date",
      "description": "Find the ISO 8601 week number for a date. Dates use the YYYY-MM-DD format and default to today. ISO weeks run Monday to Sunday and week 1 holds the year's first Thursday. Returns the week number, ISO year, and the Monday and Sunday of that week.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Optional date in YYYY-MM-DD format (defaults to today)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_working_days_calculator",
      "title": "Working days calculator",
      "url": "https://hopi.co.uk/working-days-calculator/",
      "category": "date",
      "description": "Count the working days (Monday to Friday) between two dates, inclusive of both ends, optionally excluding England and Wales bank holidays. Dates use the YYYY-MM-DD format. Bank holiday data covers 2026 and 2027 only, so outside those years just weekends are excluded.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "Start date in YYYY-MM-DD format"
          },
          "to": {
            "type": "string",
            "description": "End date in YYYY-MM-DD format"
          },
          "bankHolidays": {
            "type": "boolean",
            "description": "Exclude England and Wales bank holidays as well as weekends (default true)"
          }
        },
        "required": [
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_base64",
      "title": "Base64 encode & decode",
      "url": "https://hopi.co.uk/base64/",
      "category": "dev",
      "description": "Encode text to Base64, or decode a Base64 string back to text. UTF-8 safe, so accents and emoji survive the round trip. Returns the converted text or a clear error.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to encode, or the Base64 string to decode"
          },
          "mode": {
            "type": "string",
            "enum": [
              "encode",
              "decode"
            ],
            "description": "'encode' text to Base64, or 'decode' Base64 back to text"
          }
        },
        "required": [
          "text",
          "mode"
        ]
      }
    },
    {
      "name": "hopi_cron_expression_parser",
      "title": "Cron expression translator",
      "url": "https://hopi.co.uk/cron-expression-parser/",
      "category": "dev",
      "description": "Translate a standard five-field cron expression (minute, hour, day-of-month, month, day-of-week) into plain English. Understands stars, steps, ranges, lists and month and day names, plus shortcuts like @daily and @hourly.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "expression": {
            "type": "string",
            "description": "A five-field cron expression, for example '*/5 9-17 * * MON-FRI', or a shortcut like @daily"
          }
        },
        "required": [
          "expression"
        ]
      }
    },
    {
      "name": "hopi_css_minifier",
      "title": "CSS minifier",
      "url": "https://hopi.co.uk/css-minifier/",
      "category": "dev",
      "description": "Minify CSS by removing comments and needless whitespace, while preserving quoted strings and the spaces inside calc() expressions. Returns the minified CSS with before and after byte sizes.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "css": {
            "type": "string",
            "description": "The CSS source to minify"
          }
        },
        "required": [
          "css"
        ]
      }
    },
    {
      "name": "hopi_csv_to_json",
      "title": "CSV to JSON converter",
      "url": "https://hopi.co.uk/csv-to-json/",
      "category": "dev",
      "description": "Convert CSV text into a JSON array, following standard CSV quoting rules for embedded commas, quotes and line breaks. With headers on, the first row becomes object keys; with headers off, each row is an array of strings.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "csv": {
            "type": "string",
            "description": "The CSV text to convert"
          },
          "firstRowHeaders": {
            "type": "boolean",
            "description": "When true, the first row supplies the object keys; when false, every row becomes a plain array of strings (default true)"
          }
        },
        "required": [
          "csv"
        ]
      }
    },
    {
      "name": "hopi_diff_checker",
      "title": "Diff checker",
      "url": "https://hopi.co.uk/diff-checker/",
      "category": "dev",
      "description": "Compare two texts line by line using a longest common subsequence diff, and report which lines were added and which were removed. An edited line shows as one removed line plus one added line. Comparison is exact, including spaces and case.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "a": {
            "type": "string",
            "description": "The original (left) text"
          },
          "b": {
            "type": "string",
            "description": "The changed (right) text"
          }
        },
        "required": [
          "a",
          "b"
        ]
      }
    },
    {
      "name": "hopi_dummy_data_generator",
      "title": "Dummy data generator",
      "url": "https://hopi.co.uk/dummy-data-generator/",
      "category": "dev",
      "description": "Generate fake but safe UK test records. Phone numbers come from Ofcom's reserved drama ranges and emails use RFC 2606 example domains, so no record can reach a real person. Returns an array of records, plus CSV text.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many records to generate, from 1 to 1000"
          },
          "fields": {
            "type": "array",
            "description": "Which fields to include (default all). Choose from firstName, lastName, fullName, email, ukMobile, ukLandline, streetAddress, town, postcode, dateOfBirth, company",
            "items": {
              "type": "string",
              "enum": [
                "firstName",
                "lastName",
                "fullName",
                "email",
                "ukMobile",
                "ukLandline",
                "streetAddress",
                "town",
                "postcode",
                "dateOfBirth",
                "company"
              ]
            }
          }
        },
        "required": [
          "count"
        ]
      }
    },
    {
      "name": "hopi_email_link_generator",
      "title": "Email link generator",
      "url": "https://hopi.co.uk/email-link-generator/",
      "category": "dev",
      "description": "Build a correctly percent-encoded mailto link from to, cc, bcc, subject and body fields, plus a ready to paste HTML anchor snippet. Spaces are encoded as %20 and line breaks as %0D%0A, as the mailto standard expects.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "description": "One or more recipient addresses, separated by commas or semicolons"
          },
          "cc": {
            "type": "string",
            "description": "Optional cc addresses, separated by commas or semicolons"
          },
          "bcc": {
            "type": "string",
            "description": "Optional bcc addresses, separated by commas or semicolons"
          },
          "subject": {
            "type": "string",
            "description": "Optional subject line"
          },
          "body": {
            "type": "string",
            "description": "Optional body text; line breaks are preserved"
          },
          "linkText": {
            "type": "string",
            "description": "Optional visible text for the HTML anchor (default 'Email us')"
          }
        },
        "required": [
          "to"
        ]
      }
    },
    {
      "name": "hopi_hash_generator",
      "title": "Hash generator",
      "url": "https://hopi.co.uk/hash-generator/",
      "category": "dev",
      "description": "Compute the SHA-256, SHA-1 or SHA-512 hash of a piece of text and return the hex digest. Uses the browser WebCrypto API. SHA-1 is included for compatibility with older systems only and should not be used for anything new.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to hash"
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "SHA-256",
              "SHA-1",
              "SHA-512"
            ],
            "description": "Hash algorithm (default SHA-256)"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_html_escape",
      "title": "HTML escape & unescape",
      "url": "https://hopi.co.uk/html-escape/",
      "category": "dev",
      "description": "Escape the five special HTML characters (& < > \" ') into entities so text is safe to place in HTML, or unescape named and numeric HTML entities back into plain characters.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to escape, or the HTML with entities to unescape"
          },
          "mode": {
            "type": "string",
            "enum": [
              "escape",
              "unescape"
            ],
            "description": "'escape' text to entities, or 'unescape' entities back to text"
          }
        },
        "required": [
          "text",
          "mode"
        ]
      }
    },
    {
      "name": "hopi_http_status_codes",
      "title": "HTTP status code reference",
      "url": "https://hopi.co.uk/http-status-codes/",
      "category": "dev",
      "description": "Look up a standard HTTP status code by number and get its name, meaning and class (1xx to 5xx), or search all standard codes by a word in the number, name or description.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "integer",
            "description": "An HTTP status code to look up, for example 404"
          },
          "query": {
            "type": "string",
            "description": "A word to search for across code numbers, names and descriptions"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_json_formatter",
      "title": "JSON formatter",
      "url": "https://hopi.co.uk/json-formatter/",
      "category": "dev",
      "description": "Pretty print, minify or validate JSON. Formatting and minifying only change whitespace; key order, values and structure stay exactly as they were. Returns the output text or a clear parse error.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "json": {
            "type": "string",
            "description": "The JSON text to process"
          },
          "mode": {
            "type": "string",
            "enum": [
              "format",
              "minify",
              "validate"
            ],
            "description": "'format' to pretty print, 'minify' to strip whitespace, 'validate' to only check validity (default format)"
          },
          "indent": {
            "type": "integer",
            "description": "Number of spaces per indent level when formatting (default 2)"
          }
        },
        "required": [
          "json"
        ]
      }
    },
    {
      "name": "hopi_json_to_csv",
      "title": "JSON to CSV converter",
      "url": "https://hopi.co.uk/json-to-csv/",
      "category": "dev",
      "description": "Convert a JSON array of objects into CSV. The union of all keys becomes the header row in first-seen order, missing keys become empty cells, and nested objects or arrays are written back as compact JSON in the cell. Output follows RFC 4180 quoting.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "json": {
            "type": "string",
            "description": "A JSON array of objects to convert"
          }
        },
        "required": [
          "json"
        ]
      }
    },
    {
      "name": "hopi_jwt_decoder",
      "title": "JWT decoder",
      "url": "https://hopi.co.uk/jwt-decoder/",
      "category": "dev",
      "description": "Decode a JSON Web Token's header and payload from base64url. The signature is never verified, so a decoded claim proves nothing on its own. Reports the algorithm, the exp, iat and nbf time claims, and whether the token is expired. A leading Bearer prefix and whitespace are handled.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "The JWT to decode, optionally with a leading 'Bearer ' prefix"
          }
        },
        "required": [
          "token"
        ]
      }
    },
    {
      "name": "hopi_markdown_previewer",
      "title": "Markdown previewer",
      "url": "https://hopi.co.uk/markdown-previewer/",
      "category": "dev",
      "description": "Render a small, safe subset of markdown to HTML: headings (# to ###), bold, italic, links (http, https or mailto only), inline code, fenced code blocks, bulleted and numbered lists, and blockquotes. Every character is HTML-escaped first, so raw HTML is shown as text and never executed.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "markdown": {
            "type": "string",
            "description": "The markdown source to render"
          }
        },
        "required": [
          "markdown"
        ]
      }
    },
    {
      "name": "hopi_meta_tag_generator",
      "title": "Meta tag generator",
      "url": "https://hopi.co.uk/meta-tag-generator/",
      "category": "dev",
      "description": "Build a complete HTML head snippet from page details: title, meta description, canonical link, Open Graph and Twitter card tags. Returns the ready-to-paste snippet plus character counts.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Page title (guideline is around 60 characters)"
          },
          "description": {
            "type": "string",
            "description": "Meta description (guideline is around 155 characters)"
          },
          "canonical": {
            "type": "string",
            "description": "Canonical URL for the page"
          },
          "ogTitle": {
            "type": "string",
            "description": "Open Graph title (defaults to title if omitted)"
          },
          "ogDescription": {
            "type": "string",
            "description": "Open Graph description (defaults to description if omitted)"
          },
          "ogImage": {
            "type": "string",
            "description": "Open Graph image URL"
          },
          "ogType": {
            "type": "string",
            "description": "Open Graph type (default 'website')",
            "enum": [
              "website",
              "article",
              "product",
              "profile"
            ]
          },
          "twitterCard": {
            "type": "string",
            "description": "Twitter card type (default 'summary_large_image')",
            "enum": [
              "summary",
              "summary_large_image",
              "app",
              "player"
            ]
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_number_base_converter",
      "title": "Number base converter",
      "url": "https://hopi.co.uk/number-base-converter/",
      "category": "dev",
      "description": "Convert a whole number from one base to another between binary, octal, decimal and hexadecimal. Uses BigInt so values of any size convert exactly. Returns the value in the requested base plus all four bases.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "description": "The number to convert, as text (optional 0b/0o/0x prefix, spaces and underscores ignored, may be negative)"
          },
          "fromBase": {
            "type": "string",
            "description": "The base the value is written in",
            "enum": [
              "binary",
              "octal",
              "decimal",
              "hex"
            ]
          },
          "toBase": {
            "type": "string",
            "description": "The base to convert to",
            "enum": [
              "binary",
              "octal",
              "decimal",
              "hex"
            ]
          }
        },
        "required": [
          "value",
          "fromBase",
          "toBase"
        ]
      }
    },
    {
      "name": "hopi_password_strength_checker",
      "title": "Password strength checker",
      "url": "https://hopi.co.uk/password-strength-checker/",
      "category": "dev",
      "description": "Estimate how strong a password is: an entropy estimate in bits, a rough offline crack time (assuming ten billion guesses a second), a 0 to 4 score with a verdict, and warnings about weak patterns such as dictionary words, sequences and repeats.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "password": {
            "type": "string",
            "description": "The password to assess (never uploaded; assessed locally)"
          }
        },
        "required": [
          "password"
        ]
      }
    },
    {
      "name": "hopi_regex_tester",
      "title": "Regex tester",
      "url": "https://hopi.co.uk/regex-tester/",
      "category": "dev",
      "description": "Test a JavaScript regular expression against some text and get every match with its position. Supports the g, i and m flags. Returns up to 1000 matches.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "pattern": {
            "type": "string",
            "description": "The regular expression source (without slashes)"
          },
          "text": {
            "type": "string",
            "description": "The text to run the pattern against"
          },
          "flags": {
            "type": "string",
            "description": "Any of g (global), i (ignore case), m (multiline). Default 'g'."
          }
        },
        "required": [
          "pattern",
          "text"
        ]
      }
    },
    {
      "name": "hopi_robots_txt_generator",
      "title": "Robots.txt generator",
      "url": "https://hopi.co.uk/robots-txt-generator/",
      "category": "dev",
      "description": "Build a robots.txt file from allow and disallow rules grouped by user agent, with an optional sitemap line. You can pass a preset ('allow' all, 'block' all, 'wordpress') or your own rules array.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "preset": {
            "type": "string",
            "description": "Use a ready-made rule set instead of custom rules",
            "enum": [
              "allow",
              "block",
              "wordpress",
              "custom"
            ]
          },
          "rules": {
            "type": "array",
            "description": "Custom rules, each an object with agent, directive and path",
            "items": {
              "type": "object",
              "properties": {
                "agent": {
                  "type": "string",
                  "description": "User agent, default '*' for all crawlers"
                },
                "directive": {
                  "type": "string",
                  "description": "'allow' or 'disallow' (default disallow)",
                  "enum": [
                    "allow",
                    "disallow"
                  ]
                },
                "path": {
                  "type": "string",
                  "description": "Path such as /private/ (blank disallow means allow everything)"
                }
              }
            }
          },
          "sitemap": {
            "type": "string",
            "description": "Optional sitemap URL for the Sitemap line"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_schema_markup_generator",
      "title": "Schema markup generator",
      "url": "https://hopi.co.uk/schema-markup-generator/",
      "category": "dev",
      "description": "Build valid JSON-LD structured data using schema.org. Supports FAQ pages, articles, local businesses and breadcrumb lists. Returns the JSON-LD object and a ready-to-paste script snippet.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "The schema type to build",
            "enum": [
              "faq",
              "article",
              "local",
              "breadcrumb"
            ]
          },
          "faqs": {
            "type": "array",
            "description": "For type 'faq': questions and answers",
            "items": {
              "type": "object",
              "properties": {
                "q": {
                  "type": "string",
                  "description": "Question"
                },
                "a": {
                  "type": "string",
                  "description": "Answer"
                }
              }
            }
          },
          "headline": {
            "type": "string",
            "description": "For type 'article': the headline"
          },
          "author": {
            "type": "string",
            "description": "For type 'article': author name"
          },
          "published": {
            "type": "string",
            "description": "For type 'article': date published"
          },
          "modified": {
            "type": "string",
            "description": "For type 'article': date modified"
          },
          "name": {
            "type": "string",
            "description": "For type 'local': business name"
          },
          "street": {
            "type": "string",
            "description": "For type 'local': street address"
          },
          "town": {
            "type": "string",
            "description": "For type 'local': town or locality"
          },
          "postcode": {
            "type": "string",
            "description": "For type 'local': postal code"
          },
          "phone": {
            "type": "string",
            "description": "For type 'local': telephone"
          },
          "url": {
            "type": "string",
            "description": "For type 'local': website URL"
          },
          "hours": {
            "type": "string",
            "description": "For type 'local': opening hours"
          },
          "items": {
            "type": "array",
            "description": "For type 'breadcrumb': ordered pages",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Page name"
                },
                "url": {
                  "type": "string",
                  "description": "Page URL"
                }
              }
            }
          }
        },
        "required": [
          "type"
        ]
      }
    },
    {
      "name": "hopi_seo_analyzer",
      "title": "SEO meta tag analyser",
      "url": "https://hopi.co.uk/seo-analyzer/",
      "category": "dev",
      "description": "Analyse a page's raw HTML and report on its title, meta description, headings, canonical, robots meta, language, Open Graph, Twitter card, viewport, image alt text and word count. Returns a list of pass, check and fail results.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "html": {
            "type": "string",
            "description": "The full HTML source of the page to analyse"
          }
        },
        "required": [
          "html"
        ]
      }
    },
    {
      "name": "hopi_slug_generator",
      "title": "Slug generator",
      "url": "https://hopi.co.uk/slug-generator/",
      "category": "dev",
      "description": "Turn any title or text into a clean URL slug: lowercase, accents stripped, and every run of spaces, punctuation and symbols collapsed to a single hyphen, with hyphens trimmed from the ends.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The title or text to slugify"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_sql_formatter",
      "title": "SQL formatter",
      "url": "https://hopi.co.uk/sql-formatter/",
      "category": "dev",
      "description": "Format a SQL query: uppercase the keywords, put each clause on its own line and indent conditions, while leaving quoted strings, identifiers, numbers and comments untouched. Only whitespace and keyword case change.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sql": {
            "type": "string",
            "description": "The SQL query to format"
          }
        },
        "required": [
          "sql"
        ]
      }
    },
    {
      "name": "hopi_unix_timestamp_converter",
      "title": "Unix timestamp converter",
      "url": "https://hopi.co.uk/unix-timestamp-converter/",
      "category": "dev",
      "description": "Convert between Unix epoch timestamps and readable dates. Pass a timestamp to get the UTC and local date (seconds or milliseconds detected automatically), or pass a date (and optional time, interpreted in local time) to get the timestamp in seconds and milliseconds.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "description": "A Unix timestamp in seconds or milliseconds (may be negative). Provide this to convert a timestamp to a date."
          },
          "date": {
            "type": "string",
            "description": "A date as YYYY-MM-DD. Provide this to convert a date to a timestamp."
          },
          "time": {
            "type": "string",
            "description": "Optional time as HH:MM:SS to accompany 'date' (default 00:00:00), in local time."
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_url_encoder",
      "title": "URL encode & decode",
      "url": "https://hopi.co.uk/url-encoder/",
      "category": "dev",
      "description": "Percent-encode or decode text for URLs. Component mode encodes every reserved character (right for a single query value); whole-URL mode leaves structural characters like / ? & alone (right for a complete address).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text or URL to encode or decode"
          },
          "action": {
            "type": "string",
            "description": "Whether to encode or decode (default 'encode')",
            "enum": [
              "encode",
              "decode"
            ]
          },
          "mode": {
            "type": "string",
            "description": "'component' for a single value, 'uri' for a whole URL (default 'component')",
            "enum": [
              "component",
              "uri"
            ]
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_url_parser",
      "title": "URL parser",
      "url": "https://hopi.co.uk/url-parser/",
      "category": "dev",
      "description": "Parse a URL into its parts: protocol, host, port, path, fragment, origin and every decoded query parameter. If no scheme is given, https:// is assumed for a bare domain.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The URL to parse"
          }
        },
        "required": [
          "url"
        ]
      }
    },
    {
      "name": "hopi_utm_link_generator",
      "title": "UTM link generator",
      "url": "https://hopi.co.uk/utm-link-generator/",
      "category": "dev",
      "description": "Add UTM campaign parameters (utm_source, utm_medium, utm_campaign, utm_term, utm_content) to a URL without breaking existing query parameters. Warns on mixed case and notes any missing core parameters. Only http and https URLs are accepted.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The base URL to tag (https:// assumed if no scheme given)"
          },
          "utm_source": {
            "type": "string",
            "description": "Where the traffic comes from, e.g. newsletter"
          },
          "utm_medium": {
            "type": "string",
            "description": "The marketing medium, e.g. email"
          },
          "utm_campaign": {
            "type": "string",
            "description": "The campaign name"
          },
          "utm_term": {
            "type": "string",
            "description": "Paid keyword term (optional)"
          },
          "utm_content": {
            "type": "string",
            "description": "Content variant, e.g. button vs text link (optional)"
          }
        },
        "required": [
          "url"
        ]
      }
    },
    {
      "name": "hopi_uuid_generator",
      "title": "UUID generator",
      "url": "https://hopi.co.uk/uuid-generator/",
      "category": "dev",
      "description": "Generate 1 to 100 random version 4 UUIDs using the browser's cryptographically secure random source (crypto.randomUUID, falling back to crypto.getRandomValues). Never uses Math.random.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many UUIDs to generate, 1 to 100 (default 1)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_xml_formatter",
      "title": "XML formatter",
      "url": "https://hopi.co.uk/xml-formatter/",
      "category": "dev",
      "description": "Pretty print or minify XML. Element names, attributes, values and structure are preserved; only whitespace between elements changes. Invalid XML returns a clear parse error.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "xml": {
            "type": "string",
            "description": "The XML to format"
          },
          "action": {
            "type": "string",
            "description": "'format' to pretty print or 'minify' (default 'format')",
            "enum": [
              "format",
              "minify"
            ]
          },
          "indent": {
            "type": "integer",
            "description": "Spaces per level when pretty printing (default 2)"
          }
        },
        "required": [
          "xml"
        ]
      }
    },
    {
      "name": "hopi_ics_generator",
      "title": "Add to calendar file generator",
      "url": "https://hopi.co.uk/ics-generator/",
      "category": "files",
      "description": "Build a .ics (iCalendar, RFC 5545) calendar file for a single event and return the file text. Give a title, startDate and endDate as 'YYYY-MM-DD'. For timed events give startTime and endTime as 'HH:MM' (24-hour, read in the caller's local time zone and stored as UTC); set allDay true for an all-day event instead. Location and description are optional. Returns the .ics text ready to save.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Event title (SUMMARY)"
          },
          "startDate": {
            "type": "string",
            "description": "Start date, ISO 'YYYY-MM-DD'"
          },
          "endDate": {
            "type": "string",
            "description": "End date, ISO 'YYYY-MM-DD'. Defaults to startDate"
          },
          "allDay": {
            "type": "boolean",
            "description": "True for an all-day event (no times). Default false"
          },
          "startTime": {
            "type": "string",
            "description": "Start time 'HH:MM' 24-hour, timed events only. Default '00:00'"
          },
          "endTime": {
            "type": "string",
            "description": "End time 'HH:MM' 24-hour, timed events only. Defaults to startTime"
          },
          "location": {
            "type": "string",
            "description": "Optional location"
          },
          "description": {
            "type": "string",
            "description": "Optional description"
          }
        },
        "required": [
          "title",
          "startDate"
        ]
      }
    },
    {
      "name": "hopi_alcohol_unit_calculator",
      "title": "Alcohol unit calculator",
      "url": "https://hopi.co.uk/alcohol-unit-calculator/",
      "category": "health",
      "description": "Work out UK alcohol units in a drink from its ABV (percentage) and volume (millilitres), using units = ABV x ml / 1000. Optionally give the number of those drinks per week to get a weekly total compared against the NHS low risk guideline of 14 units a week.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "abv": {
            "type": "number",
            "description": "Alcohol by volume as a percentage, e.g. 12 for 12% wine"
          },
          "ml": {
            "type": "number",
            "description": "Volume of the drink in millilitres, e.g. 175 for a medium glass of wine"
          },
          "drinksPerWeek": {
            "type": "number",
            "description": "Optional number of these drinks per week, to work out a weekly units total"
          }
        },
        "required": [
          "abv",
          "ml"
        ]
      }
    },
    {
      "name": "hopi_bmi_calculator",
      "title": "BMI calculator",
      "url": "https://hopi.co.uk/bmi-calculator/",
      "category": "health",
      "description": "Work out body mass index (BMI) from height and weight, with the NHS weight category. Use units 'metric' with heightCm and weightKg, or 'imperial' with heightInches and weightPounds. BMI = weight in kg / (height in metres squared).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "units": {
            "type": "string",
            "enum": [
              "metric",
              "imperial"
            ],
            "description": "'metric' (cm and kg) or 'imperial' (inches and pounds)"
          },
          "heightCm": {
            "type": "number",
            "description": "Height in centimetres (metric)"
          },
          "weightKg": {
            "type": "number",
            "description": "Weight in kilograms (metric)"
          },
          "heightInches": {
            "type": "number",
            "description": "Total height in inches (imperial)"
          },
          "weightPounds": {
            "type": "number",
            "description": "Weight in pounds (imperial)"
          }
        },
        "required": [
          "units"
        ]
      }
    },
    {
      "name": "hopi_body_fat_calculator",
      "title": "Body fat percentage calculator",
      "url": "https://hopi.co.uk/body-fat-calculator/",
      "category": "health",
      "description": "Estimate body fat percentage using the US Navy tape method from a few measurements. For males give height, neck and waist; for females give height, neck, waist and hip. Use units 'metric' (centimetres) or 'imperial' (inches). Optionally give weight (kg for metric, pounds for imperial) to also get fat mass and lean mass in kilograms.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sex": {
            "type": "string",
            "enum": [
              "male",
              "female"
            ],
            "description": "Biological sex, determines the formula and whether hip is needed"
          },
          "units": {
            "type": "string",
            "enum": [
              "metric",
              "imperial"
            ],
            "description": "'metric' (cm) or 'imperial' (inches)"
          },
          "height": {
            "type": "number",
            "description": "Height (cm if metric, inches if imperial)"
          },
          "neck": {
            "type": "number",
            "description": "Neck circumference (cm if metric, inches if imperial)"
          },
          "waist": {
            "type": "number",
            "description": "Waist circumference (cm if metric, inches if imperial)"
          },
          "hip": {
            "type": "number",
            "description": "Hip circumference, females only (cm if metric, inches if imperial)"
          },
          "weight": {
            "type": "number",
            "description": "Optional weight (kg if metric, pounds if imperial) for fat and lean mass"
          }
        },
        "required": [
          "sex",
          "units",
          "height",
          "neck",
          "waist"
        ]
      }
    },
    {
      "name": "hopi_calories_to_kj",
      "title": "Calories to kJ converter",
      "url": "https://hopi.co.uk/calories-to-kj/",
      "category": "health",
      "description": "Convert food energy between kilocalories (kcal) and kilojoules (kJ) using the exact factor 1 kcal = 4.184 kJ. Give an amount and its unit ('kcal' or 'kj'); returns both values.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "The energy amount to convert"
          },
          "unit": {
            "type": "string",
            "enum": [
              "kcal",
              "kj"
            ],
            "description": "The unit of the amount: 'kcal' (kilocalories) or 'kj' (kilojoules)"
          }
        },
        "required": [
          "amount",
          "unit"
        ]
      }
    },
    {
      "name": "hopi_due_date_calculator",
      "title": "Pregnancy due date calculator",
      "url": "https://hopi.co.uk/due-date-calculator/",
      "category": "health",
      "description": "Estimate a pregnancy due date from the first day of the last menstrual period (LMP) and cycle length. Method: adjust the LMP by (cycle - 28) days, then add 280 days for the due date. Also returns the dates the second and third trimesters begin (LMP-adjusted + 84 and + 182 days). Dates are ISO 'YYYY-MM-DD'.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lmp": {
            "type": "string",
            "description": "First day of the last menstrual period, ISO date 'YYYY-MM-DD'"
          },
          "cycleLength": {
            "type": "integer",
            "description": "Cycle length in days, 20 to 45 (default 28)"
          }
        },
        "required": [
          "lmp"
        ]
      }
    },
    {
      "name": "hopi_heart_rate_zones",
      "title": "Heart rate zone calculator",
      "url": "https://hopi.co.uk/heart-rate-zones/",
      "category": "health",
      "description": "Estimate maximum heart rate and five training zones (bpm) from age. Max HR = 220 - age. Method 'max' uses percentages of max HR (50-60, 60-70, 70-80, 80-90, 90-100%). Method 'karvonen' uses heart rate reserve and needs restingHeartRate: zone = (maxHR - resting) x intensity + resting.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "age": {
            "type": "number",
            "description": "Age in years"
          },
          "method": {
            "type": "string",
            "enum": [
              "max",
              "karvonen"
            ],
            "description": "'max' (percentage of max HR) or 'karvonen' (heart rate reserve). Default 'max'"
          },
          "restingHeartRate": {
            "type": "number",
            "description": "Resting heart rate in bpm, required for the Karvonen method"
          }
        },
        "required": [
          "age"
        ]
      }
    },
    {
      "name": "hopi_running_pace_calculator",
      "title": "Running pace calculator",
      "url": "https://hopi.co.uk/running-pace-calculator/",
      "category": "health",
      "description": "Work out running pace, finish time or distance, in kilometres or miles. Mode 'pace' needs distance and timeSeconds; mode 'time' needs distance and paceSeconds (seconds per unit); mode 'distance' needs timeSeconds and paceSeconds. Distance is in the chosen unit. Returns pace per km and per mile, speed in km/h and mph, distance and total time.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "pace",
              "time",
              "distance"
            ],
            "description": "Which value to solve for"
          },
          "unit": {
            "type": "string",
            "enum": [
              "km",
              "mi"
            ],
            "description": "Unit for distance and the given pace. Default 'km'"
          },
          "distance": {
            "type": "number",
            "description": "Distance in the chosen unit (needed for 'pace' and 'time' modes)"
          },
          "timeSeconds": {
            "type": "number",
            "description": "Total time in seconds (needed for 'pace' and 'distance' modes)"
          },
          "paceSeconds": {
            "type": "number",
            "description": "Pace in seconds per unit (needed for 'time' and 'distance' modes)"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_sleep_calculator",
      "title": "Sleep cycle calculator",
      "url": "https://hopi.co.uk/sleep-calculator/",
      "category": "health",
      "description": "Suggest sleep times using 90-minute cycles plus 15 minutes to fall asleep. Mode 'wake' takes a wake time and returns the best bedtimes (wake - 15 - cycles x 90 minutes). Mode 'bedtime' takes a bedtime and returns the best wake times (bedtime + 15 + cycles x 90 minutes). Both return options for 6, 5, 4 and 3 cycles. Times are 'HH:MM' 24-hour.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "wake",
              "bedtime"
            ],
            "description": "'wake' to find bedtimes from a wake time, or 'bedtime' to find wake times from a bedtime"
          },
          "time": {
            "type": "string",
            "description": "The known time as 'HH:MM' (24-hour): the wake time for mode 'wake', or the bedtime for mode 'bedtime'"
          }
        },
        "required": [
          "mode",
          "time"
        ]
      }
    },
    {
      "name": "hopi_tdee_calculator",
      "title": "TDEE & calorie calculator",
      "url": "https://hopi.co.uk/tdee-calculator/",
      "category": "health",
      "description": "Estimate daily calories (TDEE) and BMR using the Mifflin-St Jeor equation. BMR = 10 x kg + 6.25 x cm - 5 x age + (5 for male, -161 for female). TDEE = BMR x activity factor (sedentary 1.2, light 1.375, moderate 1.55, active 1.725, very_active 1.9). Use units 'metric' (heightCm, weightKg) or 'imperial' (heightInches, weightPounds). Also returns mild-loss (-250), loss (-500) and gain (+500) calorie goals.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sex": {
            "type": "string",
            "enum": [
              "male",
              "female"
            ],
            "description": "Biological sex"
          },
          "age": {
            "type": "number",
            "description": "Age in years"
          },
          "units": {
            "type": "string",
            "enum": [
              "metric",
              "imperial"
            ],
            "description": "'metric' (cm, kg) or 'imperial' (inches, pounds)"
          },
          "heightCm": {
            "type": "number",
            "description": "Height in centimetres (metric)"
          },
          "weightKg": {
            "type": "number",
            "description": "Weight in kilograms (metric)"
          },
          "heightInches": {
            "type": "number",
            "description": "Total height in inches (imperial)"
          },
          "weightPounds": {
            "type": "number",
            "description": "Weight in pounds (imperial)"
          },
          "activity": {
            "type": "string",
            "enum": [
              "sedentary",
              "light",
              "moderate",
              "active",
              "very_active"
            ],
            "description": "Activity level, default 'moderate'"
          }
        },
        "required": [
          "sex",
          "age",
          "units"
        ]
      }
    },
    {
      "name": "hopi_water_intake_calculator",
      "title": "Daily water intake calculator",
      "url": "https://hopi.co.uk/water-intake-calculator/",
      "category": "health",
      "description": "Estimate a rough daily fluid target from body weight, using 30 to 35 ml per kg, plus an activity add (sedentary 0, light 250, moderate 500, active 750, very_active 1000 ml) and 500 ml more for hot conditions. Use units 'metric' (weightKg) or 'imperial' (weightStone and weightPounds). Returns a low-to-high range in litres, millilitres and 250 ml glasses.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "units": {
            "type": "string",
            "enum": [
              "metric",
              "imperial"
            ],
            "description": "'metric' (kg) or 'imperial' (stone and pounds)"
          },
          "weightKg": {
            "type": "number",
            "description": "Weight in kilograms (metric)"
          },
          "weightStone": {
            "type": "number",
            "description": "Whole stone part of weight (imperial)"
          },
          "weightPounds": {
            "type": "number",
            "description": "Pounds part of weight (imperial)"
          },
          "activity": {
            "type": "string",
            "enum": [
              "sedentary",
              "light",
              "moderate",
              "active",
              "very_active"
            ],
            "description": "Activity level, default 'sedentary'"
          },
          "hot": {
            "type": "boolean",
            "description": "Add 500 ml for hot conditions. Default false"
          }
        },
        "required": [
          "units"
        ]
      }
    },
    {
      "name": "hopi_average_calculator",
      "title": "Mean, median & mode calculator",
      "url": "https://hopi.co.uk/average-calculator/",
      "category": "maths",
      "description": "Work out the mean, median, mode, sum, count, minimum and maximum of a list of numbers. Provide the numbers separated by spaces, commas, semicolons or new lines (type 1200 rather than 1,200, as commas are treated as separators).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "numbers": {
            "type": "string",
            "description": "A list of numbers separated by spaces, commas, semicolons or new lines"
          }
        },
        "required": [
          "numbers"
        ]
      }
    },
    {
      "name": "hopi_discount_calculator",
      "title": "Discount & sale price calculator",
      "url": "https://hopi.co.uk/discount-calculator/",
      "category": "maths",
      "description": "Work out a discount and sale price. Mode 'pct': a percentage off a price. Mode 'fixed': a fixed pound amount off a price. Mode 'find': the discount percentage from an original price and a final price. All money figures are in pounds.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "pct",
              "fixed",
              "find"
            ],
            "description": "'pct' percentage off, 'fixed' pound amount off, or 'find' the discount from two prices"
          },
          "price": {
            "type": "number",
            "description": "The original price (used in all modes)"
          },
          "percentOff": {
            "type": "number",
            "description": "Discount percentage (mode 'pct' only)"
          },
          "amountOff": {
            "type": "number",
            "description": "Fixed pound amount off (mode 'fixed' only)"
          },
          "finalPrice": {
            "type": "number",
            "description": "The final price paid (mode 'find' only)"
          }
        },
        "required": [
          "mode",
          "price"
        ]
      }
    },
    {
      "name": "hopi_fraction_calculator",
      "title": "Fraction calculator",
      "url": "https://hopi.co.uk/fraction-calculator/",
      "category": "maths",
      "description": "Add, subtract, multiply or divide two fractions, giving the simplified result, a mixed number where relevant, and the decimal value. Each fraction is a numerator over a denominator, all whole numbers (numerators may be negative).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "op": {
            "type": "string",
            "enum": [
              "add",
              "sub",
              "mul",
              "div"
            ],
            "description": "Operation: add, sub (subtract), mul (multiply) or div (divide)"
          },
          "n1": {
            "type": "integer",
            "description": "First numerator"
          },
          "d1": {
            "type": "integer",
            "description": "First denominator (not zero)"
          },
          "n2": {
            "type": "integer",
            "description": "Second numerator"
          },
          "d2": {
            "type": "integer",
            "description": "Second denominator (not zero)"
          }
        },
        "required": [
          "op",
          "n1",
          "d1",
          "n2",
          "d2"
        ]
      }
    },
    {
      "name": "hopi_fraction_to_decimal",
      "title": "Fraction to decimal converter",
      "url": "https://hopi.co.uk/fraction-to-decimal/",
      "category": "maths",
      "description": "Convert between fractions and decimals. Mode 'toDecimal': give a numerator and denominator (whole numbers) to get the decimal and percentage. Mode 'toFraction': give a decimal to get the closest simplified fraction (denominator up to 10,000), noting whether it is exact.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "toDecimal",
              "toFraction"
            ],
            "description": "'toDecimal' from a fraction, or 'toFraction' from a decimal"
          },
          "numerator": {
            "type": "integer",
            "description": "Numerator (mode 'toDecimal')"
          },
          "denominator": {
            "type": "integer",
            "description": "Denominator, not zero (mode 'toDecimal')"
          },
          "decimal": {
            "type": "number",
            "description": "The decimal to convert (mode 'toFraction')"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_percentage_calculator",
      "title": "Percentage calculator",
      "url": "https://hopi.co.uk/percentage-calculator/",
      "category": "maths",
      "description": "Work out percentages three ways. Mode 'of': what is P percent of a number. Mode 'what': what percentage the part is of the whole. Mode 'change': the percentage change from a starting value to an end value.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "of",
              "what",
              "change"
            ],
            "description": "'of' percent of a number, 'what' one number as a percentage of another, or 'change' percentage change"
          },
          "percent": {
            "type": "number",
            "description": "The percentage (mode 'of')"
          },
          "number": {
            "type": "number",
            "description": "The number (mode 'of')"
          },
          "part": {
            "type": "number",
            "description": "The part (mode 'what')"
          },
          "whole": {
            "type": "number",
            "description": "The whole (mode 'what', not zero)"
          },
          "from": {
            "type": "number",
            "description": "Starting value (mode 'change', not zero)"
          },
          "to": {
            "type": "number",
            "description": "End value (mode 'change')"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_percentage_change_calculator",
      "title": "Percentage change calculator",
      "url": "https://hopi.co.uk/percentage-change-calculator/",
      "category": "maths",
      "description": "Work out the percentage change from a starting value to an end value, using the starting value as the base. A positive result is an increase, a negative result is a decrease.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "from": {
            "type": "number",
            "description": "The starting value (not zero)"
          },
          "to": {
            "type": "number",
            "description": "The end value"
          }
        },
        "required": [
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_percentage_decrease_calculator",
      "title": "Percentage decrease calculator",
      "url": "https://hopi.co.uk/percentage-decrease-calculator/",
      "category": "maths",
      "description": "Decrease a number by a percentage and see the new value and the amount taken off. For example, 250 decreased by 15 percent.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "number": {
            "type": "number",
            "description": "The starting number"
          },
          "percent": {
            "type": "number",
            "description": "The percentage to take off"
          }
        },
        "required": [
          "number",
          "percent"
        ]
      }
    },
    {
      "name": "hopi_percentage_difference_calculator",
      "title": "Percentage difference calculator",
      "url": "https://hopi.co.uk/percentage-difference-calculator/",
      "category": "maths",
      "description": "Work out the percentage difference between two values using the average-based formula: the absolute gap divided by the average of the two, times 100. The result is symmetric, so the order of the two values does not matter.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "a": {
            "type": "number",
            "description": "The first value"
          },
          "b": {
            "type": "number",
            "description": "The second value"
          }
        },
        "required": [
          "a",
          "b"
        ]
      }
    },
    {
      "name": "hopi_percentage_increase_calculator",
      "title": "Percentage increase calculator",
      "url": "https://hopi.co.uk/percentage-increase-calculator/",
      "category": "maths",
      "description": "Increase a number by a percentage and see the new value and the amount added. For example, 250 increased by 15 percent.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "number": {
            "type": "number",
            "description": "The starting number"
          },
          "percent": {
            "type": "number",
            "description": "The percentage to add on"
          }
        },
        "required": [
          "number",
          "percent"
        ]
      }
    },
    {
      "name": "hopi_prime_factorisation_calculator",
      "title": "Prime number & factor calculator",
      "url": "https://hopi.co.uk/prime-factorisation-calculator/",
      "category": "maths",
      "description": "Check whether a whole number (2 to 1,000,000,000,000,000) is prime, break it into its prime factors in power form, count its divisors, and list them. Uses trial division.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "number": {
            "type": "integer",
            "description": "A whole number from 2 to 1,000,000,000,000,000"
          }
        },
        "required": [
          "number"
        ]
      }
    },
    {
      "name": "hopi_ratio_calculator",
      "title": "Ratio calculator",
      "url": "https://hopi.co.uk/ratio-calculator/",
      "category": "maths",
      "description": "Work with ratios. Mode 'simplify': reduce a ratio a : b to its lowest terms, and give the 1 : n form and the decimal a / b. Mode 'solve': find the missing value x in the equivalent ratio a : b = c : x using cross multiplication. All inputs must be positive.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "simplify",
              "solve"
            ],
            "description": "'simplify' a ratio, or 'solve' for the missing value"
          },
          "a": {
            "type": "number",
            "description": "First term of the ratio (positive)"
          },
          "b": {
            "type": "number",
            "description": "Second term of the ratio (positive)"
          },
          "c": {
            "type": "number",
            "description": "Known term of the equivalent ratio, mode 'solve' (a : b = c : x)"
          }
        },
        "required": [
          "mode",
          "a",
          "b"
        ]
      }
    },
    {
      "name": "hopi_roman_numerals_converter",
      "title": "Roman numerals converter",
      "url": "https://hopi.co.uk/roman-numerals-converter/",
      "category": "maths",
      "description": "Convert between numbers and Roman numerals, both directions, for whole numbers from 1 to 3999. Give a number (e.g. 2026) to get its numeral, or a Roman numeral (e.g. MMXXVI) to get the number. The direction is detected automatically from the input.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "description": "A whole number from 1 to 3999, or a Roman numeral using I, V, X, L, C, D and M"
          }
        },
        "required": [
          "value"
        ]
      }
    },
    {
      "name": "hopi_rounding_calculator",
      "title": "Rounding & significant figures calculator",
      "url": "https://hopi.co.uk/rounding-calculator/",
      "category": "maths",
      "description": "Round a number to a chosen number of decimal places or significant figures, with halves always rounded up (away from zero). Mode 'dp': decimal places, 0 to 12. Mode 'sf': significant figures, 1 to 15.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "number": {
            "type": "number",
            "description": "The number to round"
          },
          "mode": {
            "type": "string",
            "enum": [
              "dp",
              "sf"
            ],
            "description": "'dp' for decimal places, or 'sf' for significant figures"
          },
          "count": {
            "type": "integer",
            "description": "How many decimal places (0 to 12) or significant figures (1 to 15)"
          }
        },
        "required": [
          "number",
          "mode",
          "count"
        ]
      }
    },
    {
      "name": "hopi_scientific_calculator",
      "title": "Scientific calculator",
      "url": "https://hopi.co.uk/scientific-calculator/",
      "category": "maths",
      "description": "Evaluate a maths expression following the standard order of operations (BODMAS). Supports + - * / ^ (power), ! (factorial), % (as divide by 100), brackets, the constants pi and e, and the functions sin, cos, tan, asin, acos, atan, ln, log (base 10) and sqrt. Set angleMode to 'deg' (default) or 'rad' for trigonometry.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "expression": {
            "type": "string",
            "description": "The maths expression, e.g. '2 + 3 * 4', 'sin(30)', 'sqrt(2)^2', '5!'"
          },
          "angleMode": {
            "type": "string",
            "enum": [
              "deg",
              "rad"
            ],
            "description": "Angle units for trigonometry: 'deg' (default) or 'rad'"
          }
        },
        "required": [
          "expression"
        ]
      }
    },
    {
      "name": "hopi_standard_deviation_calculator",
      "title": "Standard deviation calculator",
      "url": "https://hopi.co.uk/standard-deviation-calculator/",
      "category": "maths",
      "description": "Work out the sample and population standard deviation, sample and population variance, mean and count from a list of numbers. Provide the numbers separated by spaces, commas, semicolons or new lines. Sample figures need at least two values.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "numbers": {
            "type": "string",
            "description": "A list of numbers separated by spaces, commas, semicolons or new lines"
          }
        },
        "required": [
          "numbers"
        ]
      }
    },
    {
      "name": "hopi_triangle_calculator",
      "title": "Right-angle triangle calculator",
      "url": "https://hopi.co.uk/triangle-calculator/",
      "category": "maths",
      "description": "Solve a right-angle triangle from any two given values, at least one of which must be a side. Sides: a (opposite), b (adjacent), c (hypotenuse). angleA is angle A in degrees, between 0 and 90 (the third angle is the 90 degree right angle). Returns all three sides, both non-right angles, the area and the perimeter.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "a": {
            "type": "number",
            "description": "Side a, the opposite (greater than 0)"
          },
          "b": {
            "type": "number",
            "description": "Side b, the adjacent (greater than 0)"
          },
          "c": {
            "type": "number",
            "description": "Side c, the hypotenuse (greater than 0, must be the longest side)"
          },
          "angleA": {
            "type": "number",
            "description": "Angle A in degrees, strictly between 0 and 90"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_bill_splitter",
      "title": "Bill splitter",
      "url": "https://hopi.co.uk/bill-splitter/",
      "category": "money",
      "description": "Split a restaurant bill between people. In 'itemised' mode, list each item with its amount and who shared it, then add an optional tip and service charge (both percentages applied to each person's own share). In 'even' mode, split one total evenly with an optional tip. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "itemised",
              "even"
            ],
            "description": "'itemised' splits by item and who had it; 'even' splits one total equally"
          },
          "people": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Itemised mode: names of the people sharing the bill"
          },
          "items": {
            "type": "array",
            "description": "Itemised mode: each item with its amount and the names who shared it. An item with no names is shared by everyone.",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Item name"
                },
                "amount": {
                  "type": "number",
                  "description": "Item cost in GBP"
                },
                "assigned": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Names sharing this item; omit or empty for everyone"
                }
              },
              "required": [
                "amount"
              ]
            }
          },
          "tipPercent": {
            "type": "number",
            "description": "Tip as a percentage (default 0)"
          },
          "servicePercent": {
            "type": "number",
            "description": "Itemised mode: service charge as a percentage (default 0)"
          },
          "total": {
            "type": "number",
            "description": "Even mode: the bill total before tip"
          },
          "peopleCount": {
            "type": "integer",
            "description": "Even mode: number of people to split between"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_cagr_calculator",
      "title": "CAGR calculator",
      "url": "https://hopi.co.uk/cagr-calculator/",
      "category": "money",
      "description": "Work out the compound annual growth rate (CAGR) that takes a starting value to an ending value over a number of years. Returns the annual rate, the total growth and the growth multiple.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "start": {
            "type": "number",
            "description": "Starting value (must be greater than zero)"
          },
          "end": {
            "type": "number",
            "description": "Ending value"
          },
          "years": {
            "type": "number",
            "description": "Number of years over the period (may be a fraction)"
          }
        },
        "required": [
          "start",
          "end",
          "years"
        ]
      }
    },
    {
      "name": "hopi_compound_interest_calculator",
      "title": "Compound interest calculator",
      "url": "https://hopi.co.uk/compound-interest-calculator/",
      "category": "money",
      "description": "Project savings growth from a starting deposit plus a regular monthly contribution, compounded monthly with contributions added at the end of each month. Returns the final balance, total paid in and interest earned. Amounts in GBP, rate is the annual rate as a percentage.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "principal": {
            "type": "number",
            "description": "Starting deposit in GBP (default 0)"
          },
          "monthly": {
            "type": "number",
            "description": "Monthly contribution in GBP (default 0)"
          },
          "rate": {
            "type": "number",
            "description": "Annual interest rate as a percentage"
          },
          "years": {
            "type": "number",
            "description": "Term in years (1 to 100)"
          }
        },
        "required": [
          "rate",
          "years"
        ]
      }
    },
    {
      "name": "hopi_currency_converter",
      "title": "Currency converter",
      "url": "https://hopi.co.uk/currency-converter/",
      "category": "money",
      "description": "Convert an amount of money from one currency to another using Hopi's live mid-market exchange rates (updated hourly, 150+ currencies). Use ISO 4217 codes such as GBP, EUR, USD, JPY.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "The amount to convert"
          },
          "from": {
            "type": "string",
            "description": "Currency to convert from, ISO 4217 code e.g. GBP"
          },
          "to": {
            "type": "string",
            "description": "Currency to convert to, ISO 4217 code e.g. EUR"
          }
        },
        "required": [
          "amount",
          "from",
          "to"
        ]
      }
    },
    {
      "name": "hopi_day_rate_calculator",
      "title": "Day rate to salary calculator",
      "url": "https://hopi.co.uk/day-rate-calculator/",
      "category": "money",
      "description": "Convert between a contractor day rate and an annual salary equivalent using a chosen number of billable working days per year (default 220). Mode 'to_salary' turns a day rate into yearly, monthly and weekly figures; mode 'to_rate' turns a salary into a day rate. Gross amounts in GBP, before tax.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "to_salary",
              "to_rate"
            ],
            "description": "'to_salary' from a day rate, or 'to_rate' from a salary"
          },
          "dayRate": {
            "type": "number",
            "description": "Day rate in GBP (required for to_salary)"
          },
          "salary": {
            "type": "number",
            "description": "Annual salary in GBP (required for to_rate)"
          },
          "workingDays": {
            "type": "number",
            "description": "Billable working days per year, 1 to 365 (default 220)"
          }
        },
        "required": [
          "mode"
        ]
      }
    },
    {
      "name": "hopi_energy_cost_calculator",
      "title": "Energy running cost calculator",
      "url": "https://hopi.co.uk/energy-cost-calculator/",
      "category": "money",
      "description": "Work out the running cost of an electrical appliance from its power in watts, hours used per day and your electricity unit price in pence per kWh. Returns daily, weekly, monthly and yearly cost plus kWh used. Costs in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "watts": {
            "type": "number",
            "description": "Appliance power draw in watts (0 to 100000)"
          },
          "hoursPerDay": {
            "type": "number",
            "description": "Hours used per day (0 to 24)"
          },
          "pencePerKwh": {
            "type": "number",
            "description": "Electricity unit price in pence per kWh"
          }
        },
        "required": [
          "watts",
          "hoursPerDay",
          "pencePerKwh"
        ]
      }
    },
    {
      "name": "hopi_fuel_cost_calculator",
      "title": "Fuel cost calculator",
      "url": "https://hopi.co.uk/fuel-cost-calculator/",
      "category": "money",
      "description": "Estimate the fuel cost of a journey from the distance in miles, the car's fuel economy in miles per gallon (UK gallon) and the pump price in pence per litre. Optionally double it for a return trip and split between passengers. Returns total cost, litres used and cost per person. Costs in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "miles": {
            "type": "number",
            "description": "One-way distance in miles"
          },
          "mpg": {
            "type": "number",
            "description": "Fuel economy in miles per UK gallon"
          },
          "pencePerLitre": {
            "type": "number",
            "description": "Pump price in pence per litre"
          },
          "returnTrip": {
            "type": "boolean",
            "description": "Double the distance for a return journey (default false)"
          },
          "people": {
            "type": "integer",
            "description": "Number of people to split the cost between (default 1)"
          }
        },
        "required": [
          "miles",
          "mpg",
          "pencePerLitre"
        ]
      }
    },
    {
      "name": "hopi_holiday_entitlement_calculator",
      "title": "Holiday entitlement calculator",
      "url": "https://hopi.co.uk/holiday-entitlement-calculator/",
      "category": "money",
      "description": "Work out UK statutory paid holiday entitlement from the number of days worked per week, using 5.6 weeks a year capped at the statutory 28 days. Optionally scale to a part-year by the number of months worked. Returns entitlement in days and weeks.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "daysPerWeek": {
            "type": "number",
            "description": "Days worked per week (1 to 7)"
          },
          "months": {
            "type": "number",
            "description": "Months of the year worked (1 to 12, default 12)"
          }
        },
        "required": [
          "daysPerWeek"
        ]
      }
    },
    {
      "name": "hopi_hourly_to_salary",
      "title": "Hourly wage to salary converter",
      "url": "https://hopi.co.uk/hourly-to-salary/",
      "category": "money",
      "description": "Convert between an hourly pay rate and an annual salary based on hours worked per week (52 weeks a year). Mode 'to_salary' turns an hourly rate into annual, monthly and weekly pay; mode 'to_hourly' turns a salary into an hourly rate. Gross amounts in GBP, before tax.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "to_salary",
              "to_hourly"
            ],
            "description": "'to_salary' from an hourly rate, or 'to_hourly' from a salary"
          },
          "hourlyRate": {
            "type": "number",
            "description": "Hourly pay rate in GBP (required for to_salary)"
          },
          "salary": {
            "type": "number",
            "description": "Annual salary in GBP (required for to_hourly)"
          },
          "hoursPerWeek": {
            "type": "number",
            "description": "Hours worked per week (greater than 0, up to 168)"
          }
        },
        "required": [
          "mode",
          "hoursPerWeek"
        ]
      }
    },
    {
      "name": "hopi_inflation_calculator",
      "title": "UK inflation calculator",
      "url": "https://hopi.co.uk/inflation-calculator/",
      "category": "money",
      "description": "Adjust a money amount for UK inflation. Mode 'cpi' uses ONS CPI annual averages (2015 = 100) between two years from 1988 to 2025 and returns the adjusted value, total change and average annual rate. Mode 'custom' compounds a chosen annual inflation rate over a number of years. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "cpi",
              "custom"
            ],
            "description": "'cpi' uses the ONS CPI index between two years; 'custom' uses your own rate"
          },
          "amount": {
            "type": "number",
            "description": "The money amount to adjust"
          },
          "fromYear": {
            "type": "integer",
            "description": "CPI mode: starting year (1988 to 2025)"
          },
          "toYear": {
            "type": "integer",
            "description": "CPI mode: ending year (1988 to 2025, default 2025)"
          },
          "ratePercent": {
            "type": "number",
            "description": "Custom mode: annual inflation rate as a percentage (-50 to 100)"
          },
          "years": {
            "type": "number",
            "description": "Custom mode: number of years (0 to 200)"
          }
        },
        "required": [
          "mode",
          "amount"
        ]
      }
    },
    {
      "name": "hopi_loan_calculator",
      "title": "Loan repayment calculator",
      "url": "https://hopi.co.uk/loan-calculator/",
      "category": "money",
      "description": "Work out the monthly repayment on a loan from the amount borrowed, the annual interest rate and the term in years, using the standard amortising formula. Returns the monthly payment, total repaid and total interest. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "Amount borrowed in GBP (greater than zero)"
          },
          "rate": {
            "type": "number",
            "description": "Annual interest rate (APR) as a percentage (0 to 100)"
          },
          "years": {
            "type": "number",
            "description": "Loan term in years (greater than 0, up to 30)"
          }
        },
        "required": [
          "amount",
          "rate",
          "years"
        ]
      }
    },
    {
      "name": "hopi_margin_calculator",
      "title": "Margin & markup calculator",
      "url": "https://hopi.co.uk/margin-calculator/",
      "category": "money",
      "description": "Work out profit, gross margin and markup from a cost price and a selling price. Margin is profit as a percentage of the selling price; markup is profit as a percentage of the cost. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "cost": {
            "type": "number",
            "description": "Cost price in GBP"
          },
          "price": {
            "type": "number",
            "description": "Selling price in GBP"
          }
        },
        "required": [
          "cost",
          "price"
        ]
      }
    },
    {
      "name": "hopi_mortgage_calculator",
      "title": "Mortgage repayment calculator",
      "url": "https://hopi.co.uk/mortgage-calculator/",
      "category": "money",
      "description": "Work out the monthly payment on a repayment mortgage at a constant interest rate, using the standard amortising formula. Returns the monthly payment, total repaid and total interest. Fees and rate changes are not included. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "Amount borrowed in GBP (greater than zero)"
          },
          "rate": {
            "type": "number",
            "description": "Annual interest rate as a percentage (0 to 50)"
          },
          "years": {
            "type": "number",
            "description": "Mortgage term in years (greater than 0, up to 50)"
          }
        },
        "required": [
          "amount",
          "rate",
          "years"
        ]
      }
    },
    {
      "name": "hopi_mortgage_overpayment_calculator",
      "title": "Mortgage overpayment calculator",
      "url": "https://hopi.co.uk/mortgage-overpayment-calculator/",
      "category": "money",
      "description": "See how much time and interest a regular monthly overpayment saves on a repayment mortgage. Give the current balance, annual rate, remaining term in years and the extra amount paid each month. Returns the time saved, interest saved, new payoff time and the monthly payment. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "number",
            "description": "Current mortgage balance in GBP (greater than zero)"
          },
          "rate": {
            "type": "number",
            "description": "Annual interest rate as a percentage (0 to 50)"
          },
          "years": {
            "type": "number",
            "description": "Remaining term in years (greater than 0, up to 50)"
          },
          "extra": {
            "type": "number",
            "description": "Extra monthly overpayment in GBP (0 or more)"
          }
        },
        "required": [
          "balance",
          "rate",
          "years",
          "extra"
        ]
      }
    },
    {
      "name": "hopi_national_insurance_calculator",
      "title": "National Insurance calculator",
      "url": "https://hopi.co.uk/national-insurance-calculator/",
      "category": "money",
      "description": "Work out UK employee Class 1 National Insurance for the 2026/27 tax year from an annual gross salary. Uses the primary threshold of £12,570, upper earnings limit of £50,270, 8% between them and 2% above. Returns NI due per year, month and week plus the effective rate. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "salary": {
            "type": "number",
            "description": "Annual gross salary in GBP"
          }
        },
        "required": [
          "salary"
        ]
      }
    },
    {
      "name": "hopi_net_to_gross",
      "title": "Net to gross salary calculator",
      "url": "https://hopi.co.uk/net-to-gross/",
      "category": "money",
      "description": "Work out the gross salary needed to achieve a desired take-home (net) pay for the 2026/27 tax year in England, Wales and Northern Ireland, using code 1257L income tax bands with personal allowance taper and employee National Insurance. Give the net figure as yearly or monthly. Returns the required gross, tax and NI. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "net": {
            "type": "number",
            "description": "Desired take-home pay in GBP"
          },
          "period": {
            "type": "string",
            "enum": [
              "year",
              "month"
            ],
            "description": "Whether the net figure is yearly or monthly (default year)"
          }
        },
        "required": [
          "net"
        ]
      }
    },
    {
      "name": "hopi_overtime_pay_calculator",
      "title": "Overtime pay calculator",
      "url": "https://hopi.co.uk/overtime-pay-calculator/",
      "category": "money",
      "description": "Work out gross overtime pay from a base hourly rate and hours worked at three multipliers: standard (1x), time and a half (1.5x) and double time (2x). At least one hours figure is required. Returns pay at each rate, the total and total hours. Gross pay in GBP, before tax and NI.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "rate": {
            "type": "number",
            "description": "Base hourly rate in GBP"
          },
          "standardHours": {
            "type": "number",
            "description": "Hours paid at the standard rate (default 0)"
          },
          "timeAndHalfHours": {
            "type": "number",
            "description": "Hours paid at time and a half, 1.5x (default 0)"
          },
          "doubleHours": {
            "type": "number",
            "description": "Hours paid at double time, 2x (default 0)"
          }
        },
        "required": [
          "rate"
        ]
      }
    },
    {
      "name": "hopi_pro_rata_salary_calculator",
      "title": "Pro-rata salary calculator",
      "url": "https://hopi.co.uk/pro-rata-salary-calculator/",
      "category": "money",
      "description": "Work out a pro rata salary for part-time hours by scaling a full-time salary by the ratio of your hours to full-time hours. Returns the pro rata yearly, monthly and weekly pay and the fraction of full-time. Amounts in GBP, gross before tax.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "fullTimeSalary": {
            "type": "number",
            "description": "Full-time annual salary in GBP (greater than zero)"
          },
          "fullTimeHours": {
            "type": "number",
            "description": "Full-time hours per week (greater than zero)"
          },
          "hours": {
            "type": "number",
            "description": "Your hours per week (greater than zero)"
          }
        },
        "required": [
          "fullTimeSalary",
          "fullTimeHours",
          "hours"
        ]
      }
    },
    {
      "name": "hopi_redundancy_pay_calculator",
      "title": "Redundancy pay calculator",
      "url": "https://hopi.co.uk/redundancy-pay-calculator/",
      "category": "money",
      "description": "Work out UK statutory redundancy pay for redundancies on or after 6 April 2026, using the gov.uk count-back method: for each full year of service (up to 20), 1.5 weeks if worked aged 41+, 1 week aged 22 to 40, and 0.5 weeks under 22. Weekly pay is capped at £751 and the total at £22,530. At least 2 full years of service are needed. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "age": {
            "type": "integer",
            "description": "Age at redundancy (15 to 100)"
          },
          "years": {
            "type": "integer",
            "description": "Full years of continuous service (0 to 60, cannot exceed age)"
          },
          "weeklyPay": {
            "type": "number",
            "description": "Gross weekly pay in GBP"
          }
        },
        "required": [
          "age",
          "years",
          "weeklyPay"
        ]
      }
    },
    {
      "name": "hopi_savings_goal_calculator",
      "title": "Savings goal calculator",
      "url": "https://hopi.co.uk/savings-goal-calculator/",
      "category": "money",
      "description": "Plan a savings goal, compounded monthly. Mode 'time' works out how long a monthly deposit takes to reach a target. Mode 'monthly' works out the monthly saving needed to reach a target within a number of years. Both take an optional starting balance and an annual interest rate. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "time",
              "monthly"
            ],
            "description": "'time' finds the time to reach the goal; 'monthly' finds the monthly saving needed"
          },
          "target": {
            "type": "number",
            "description": "Savings target in GBP (greater than zero)"
          },
          "start": {
            "type": "number",
            "description": "Starting balance in GBP (default 0)"
          },
          "rate": {
            "type": "number",
            "description": "Annual interest rate as a percentage"
          },
          "monthly": {
            "type": "number",
            "description": "Time mode: monthly deposit in GBP"
          },
          "years": {
            "type": "number",
            "description": "Monthly mode: number of years to reach the goal"
          }
        },
        "required": [
          "mode",
          "target",
          "rate"
        ]
      }
    },
    {
      "name": "hopi_stamp_duty_calculator",
      "title": "Stamp duty calculator",
      "url": "https://hopi.co.uk/stamp-duty-calculator/",
      "category": "money",
      "description": "Work out Stamp Duty Land Tax (SDLT) on a property purchase in England and Northern Ireland. Buyer types: 'ftb' first-time buyer (relief up to £500,000, standard rates above), 'home' moving home (main residence), 'additional' second home or buy-to-let (higher rates, only from £40,000). Returns the tax due and the effective rate. Amounts in GBP. Scotland (LBTT) and Wales (LTT) have their own rates.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "price": {
            "type": "number",
            "description": "Property purchase price in GBP"
          },
          "buyer": {
            "type": "string",
            "enum": [
              "ftb",
              "home",
              "additional"
            ],
            "description": "'ftb' first-time buyer, 'home' moving home, 'additional' second home or buy-to-let"
          }
        },
        "required": [
          "price",
          "buyer"
        ]
      }
    },
    {
      "name": "hopi_student_loan_calculator",
      "title": "Student loan repayment calculator",
      "url": "https://hopi.co.uk/student-loan-calculator/",
      "category": "money",
      "description": "Work out UK student loan repayments from an annual salary using 2026/27 thresholds. Plans: 'p1' Plan 1 (9% above £26,900), 'p2' Plan 2 (9% above £29,385), 'p4' Plan 4 (9% above £33,795), 'p5' Plan 5 (9% above £25,000), 'pg' Postgraduate Loan (6% above £21,000). An undergraduate plan can optionally add a Postgraduate Loan on top. Returns yearly and monthly repayments. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "salary": {
            "type": "number",
            "description": "Annual salary in GBP"
          },
          "plan": {
            "type": "string",
            "enum": [
              "p1",
              "p2",
              "p4",
              "p5",
              "pg"
            ],
            "description": "Repayment plan"
          },
          "addPostgraduate": {
            "type": "boolean",
            "description": "Add a Postgraduate Loan on top of an undergraduate plan (ignored when plan is pg; default false)"
          }
        },
        "required": [
          "salary",
          "plan"
        ]
      }
    },
    {
      "name": "hopi_take_home_pay_calculator",
      "title": "Take-home pay calculator",
      "url": "https://hopi.co.uk/take-home-pay-calculator/",
      "category": "money",
      "description": "Work out UK take-home pay from an annual gross salary for the 2026/27 tax year in England, Wales and Northern Ireland, using code 1257L income tax bands (20/40/45%) with personal allowance taper above £100,000, plus employee National Insurance. Returns net pay per year, month and week, and the tax and NI deducted. Amounts in GBP.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "salary": {
            "type": "number",
            "description": "Annual gross salary in GBP"
          }
        },
        "required": [
          "salary"
        ]
      }
    },
    {
      "name": "hopi_tip_calculator",
      "title": "Tip calculator",
      "url": "https://hopi.co.uk/tip-calculator/",
      "category": "money",
      "description": "Work out a tip on a bill and optionally split the total between people. Returns the tip amount, the total, and the amount per person.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "bill": {
            "type": "number",
            "description": "The bill amount before tip"
          },
          "tipPercent": {
            "type": "number",
            "description": "Tip as a percentage (default 12.5)"
          },
          "split": {
            "type": "integer",
            "description": "Number of people to split between (default 1)"
          }
        },
        "required": [
          "bill"
        ]
      }
    },
    {
      "name": "hopi_ucas_points_calculator",
      "title": "UCAS points calculator",
      "url": "https://hopi.co.uk/ucas-points-calculator/",
      "category": "money",
      "description": "Add up UCAS tariff points from A-level grades using the current tariff: A* 56, A 48, B 40, C 32, D 24, E 16. Give the number of grades at each level. Returns the total points and the number of grades counted.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "aStar": {
            "type": "integer",
            "description": "Number of A* grades (0 to 20)"
          },
          "a": {
            "type": "integer",
            "description": "Number of A grades (0 to 20)"
          },
          "b": {
            "type": "integer",
            "description": "Number of B grades (0 to 20)"
          },
          "c": {
            "type": "integer",
            "description": "Number of C grades (0 to 20)"
          },
          "d": {
            "type": "integer",
            "description": "Number of D grades (0 to 20)"
          },
          "e": {
            "type": "integer",
            "description": "Number of E grades (0 to 20)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_unit_price_calculator",
      "title": "Unit price comparison",
      "url": "https://hopi.co.uk/unit-price-calculator/",
      "category": "money",
      "description": "Compare the unit price of two or more items to find the best value. Each item has a price in GBP, a quantity and a unit ('g', 'kg', 'ml', 'l' or 'each'). Weights are compared per kg, volumes per litre, and counts each. Returns the unit price of every item and which is cheapest.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "description": "The items to compare (at least two)",
            "items": {
              "type": "object",
              "properties": {
                "price": {
                  "type": "number",
                  "description": "Price in GBP"
                },
                "quantity": {
                  "type": "number",
                  "description": "Quantity in the chosen unit (greater than zero)"
                },
                "unit": {
                  "type": "string",
                  "enum": [
                    "g",
                    "kg",
                    "ml",
                    "l",
                    "each"
                  ],
                  "description": "Unit of the quantity"
                }
              },
              "required": [
                "price",
                "quantity",
                "unit"
              ]
            }
          }
        },
        "required": [
          "items"
        ]
      }
    },
    {
      "name": "hopi_vat_calculator",
      "title": "VAT calculator",
      "url": "https://hopi.co.uk/vat-calculator/",
      "category": "money",
      "description": "Add UK VAT to a net amount, or remove VAT from a gross (VAT-inclusive) amount. Default rate is the UK standard 20 percent. Returns the net, VAT and gross figures.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "The money amount"
          },
          "mode": {
            "type": "string",
            "enum": [
              "add",
              "remove"
            ],
            "description": "'add' VAT to a net amount, or 'remove' VAT from a gross amount"
          },
          "rate": {
            "type": "number",
            "description": "VAT rate as a percentage (default 20)"
          }
        },
        "required": [
          "amount",
          "mode"
        ]
      }
    },
    {
      "name": "hopi_bingo_card_generator",
      "title": "Bingo card generator",
      "url": "https://hopi.co.uk/bingo-card-generator/",
      "category": "random",
      "description": "Generate one or more UK 90-ball bingo cards. Each card is a 3-row by 9-column grid holding 15 numbers, 5 per row, with each column drawing from its own decade (1 to 9, 10 to 19, and so on up to 80 to 90). Blank squares are null.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many cards to generate, 1 to 100 (default 1)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_coin_flip",
      "title": "Coin flip",
      "url": "https://hopi.co.uk/coin-flip/",
      "category": "random",
      "description": "Flip a fair coin one or more times. Returns each result plus a tally of heads and tails.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many coins to flip, 1 to 10000 (default 1)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_combination_generator",
      "title": "Combination generator",
      "url": "https://hopi.co.uk/combination-generator/",
      "category": "random",
      "description": "List every way to choose r items from a list, ignoring order (combinations). Returns the total count and the combinations themselves (the first 5000).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "description": "The list of items to choose from"
          },
          "choose": {
            "type": "integer",
            "description": "How many items to pick in each combination (r)"
          }
        },
        "required": [
          "items",
          "choose"
        ]
      }
    },
    {
      "name": "hopi_dice_roller",
      "title": "Dice roller",
      "url": "https://hopi.co.uk/dice-roller/",
      "category": "random",
      "description": "Roll one or more dice with a given number of sides. Returns each die result plus the total, highest and lowest.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "integer",
            "description": "How many dice to roll, 1 to 20 (default 1)"
          },
          "sides": {
            "type": "integer",
            "description": "Number of sides on each die (default 6)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_euromillions_generator",
      "title": "EuroMillions number generator",
      "url": "https://hopi.co.uk/euromillions-generator/",
      "category": "random",
      "description": "Generate random EuroMillions lines. Each line has 5 main numbers from 1 to 50 and 2 Lucky Stars from 1 to 12.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lines": {
            "type": "integer",
            "description": "How many lines to generate, 1 to 10 (default 1)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_fortune_cookie",
      "title": "Fortune cookie",
      "url": "https://hopi.co.uk/fortune-cookie/",
      "category": "random",
      "description": "Crack open a virtual fortune cookie and receive a random cheerful fortune. Returns the fortune.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    },
    {
      "name": "hopi_lottery_number_generator",
      "title": "Lottery number generator",
      "url": "https://hopi.co.uk/lottery-number-generator/",
      "category": "random",
      "description": "Generate random lines for a UK lottery game: Lotto (6 numbers from 1 to 59), Thunderball (5 from 1 to 39 plus a Thunderball from 1 to 14) or Set For Life (5 from 1 to 47 plus a Life Ball from 1 to 10).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "game": {
            "type": "string",
            "enum": [
              "lotto",
              "thunderball",
              "setforlife"
            ],
            "description": "Which game to play (default lotto)"
          },
          "lines": {
            "type": "integer",
            "description": "How many lines to generate, 1 to 10 (default 1)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_magic_8_ball",
      "title": "Magic 8 ball",
      "url": "https://hopi.co.uk/magic-8-ball/",
      "category": "random",
      "description": "Ask the Magic 8 Ball a yes or no question and receive one of its twenty classic answers at random. Returns the answer.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string",
            "description": "The yes or no question to ask (optional)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_passphrase_generator",
      "title": "Passphrase generator",
      "url": "https://hopi.co.uk/passphrase-generator/",
      "category": "random",
      "description": "Build a memorable passphrase by joining random everyday words with a separator. Returns the passphrase and its approximate entropy in bits.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "words": {
            "type": "integer",
            "description": "How many words in the passphrase, 3 to 8 (default 4)"
          },
          "separator": {
            "type": "string",
            "enum": [
              "-",
              ".",
              "_",
              " "
            ],
            "description": "Character between words (default '-')"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_password_generator",
      "title": "Password generator",
      "url": "https://hopi.co.uk/password-generator/",
      "category": "random",
      "description": "Generate a strong random password from selected character sets. At least one character from each selected set is guaranteed. Returns the password and its approximate entropy in bits.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "length": {
            "type": "integer",
            "description": "Password length, 4 to 128 (default 16)"
          },
          "lowercase": {
            "type": "boolean",
            "description": "Include lower-case letters (default true)"
          },
          "uppercase": {
            "type": "boolean",
            "description": "Include upper-case letters (default true)"
          },
          "digits": {
            "type": "boolean",
            "description": "Include digits (default true)"
          },
          "symbols": {
            "type": "boolean",
            "description": "Include symbols !#$%&*+-=?@^_~ (default true)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_random_coordinates",
      "title": "Random coordinates generator",
      "url": "https://hopi.co.uk/random-coordinates/",
      "category": "random",
      "description": "Generate random geographic coordinates that are uniform by surface area across the globe (points are not bunched at the poles). Returns latitude and longitude in decimal degrees.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "integer",
            "description": "How many points to generate, 1 to 100 (default 1)"
          },
          "decimals": {
            "type": "integer",
            "description": "Decimal places for each coordinate, 2 to 6 (default 4)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_random_letter_generator",
      "title": "Random letter generator",
      "url": "https://hopi.co.uk/random-letter-generator/",
      "category": "random",
      "description": "Generate random letters from the alphabet, optionally limited to vowels or consonants. Returns the letters as a list.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "integer",
            "description": "How many letters to generate, 1 to 100 (default 1)"
          },
          "set": {
            "type": "string",
            "enum": [
              "any",
              "vowels",
              "consonants"
            ],
            "description": "Which letters to draw from (default any)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_random_number_generator",
      "title": "Random number generator",
      "url": "https://hopi.co.uk/random-number-generator/",
      "category": "random",
      "description": "Generate one or more random whole numbers within a range (inclusive), optionally with no repeats. Returns the numbers as a list.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "min": {
            "type": "integer",
            "description": "Lowest possible number (inclusive)"
          },
          "max": {
            "type": "integer",
            "description": "Highest possible number (inclusive)"
          },
          "quantity": {
            "type": "integer",
            "description": "How many numbers to generate, 1 to 1000 (default 1)"
          },
          "unique": {
            "type": "boolean",
            "description": "If true, no number repeats (default false)"
          }
        },
        "required": [
          "min",
          "max"
        ]
      }
    },
    {
      "name": "hopi_random_team_generator",
      "title": "Random team generator",
      "url": "https://hopi.co.uk/random-team-generator/",
      "category": "random",
      "description": "Shuffle a list of names and deal them evenly into a set number of teams. Returns each team's members.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "names": {
            "type": "array",
            "description": "The list of names to split into teams"
          },
          "teams": {
            "type": "integer",
            "description": "How many teams to make, 2 to 20"
          }
        },
        "required": [
          "names",
          "teams"
        ]
      }
    },
    {
      "name": "hopi_random_word_generator",
      "title": "Random word generator",
      "url": "https://hopi.co.uk/random-word-generator/",
      "category": "random",
      "description": "Generate random everyday English nouns, with no repeats. Returns the words as a list.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "integer",
            "description": "How many words to generate, 1 to 20 (default 1)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_secret_santa_generator",
      "title": "Secret Santa generator",
      "url": "https://hopi.co.uk/secret-santa-generator/",
      "category": "random",
      "description": "Draw Secret Santa gift pairings from a list of names. Every person gives to exactly one other person, and nobody is assigned to themselves (a derangement). Returns the giver to receiver pairs.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "names": {
            "type": "array",
            "description": "The list of participant names (at least two, no duplicates)"
          }
        },
        "required": [
          "names"
        ]
      }
    },
    {
      "name": "hopi_slot_machine_picker",
      "title": "Slot machine name picker",
      "url": "https://hopi.co.uk/slot-machine-picker/",
      "category": "random",
      "description": "Spin a slot machine reel of names or options and pick one at random. Every item has an equal chance. Returns the chosen item.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "description": "The list of names or options on the reel (at least two)"
          }
        },
        "required": [
          "items"
        ]
      }
    },
    {
      "name": "hopi_spin_the_bottle",
      "title": "Spin the bottle",
      "url": "https://hopi.co.uk/spin-the-bottle/",
      "category": "random",
      "description": "Spin the bottle and pick one player at random from those in the circle. Every player has an equal chance. Returns the chosen player.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "players": {
            "type": "array",
            "description": "The list of players in the circle (at least two)"
          }
        },
        "required": [
          "players"
        ]
      }
    },
    {
      "name": "hopi_username_generator",
      "title": "Username generator",
      "url": "https://hopi.co.uk/username-generator/",
      "category": "random",
      "description": "Invent memorable usernames by pairing a random adjective with a random noun, optionally with a two-digit number on the end. Returns a list of unique usernames.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many usernames to generate, 1 to 50 (default 6)"
          },
          "addNumbers": {
            "type": "boolean",
            "description": "Append a two-digit number to each name (default false)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_wheel_spinner",
      "title": "Wheel spinner",
      "url": "https://hopi.co.uk/wheel-spinner/",
      "category": "random",
      "description": "Spin a wheel of names or options and pick one at random. Every item has an equal chance. Returns the chosen item.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "description": "The list of names or options on the wheel (at least two)"
          }
        },
        "required": [
          "items"
        ]
      }
    },
    {
      "name": "hopi_yes_no_wheel",
      "title": "Yes or no",
      "url": "https://hopi.co.uk/yes-no-wheel/",
      "category": "random",
      "description": "Get a random yes or no decision, with an optional maybe. Returns the answer.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "allowMaybe": {
            "type": "boolean",
            "description": "Include 'maybe' as a possible answer (default false)"
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_alphabetical_order",
      "title": "Alphabetical order sorter",
      "url": "https://hopi.co.uk/alphabetical-order/",
      "category": "text",
      "description": "Sort the lines of a block of text into alphabetical order. Blank lines are dropped. Uses natural en-GB ordering so numbers within lines sort sensibly. Can sort ascending (A to Z) or descending (Z to A), and can ignore case.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to sort, one item per line"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "description": "'asc' for A to Z (default), 'desc' for Z to A"
          },
          "caseInsensitive": {
            "type": "boolean",
            "description": "Ignore letter case when sorting (default false)"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_caesar_cipher",
      "title": "Caesar cipher & ROT13",
      "url": "https://hopi.co.uk/caesar-cipher/",
      "category": "text",
      "description": "Encode or decode text with a Caesar shift cipher. Each letter is moved along the alphabet by the shift amount; a shift of 13 is ROT13. Only A to Z letters are changed, everything else is left as is. Decoding applies the opposite shift.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to transform"
          },
          "shift": {
            "type": "integer",
            "description": "How many places to shift each letter (e.g. 3, or 13 for ROT13)"
          },
          "mode": {
            "type": "string",
            "enum": [
              "encode",
              "decode"
            ],
            "description": "'encode' to apply the shift, 'decode' to reverse it (default encode)"
          }
        },
        "required": [
          "text",
          "shift"
        ]
      }
    },
    {
      "name": "hopi_case_converter",
      "title": "Case converter",
      "url": "https://hopi.co.uk/case-converter/",
      "category": "text",
      "description": "Convert text to a different letter case. 'upper' is UPPERCASE, 'lower' is lowercase, 'title' capitalises the first letter of each word, and 'sentence' capitalises the first letter of each sentence.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to convert"
          },
          "mode": {
            "type": "string",
            "enum": [
              "upper",
              "lower",
              "title",
              "sentence"
            ],
            "description": "The target case"
          }
        },
        "required": [
          "text",
          "mode"
        ]
      }
    },
    {
      "name": "hopi_character_counter",
      "title": "Character counter",
      "url": "https://hopi.co.uk/character-counter/",
      "category": "text",
      "description": "Count the characters in a block of text, including a count with spaces removed, the word count, how many SMS messages it would take to send, and the Twitter/X characters remaining out of 280.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to measure"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_emoji_remover",
      "title": "Emoji remover",
      "url": "https://hopi.co.uk/emoji-remover/",
      "category": "text",
      "description": "Remove emoji from a block of text, leaving the words and normal punctuation intact. Joined emoji sequences (such as a family or a flag) count as a single emoji. The copyright, registered and trademark symbols are kept. Returns the cleaned text and how many emoji were removed.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to clean"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_find_and_replace",
      "title": "Find and replace",
      "url": "https://hopi.co.uk/find-and-replace/",
      "category": "text",
      "description": "Find every occurrence of a piece of text and replace it with something else. Supports case-sensitive matching, whole-word matching, and full regular expressions. Returns the new text and how many matches were replaced.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to search within"
          },
          "find": {
            "type": "string",
            "description": "The text or pattern to find"
          },
          "replace": {
            "type": "string",
            "description": "The replacement text (default empty)"
          },
          "caseSensitive": {
            "type": "boolean",
            "description": "Match case exactly (default false)"
          },
          "wholeWord": {
            "type": "boolean",
            "description": "Only match whole words (default false)"
          },
          "regex": {
            "type": "boolean",
            "description": "Treat 'find' as a regular expression (default false)"
          }
        },
        "required": [
          "text",
          "find"
        ]
      }
    },
    {
      "name": "hopi_lorem_ipsum_generator",
      "title": "Lorem ipsum generator",
      "url": "https://hopi.co.uk/lorem-ipsum-generator/",
      "category": "text",
      "description": "Generate lorem ipsum placeholder text. Choose whether the count is a number of paragraphs, sentences or words, and how many. Limits are 100 paragraphs, 500 sentences or 2000 words.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "paragraphs",
              "sentences",
              "words"
            ],
            "description": "What the count refers to (default paragraphs)"
          },
          "count": {
            "type": "integer",
            "description": "How many paragraphs, sentences or words to produce"
          }
        },
        "required": [
          "count"
        ]
      }
    },
    {
      "name": "hopi_morse_code_translator",
      "title": "Morse code translator",
      "url": "https://hopi.co.uk/morse-code-translator/",
      "category": "text",
      "description": "Translate text into international Morse code, or Morse code back into text. Letters are separated by spaces and words by a forward slash. When decoding, underscores are treated as dashes and pipes as word separators. Unknown Morse sequences appear as # in the output.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text or Morse code to translate"
          },
          "direction": {
            "type": "string",
            "enum": [
              "t2m",
              "m2t"
            ],
            "description": "'t2m' text to Morse (default), 'm2t' Morse to text"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_nato_phonetic_alphabet",
      "title": "NATO phonetic alphabet translator",
      "url": "https://hopi.co.uk/nato-phonetic-alphabet/",
      "category": "text",
      "description": "Spell text out using the NATO phonetic alphabet (Alfa, Bravo, Charlie and so on), or convert a phonetic spelling back into plain text. Spaces become (space). When converting back, common variants such as Alpha, Juliet, Xray, Niner and Fife are accepted; unrecognised words appear as #.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text or phonetic spelling to convert"
          },
          "direction": {
            "type": "string",
            "enum": [
              "t2n",
              "n2t"
            ],
            "description": "'t2n' text to phonetic (default), 'n2t' phonetic to text"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_reading_time_calculator",
      "title": "Reading time calculator",
      "url": "https://hopi.co.uk/reading-time-calculator/",
      "category": "text",
      "description": "Estimate how long a block of text takes to read. Returns a silent reading time (225 words per minute) and a read-aloud time (130 words per minute), along with the word count.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to measure"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_remove_duplicate_lines",
      "title": "Duplicate line remover",
      "url": "https://hopi.co.uk/remove-duplicate-lines/",
      "category": "text",
      "description": "Remove duplicate lines from a block of text, keeping the first occurrence of each line in its original order. Can optionally ignore letter case when deciding what counts as a duplicate. Returns the deduplicated text plus how many lines were kept and removed.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to deduplicate, one item per line"
          },
          "caseInsensitive": {
            "type": "boolean",
            "description": "Treat lines that differ only in case as duplicates (default false)"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_remove_extra_spaces",
      "title": "Remove extra spaces",
      "url": "https://hopi.co.uk/remove-extra-spaces/",
      "category": "text",
      "description": "Tidy up spacing in text: collapse runs of spaces, tabs and non-breaking spaces down to a single space and trim each line. Can optionally also remove blank lines. Line breaks between lines are kept.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to clean"
          },
          "removeBlankLines": {
            "type": "boolean",
            "description": "Also drop empty lines (default false)"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_remove_line_breaks",
      "title": "Remove line breaks",
      "url": "https://hopi.co.uk/remove-line-breaks/",
      "category": "text",
      "description": "Remove line breaks from text. In 'spaces' mode every line is joined into one with single spaces. In 'paragraphs' mode blank lines are treated as paragraph breaks, so text is joined within each paragraph while the blank line between paragraphs is preserved.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to join"
          },
          "mode": {
            "type": "string",
            "enum": [
              "spaces",
              "paragraphs"
            ],
            "description": "'spaces' joins everything into one block (default), 'paragraphs' keeps paragraph breaks"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_reverse_text",
      "title": "Reverse text generator",
      "url": "https://hopi.co.uk/reverse-text/",
      "category": "text",
      "description": "Reverse text in one of three ways. 'characters' reverses the entire text character by character. 'words' reverses the order of words on each line. 'each' keeps the word order but reverses the letters within each word.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to reverse"
          },
          "mode": {
            "type": "string",
            "enum": [
              "characters",
              "words",
              "each"
            ],
            "description": "'characters' (default), 'words' reverses word order per line, 'each' reverses letters within each word"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_small_text_generator",
      "title": "Small text generator",
      "url": "https://hopi.co.uk/small-text-generator/",
      "category": "text",
      "description": "Convert text into decorative Unicode styles. 'superscript' uses tiny raised characters, 'smallcaps' uses small capital letters, and 'fullwidth' uses wide monospaced characters. Any character with no styled equivalent is left unchanged.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to convert"
          },
          "style": {
            "type": "string",
            "enum": [
              "superscript",
              "smallcaps",
              "fullwidth"
            ],
            "description": "Which style to apply (default superscript)"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_special_characters",
      "title": "Special characters to copy",
      "url": "https://hopi.co.uk/special-characters/",
      "category": "text",
      "description": "List special characters and symbols grouped by category: arrows, stars and hearts, maths, currency, punctuation, legal marks and accents. Optionally filter to a single group. Returns the characters ready to copy.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "group": {
            "type": "string",
            "enum": [
              "arrows",
              "stars",
              "maths",
              "currency",
              "punctuation",
              "legal",
              "accents"
            ],
            "description": "Optional: return only this group. Omit to return every group."
          }
        },
        "required": []
      }
    },
    {
      "name": "hopi_text_repeater",
      "title": "Text repeater",
      "url": "https://hopi.co.uk/text-repeater/",
      "category": "text",
      "description": "Repeat a piece of text a chosen number of times, joined by an optional separator, with optional line numbering. Count is capped at 10000 repeats and the output is capped at 100000 characters. Returns the repeated text plus its character and line counts.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to repeat"
          },
          "count": {
            "type": "integer",
            "description": "How many times to repeat it (1 to 10000)"
          },
          "separator": {
            "type": "string",
            "enum": [
              "none",
              "space",
              "newline",
              "comma",
              "custom"
            ],
            "description": "How to join the repeats (default none)"
          },
          "customSeparator": {
            "type": "string",
            "description": "The separator string to use when separator is 'custom'"
          },
          "numbering": {
            "type": "boolean",
            "description": "Prefix each repeat with a number, e.g. '1. ' (default false)"
          }
        },
        "required": [
          "text",
          "count"
        ]
      }
    },
    {
      "name": "hopi_text_splitter",
      "title": "Text splitter",
      "url": "https://hopi.co.uk/text-splitter/",
      "category": "text",
      "description": "Split a long block of text into smaller blocks. In 'length' mode it splits into chunks up to a maximum character size, breaking at spaces where possible, and can add 1/n numbering to each block. In 'delimiter' mode it splits wherever a delimiter appears (use \\n for newline, \\t for tab). Returns the list of blocks.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to split"
          },
          "mode": {
            "type": "string",
            "enum": [
              "length",
              "delimiter"
            ],
            "description": "'length' splits by character size (default), 'delimiter' splits at a delimiter"
          },
          "size": {
            "type": "integer",
            "description": "Maximum characters per block for length mode (at least 10, default 280)"
          },
          "numbered": {
            "type": "boolean",
            "description": "Add ' n/total' numbering to each block in length mode (default false)"
          },
          "delimiter": {
            "type": "string",
            "description": "The delimiter for delimiter mode; \\n and \\t are interpreted as newline and tab"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_upside_down_text",
      "title": "Upside down text",
      "url": "https://hopi.co.uk/upside-down-text/",
      "category": "text",
      "description": "Flip text upside down using Unicode look-alike characters and reverse its order, so it reads as if rotated 180 degrees. Characters with no upside-down equivalent are kept as they are (but still reversed in position).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to flip upside down"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_word_counter",
      "title": "Word counter",
      "url": "https://hopi.co.uk/word-counter/",
      "category": "text",
      "description": "Analyse a block of text and return the word count, character count (with and without spaces), sentence count, paragraph count and an estimated reading time at 225 words per minute.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to analyse"
          }
        },
        "required": [
          "text"
        ]
      }
    },
    {
      "name": "hopi_word_frequency_counter",
      "title": "Word frequency counter",
      "url": "https://hopi.co.uk/word-frequency-counter/",
      "category": "text",
      "description": "Count how often each word appears in a block of text, sorted from most to least frequent. Returns the total word count, the number of unique words, and the top 20 words with their counts and percentages. Common stop words (the, and, of, ...) can optionally be ignored.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to analyse"
          },
          "ignoreStopwords": {
            "type": "boolean",
            "description": "Ignore common words such as the, and, of, to (default false)"
          }
        },
        "required": [
          "text"
        ]
      }
    }
  ]
}
