← WebMCP Directory

Tool tree

loomlace.vercel.app

CommerceTools verified
Website
A local-first jewellery studio where you and your agent sculpt the same live design.
Explore capabilities

    page: Every page

    get_design_stateAnswer

    Read the ring the customer is currently looking at, as JSON. Call this first, and again whenever you want to build on an edit the human made by hand — they can drag stones and move sliders while you work, so the design changes underneath you.

    View tool JSON
    {
      "name": "get_design_state",
      "kind": "answer",
      "impl": "imperative",
      "description": "Read the ring the customer is currently looking at, as JSON. Call this first, and again whenever you want to build on an edit the human made by hand — they can drag stones and move sliders while you work, so the design changes underneath you.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    set_bandAction

    Change the ring's band. widthMm is the band thickness in millimetres — 1.2 is a delicate thread, 2.2 is a classic everyday weight, 4.0 is deliberately chunky. profile changes the cross-section silhouette: flat is modern and architectural, court is rounded and comfortable, bevel is a flat face with the edges cut away at an angle, knife-edge is sharp and art-deco. metal changes both the colour and the price. Omit any field to leave it as it is.

    View tool JSON
    {
      "name": "set_band",
      "kind": "act",
      "impl": "imperative",
      "description": "Change the ring's band. widthMm is the band thickness in millimetres — 1.2 is a delicate thread, 2.2 is a classic everyday weight, 4.0 is deliberately chunky. profile changes the cross-section silhouette: flat is modern and architectural, court is rounded and comfortable, bevel is a flat face with the edges cut away at an angle, knife-edge is sharp and art-deco. metal changes both the colour and the price. Omit any field to leave it as it is.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "widthMm": {
            "type": "number",
            "minimum": 1.2,
            "maximum": 4
          },
          "profile": {
            "type": "string",
            "enum": [
              "flat",
              "court",
              "bevel",
              "knife-edge"
            ]
          },
          "metal": {
            "type": "string",
            "enum": [
              "yellow",
              "white",
              "rose",
              "platinum"
            ]
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    set_setting_styleAction

    Choose how the stones are held. 'solitaire' is a single raised stone on plain claws. 'halo' rings the centre stone with small pavé stones so it reads larger. 'pave' scatters small stones along the band itself. 'bezel' wraps the stone in a continuous metal rim — the most modern and the most protective. Choosing a setting commits the design far enough that engraving becomes available.

    View tool JSON
    {
      "name": "set_setting_style",
      "kind": "act",
      "impl": "imperative",
      "description": "Choose how the stones are held. 'solitaire' is a single raised stone on plain claws. 'halo' rings the centre stone with small pavé stones so it reads larger. 'pave' scatters small stones along the band itself. 'bezel' wraps the stone in a continuous metal rim — the most modern and the most protective. Choosing a setting commits the design far enough that engraving becomes available.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "setting": {
            "type": "string",
            "enum": [
              "solitaire",
              "halo",
              "pave",
              "bezel"
            ]
          }
        },
        "required": [
          "setting"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    set_viewAction

    Rotate the ring on screen. 'top' is the hero shot, looking down onto the stone and the setting that holds it; 'side' is the dead-on profile, which is the view that shows how high the stone sits; 'inside' moves in on the inner band surface, where engraving goes. Nothing about the ring itself changes — this only moves the camera, so it is cheap to call and worth calling to show the customer what you just did.

    View tool JSON
    {
      "name": "set_view",
      "kind": "act",
      "impl": "imperative",
      "description": "Rotate the ring on screen. 'top' is the hero shot, looking down onto the stone and the setting that holds it; 'side' is the dead-on profile, which is the view that shows how high the stone sits; 'inside' moves in on the inner band surface, where engraving goes. Nothing about the ring itself changes — this only moves the camera, so it is cheap to call and worth calling to show the customer what you just did.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "view": {
            "type": "string",
            "enum": [
              "top",
              "side",
              "inside"
            ]
          }
        },
        "required": [
          "view"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    place_stoneAction

    Add a new stone to the ring, or move/restyle one that's already there. Omit id to add a new stone — the store generates its id and returns it in the summary, so hold onto that id if you plan to touch this stone again later (e.g. add three accent stones, then move the second one by passing its id back in). Pass an id that already exists to update that stone in place; a made-up id is treated as a fresh stone using that id, so when in doubt about whether one exists, call get_design_state first rather than guessing. x and y describe where the stone sits on the band's face, both normalised 0 to 1. x is the position AROUND the band's circumference: 0.5 is dead centre (the front of the finger), lower values move left, higher values move right — a three-stone trellis might sit at x = 0.4, 0.5, 0.6. y is the position ACROSS the band's face, along the finger: 0 and 1 are the band's two edges and 0.5 is centred. y only has as much room to move as the band is wide, so on a slim band it is a fine adjustment rather than a dramatic one — prefer x for anything meant to read at a glance. A classic solitaire sits at x=0.5, y=0.5. sizeMm is the stone's diameter in millimetres, from 1.5 (a pavé speck) to 12 (a bold statement centre stone) — 6.5mm is a typical solitaire. type is the gem material (diamond/sapphire/emerald/ruby) and cut is its shape (round/oval/emerald/princess) — these are independent, so type=emerald with cut=round means a round-cut emerald gemstone, not the rectangular step cut. The FIRST stone in the design is the centre stone: the halo, bezel or claws are built around that one, and it is the stone the price is dominated by. A new stone is appended, so adding one never takes the centre away from the stone that already had it — pass that stone's id if what you actually want is to change the centre. Prefer apply_style_preset when you want to restyle the whole ring at once; use this tool for adding or fine-tuning one stone at a time.

    View tool JSON
    {
      "name": "place_stone",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a new stone to the ring, or move/restyle one that's already there. Omit id to add a new stone — the store generates its id and returns it in the summary, so hold onto that id if you plan to touch this stone again later (e.g. add three accent stones, then move the second one by passing its id back in). Pass an id that already exists to update that stone in place; a made-up id is treated as a fresh stone using that id, so when in doubt about whether one exists, call get_design_state first rather than guessing. x and y describe where the stone sits on the band's face, both normalised 0 to 1. x is the position AROUND the band's circumference: 0.5 is dead centre (the front of the finger), lower values move left, higher values move right — a three-stone trellis might sit at x = 0.4, 0.5, 0.6. y is the position ACROSS the band's face, along the finger: 0 and 1 are the band's two edges and 0.5 is centred. y only has as much room to move as the band is wide, so on a slim band it is a fine adjustment rather than a dramatic one — prefer x for anything meant to read at a glance. A classic solitaire sits at x=0.5, y=0.5. sizeMm is the stone's diameter in millimetres, from 1.5 (a pavé speck) to 12 (a bold statement centre stone) — 6.5mm is a typical solitaire. type is the gem material (diamond/sapphire/emerald/ruby) and cut is its shape (round/oval/emerald/princess) — these are independent, so type=emerald with cut=round means a round-cut emerald gemstone, not the rectangular step cut. The FIRST stone in the design is the centre stone: the halo, bezel or claws are built around that one, and it is the stone the price is dominated by. A new stone is appended, so adding one never takes the centre away from the stone that already had it — pass that stone's id if what you actually want is to change the centre. Prefer apply_style_preset when you want to restyle the whole ring at once; use this tool for adding or fine-tuning one stone at a time.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "diamond",
              "sapphire",
              "emerald",
              "ruby"
            ]
          },
          "cut": {
            "type": "string",
            "enum": [
              "round",
              "oval",
              "emerald",
              "princess"
            ]
          },
          "sizeMm": {
            "type": "number",
            "minimum": 1.5,
            "maximum": 12
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    remove_stoneAction

    Remove a stone from the ring by id. Get the id from get_design_state or from the id place_stone returned when you created it. If the id doesn't match any stone currently on the ring, nothing is removed and the summary lists every id that DOES exist, so you can correct yourself instead of guessing again blindly. Removing the first stone promotes the next one to centre, so the setting rebuilds itself around a different stone and the price moves — worth a get_design_state afterwards if the ring had more than one stone on it.

    View tool JSON
    {
      "name": "remove_stone",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove a stone from the ring by id. Get the id from get_design_state or from the id place_stone returned when you created it. If the id doesn't match any stone currently on the ring, nothing is removed and the summary lists every id that DOES exist, so you can correct yourself instead of guessing again blindly. Removing the first stone promotes the next one to centre, so the setting rebuilds itself around a different stone and the price moves — worth a get_design_state afterwards if the ring had more than one stone on it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    apply_style_presetAction

    Restyle the whole ring to a named aesthetic in one call — the headline move of this app, because it changes several properties in a coordinated way rather than one field at a time. 'art-deco': Sharp geometry and symmetry — a knife-edge band, step-cut stone and a tight halo. Concretely: band becomes a slim knife-edge profile (about 15% thinner), setting becomes a tight halo, and the centre stone is cut as a step-cut emerald square. 'minimalist': Nothing that isn't load-bearing — a thin flat band, one round stone, bezel-set. Concretely: band becomes flat and thin (about 30% thinner, capped at 1.8mm), setting becomes bezel, the centre stone shrinks slightly and every other stone is removed — the whole point is subtraction. 'vintage': Softer and more ornate — a rounded court band, oval stone and pavé along the shoulders. Concretely: band becomes a fuller court profile (about 15% thicker), setting becomes pavé along the shoulders, and the centre stone is cut oval. Crucially, a preset is a function of the design you already have, not a reset to defaults: it only touches the properties that define its look (band profile/width, setting, stone cut) and leaves everything else exactly as the customer chose — the metal, the stone material (diamond/sapphire/etc.), and any engraving text all survive untouched. That means a preset composes with manual edits in either order: apply rose gold and a sapphire first, then art-deco, and you get a rose-gold sapphire art-deco ring, not a reset to yellow gold and diamond.

    View tool JSON
    {
      "name": "apply_style_preset",
      "kind": "act",
      "impl": "imperative",
      "description": "Restyle the whole ring to a named aesthetic in one call — the headline move of this app, because it changes several properties in a coordinated way rather than one field at a time. 'art-deco': Sharp geometry and symmetry — a knife-edge band, step-cut stone and a tight halo. Concretely: band becomes a slim knife-edge profile (about 15% thinner), setting becomes a tight halo, and the centre stone is cut as a step-cut emerald square. 'minimalist': Nothing that isn't load-bearing — a thin flat band, one round stone, bezel-set. Concretely: band becomes flat and thin (about 30% thinner, capped at 1.8mm), setting becomes bezel, the centre stone shrinks slightly and every other stone is removed — the whole point is subtraction. 'vintage': Softer and more ornate — a rounded court band, oval stone and pavé along the shoulders. Concretely: band becomes a fuller court profile (about 15% thicker), setting becomes pavé along the shoulders, and the centre stone is cut oval. Crucially, a preset is a function of the design you already have, not a reset to defaults: it only touches the properties that define its look (band profile/width, setting, stone cut) and leaves everything else exactly as the customer chose — the metal, the stone material (diamond/sapphire/etc.), and any engraving text all survive untouched. That means a preset composes with manual edits in either order: apply rose gold and a sapphire first, then art-deco, and you get a rose-gold sapphire art-deco ring, not a reset to yellow gold and diamond.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "style": {
            "type": "string",
            "enum": [
              "art-deco",
              "minimalist",
              "vintage"
            ]
          }
        },
        "required": [
          "style"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    save_lookAction

    Freeze the ring exactly as it is right now as a saved 'look', so you can change it freely afterwards and still come back. This is how you offer a customer a real choice: save the current ring, try a variation, save that too, then restore whichever they preferred — nothing else in this app is undoable, so a look is the only way back to a design once you have edited past it. Give it a short label they'd recognise ("the warmer one", "under £3,000"); omit it and one is generated from the design. Returns the look's number — the handle restore_look takes. Only the most recent 6 looks are kept; saving past that drops the oldest. This tool takes about half a second to return because it waits for the ring to finish animating into place before photographing it for the customer's thumbnail strip — the photo is for them, not for you, and is never returned to you.

    View tool JSON
    {
      "name": "save_look",
      "kind": "act",
      "impl": "imperative",
      "description": "Freeze the ring exactly as it is right now as a saved 'look', so you can change it freely afterwards and still come back. This is how you offer a customer a real choice: save the current ring, try a variation, save that too, then restore whichever they preferred — nothing else in this app is undoable, so a look is the only way back to a design once you have edited past it. Give it a short label they'd recognise (\"the warmer one\", \"under £3,000\"); omit it and one is generated from the design. Returns the look's number — the handle restore_look takes. Only the most recent 6 looks are kept; saving past that drops the oldest. This tool takes about half a second to return because it waits for the ring to finish animating into place before photographing it for the customer's thumbnail strip — the photo is for them, not for you, and is never returned to you.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "maxLength": 60
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    list_looksAnswer

    List the looks saved so far, oldest first — each one's number, its label, what the ring actually is in words, and what it would cost. Use it to compare variations for the customer without restoring each one in turn, and to check which numbers are still live before calling restore_look. Numbers are never reused, so a look you saved earlier keeps its number even after older looks have been dropped, which means the list can have gaps in it. Read-only — never changes the ring.

    View tool JSON
    {
      "name": "list_looks",
      "kind": "answer",
      "impl": "imperative",
      "description": "List the looks saved so far, oldest first — each one's number, its label, what the ring actually is in words, and what it would cost. Use it to compare variations for the customer without restoring each one in turn, and to check which numbers are still live before calling restore_look. Numbers are never reused, so a look you saved earlier keeps its number even after older looks have been dropped, which means the list can have gaps in it. Read-only — never changes the ring.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    restore_lookAction

    Put a saved look back on the screen, replacing the ring currently being designed. Everything comes back together — band, stones, setting, engraving, size — because a look is a whole design and not a patch. The current ring is NOT saved first, so if the customer might want it back, call save_look before this. Pass the number from save_look or list_looks; if that number no longer exists, nothing changes and the summary tells you which numbers do.

    View tool JSON
    {
      "name": "restore_look",
      "kind": "act",
      "impl": "imperative",
      "description": "Put a saved look back on the screen, replacing the ring currently being designed. Everything comes back together — band, stones, setting, engraving, size — because a look is a whole design and not a patch. The current ring is NOT saved first, so if the customer might want it back, call save_look before this. Pass the number from save_look or list_looks; if that number no longer exists, nothing changes and the summary tells you which numbers do.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "n": {
            "type": "number"
          }
        },
        "required": [
          "n"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    delete_lookSensitive Action

    Forget a saved look by number. Only worth calling to clear something the customer has ruled out — you do not need to delete anything to make room, since saving past 6 looks drops the oldest by itself. The design on screen is untouched either way, even if it is the one that look was saved from.

    View tool JSON
    {
      "name": "delete_look",
      "kind": "transact",
      "impl": "imperative",
      "description": "Forget a saved look by number. Only worth calling to clear something the customer has ruled out — you do not need to delete anything to make room, since saving past 6 looks drops the oldest by itself. The design on screen is untouched either way, even if it is the one that look was saved from.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "n": {
            "type": "number"
          }
        },
        "required": [
          "n"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    estimate_priceAnswer

    Price the ring exactly as it's currently designed — band metal and width, every stone's type/cut/size, and the setting — as a line-itemised GBP estimate. Call this before add_to_cart so you can quote the customer a real number, and call it again after any edit that could change cost (metal, stone count, stone size, setting) since price is a live function of the whole design, not a cached value. Returns the individual price lines as well as the formatted total, so you can explain the price line by line rather than quoting a bare figure. Read-only — never changes the ring.

    View tool JSON
    {
      "name": "estimate_price",
      "kind": "answer",
      "impl": "imperative",
      "description": "Price the ring exactly as it's currently designed — band metal and width, every stone's type/cut/size, and the setting — as a line-itemised GBP estimate. Call this before add_to_cart so you can quote the customer a real number, and call it again after any edit that could change cost (metal, stone count, stone size, setting) since price is a live function of the whole design, not a cached value. Returns the individual price lines as well as the formatted total, so you can explain the price line by line rather than quoting a bare figure. Read-only — never changes the ring.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    add_to_cartAction

    Hand the finished design off to the jeweller's order system for checkout, opening the order page in a new browser tab. This is the one consequential tool in this set — call estimate_price first so you can tell the customer what they're about to order, and only call this once they've confirmed they're happy with the design. Encodes the full design as JSON plus human-readable fields (metal, band width, setting, a plain-text stone summary, ring size, and the GBP price) so the landing page is useful even before it parses the JSON. The browser may show its own confirmation prompt before opening the tab — that's expected for an action this consequential. If the browser blocks the popup, this tool does NOT fail silently: it returns ok:false with the destination URL so you can relay it to the human to open themselves. Optional note (max 200 characters) passes a short message to the jeweller, e.g. 'needed by Friday'.

    View tool JSON
    {
      "name": "add_to_cart",
      "kind": "act",
      "impl": "imperative",
      "description": "Hand the finished design off to the jeweller's order system for checkout, opening the order page in a new browser tab. This is the one consequential tool in this set — call estimate_price first so you can tell the customer what they're about to order, and only call this once they've confirmed they're happy with the design. Encodes the full design as JSON plus human-readable fields (metal, band width, setting, a plain-text stone summary, ring size, and the GBP price) so the landing page is useful even before it parses the JSON. The browser may show its own confirmation prompt before opening the tab — that's expected for an action this consequential. If the browser blocks the popup, this tool does NOT fail silently: it returns ok:false with the destination URL so you can relay it to the human to open themselves. Optional note (max 200 characters) passes a short message to the jeweller, e.g. 'needed by Friday'.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "note": {
            "type": "string",
            "maxLength": 200
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    set_sizeAction

    Set the customer's UK ring size. Accepts a single letter A–Z, optionally with a half — 'M', 'L½', 'L 1/2', and 'L half' all normalise to the same size. UK sizing for adult fingers realistically runs about D to Z, but the full letter range is accepted since a child's or a novelty size is still a valid design choice. If the input can't be parsed as a UK size at all (e.g. a US/EU number, or free text), the current size is left unchanged and the summary explains the expected format instead of crashing.

    View tool JSON
    {
      "name": "set_size",
      "kind": "act",
      "impl": "imperative",
      "description": "Set the customer's UK ring size. Accepts a single letter A–Z, optionally with a half — 'M', 'L½', 'L 1/2', and 'L half' all normalise to the same size. UK sizing for adult fingers realistically runs about D to Z, but the full letter range is accepted since a child's or a novelty size is still a valid design choice. If the input can't be parsed as a UK size at all (e.g. a US/EU number, or free text), the current size is left unchanged and the summary explains the expected format instead of crashing.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sizeUk": {
            "type": "string"
          }
        },
        "required": [
          "sizeUk"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }