Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Certificate changed, valid to 2027-01-19
Recently observed → Live
Live → Recently observed
Added "kapruka_gift_countries" and "kapruka_gift_country_products"; changed the definition of "kapruka_check_delivery", "kapruka_create_order", "kapruka_get_product" and 1 more (8 tools before, 10 now)
⟨481 unchanged words⟩ delivery date is more than 1 day out. INTERNATIONAL GIFTS (store products from kapruka_gift_country_products): pass product_id or cart (no city needed) and, for Australia / the UAE, `zone`. The answer is that country's delivery: available or not, the fee for the whole order, and the earliest date (3 days ahead; used when delivery_date is omitted). Args: params (CheckDeliveryInput): - city (str): Canonical city name (e.g. 'Colombo 03', 'Galle'); not needed for international gift store products - zone (Optional[str]): international gifts in Australia / the UAE - delivery_date (Optional[str]): YYYY-MM-DD; defaults ⟨289 unchanged words⟩
⟨58 unchanged words⟩ ,"title":"Cart"},"city":{"anyOf":[{"maxLength":100,"minLength":2,"type":"string"},{"type":"null"}],"default":null,"description":"Canonical Sri Lanka city name (use kapruka_list_delivery_cities to find one). Examples: 'Colombo 03', 'Anuradhapura', 'Galle'.","maxLength":100Required,"minLengthexcept for international gift store products (their country comes from the item).
Changed the definition of "kapruka_check_delivery", "kapruka_create_order" and "kapruka_get_product"
⟨351 unchanged words⟩ when the real cause is the cutoff). ECONOMY DELIVERY (cheaper courier, a few days instead of a chosen date) is worked out from the `cart` (and `gift_message`, which you should pass when there is one). When the answer shows an economy option, offer it to the customer as the cheaper choice, quoting its fee, promise wording and "expected by" date as given; if they take it, call kapruka_create_order with `delivery.type: "economy"` (the order is dated for you). When the answer says the order goes by economy delivery, that is the ONLY option for these items: tell the customer and order with `delivery.type: "economy"`. When economy is not shown, do not mention it. Perishable codes (CAKE*, FLOWER*, COMBO*) additionally ⟨80 unchanged words⟩ not in `cart` (custom cake quote) - gift_message (Optional[str]): the order's gift message, for the economy rule - response_format (str): 'markdown' (default) or 'json' ⟨156 unchanged words⟩ at 60) "perishable_warning": str | null, # populated when product_id is perishable "economy": { # only with `cart` "available": bool, # false: say nothing about economy "forced": bool, # true: economy is the ONLY option "fee": number, "currency": "LKR", "promise": str, # quote as given "delivery_date": str, # "expected by" date; create_order uses it "saving": number | null # vs the standard fee }
Changed the definition of "kapruka_get_product" and "kapruka_search_products"
⟨26 unchanged words⟩ delivery scope, and a direct product URL. Discounts: `price` is what checkout charges, with any website discount already applied; `compare_at_price` is the pre-discount price when one applies (null otherwise). Each variant carries its own pair. Quote `price`. Delivery scope: most gifts ship island-wide, but ⟨254 unchanged words⟩
⟨157 unchanged words⟩ in their own currency; do not convert it. A row's `price` is the discounted price checkout charges (the bounds filter on it); `compare_at_price` is set when on sale. Search results carry NO delivery-scope information. Food, ⟨266 unchanged words⟩
Changed the definition of "kapruka_check_delivery"
⟨7 unchanged words⟩ given city on a given date, andatthewhatdeliveryrate.fee. Returns whether theflatrequested date is available (if not, the next available date plus reason) and the delivery fee the checkout will charge. THE FEE DEPENDS ON THE CART AND THE CURRENCY — the city's base rate is not what checkout charges. Sri Lankan customers (LKR) pay the city rate capped by the cart value (25% of the item value,whetherat
Changed the definition of "kapruka_check_delivery", "kapruka_list_categories" and "kapruka_search_products"
⟨151 unchanged words⟩ check `item_deliverable` is present before relying on it. product_id also selects the SAME-DAY rule the checkout applies to that item: vendor-delivered items (restaurant food) can go today until late afternoon; ordinary items move to the next date; ordinary same-day is only possible early in the morning near Colombo. So a check without product_id can differ from one with it — always pass it once an item is chosen. When `available` is false, offer `next_available_date`. Do not interpret the `reason` text (it is the website's wording and may say slots are full when the real cause is the cutoff). Perishable codes (CAKE*, FLOWER*, COMBO*) additionally ⟨155 unchanged words⟩
List top-level Kapruka product categories by name with browse URLs.
Returns Changed the definition of "kapruka_create_order", "kapruka_get_product", "kapruka_render_options_card" and 1 more
⟨247 unchanged words⟩ LKR (default), USD, GBP, AUD,CAD,EUR - response_format (str): 'markdown' (default) ⟨234 unchanged words⟩
⟨234 unchanged words⟩ Supported: LKR, USD, GBP, AUD,CAD,EUR.","title":"Currency","type":" ⟨286 unchanged words⟩
Changed the definition of "kapruka_search_products"
⟨11 unchanged words⟩ ,"default":null,"description":"Filter bycategorySUBCATEGORYnameFACET(NAME — the same value the website's search uses in its `subcat=` parameter and shows in its left sidebar, e.g. 'Kapruka Cakes', 'Fresh Flowers', 'Birthday', 'Greeting Cards', 'Cake And Flower', 'Home And Lifestyle', 'Grocery Items'. These are narrower than a department and the valid set DEPENDS ON THE QUERY. Department words ('Cakes', 'Flowers', 'Toys').Case-insensitive.and most values from kapruka_list_categories are NOT valid here and return nothing. When the filter matches nothing this tool retries without it and says so, so a wrong value costs relevance, not results. If unsure, leave it unset and put the words in `q`.
Changed the definition of "kapruka_render_options_card"
⟨140 unchanged words⟩ ), USD, GBP, AUD, CAD, EUR - courtesy ({currency, per_usd}, optional): home-currency figure printed under each USD price ("≈ JPY 2,544"); the caller's rate, echoed back - footer_note (str, optional): appended to the footer reply hint Returns: str: JSON: { "card_url": ⟨19 unchanged words⟩ "amount": float, "currency": str}, "price_note": str | null, "url": str}], "courtesy": {"currency": str, "per_usd": float} | null, # what was printed, or null "unavailable": [str] # product_ids that ⟨15 unchanged words⟩
⟨61 unchanged words⟩ ":"CardProduct","type":"object"},"Courtesy":{"additionalProperties":false,"description":"A home-currency approximation to print under each USD price.\n\nThe CALLER supplies the rate it used for its own chat text, so the card and\nthe text agree to the unit; the card never converts on its own. Only\napplied when the card is priced in USD — the courtesy figure describes\nwhat a USD charge will look like on the customer's statement.","properties":{"currency":{"description":"ISO-4217 code of the customer's home currency, e.g. JPY.","maxLength":3,"minLength":3,"pattern":"^[A-Za-z]{3}$","title":"Currency","type":"string"},"per_usd":{"description":"Units of that currency per 1 USD, as used for the chat text.","exclusiveMaximum":1000000,"exclusiveMinimum":0,"title":"Per Usd","type":"number"}},"required":["currency","per_usd"],"title":"Courtesy","type":"object"},"
Changed the definition of "kapruka_create_order"
⟨117 unchanged words⟩ : - cart (list[CartItem]): 1–30items.lines.EachCatalogue line: product_id, quantity (default 1), optional icing_text (cakes only). Custom cake line: custom_cake_request_id + phone — orders the cake Kapruka staff quoted via kapruka_custom_cake_status (status must be 'quoted'; quantity is always 1; never send a price). Lines can be mixed in one order — one delivery fee covers everything; the whole cart must be deliverable to delivery.city. Only place a custom cake order after the customer clearly accepted the quoted total. - recipient (Recipient): name + phone ⟨78 unchanged words⟩ order_ref": str, # e.g. "ORD-20260520-7823" "order_id": str, # id used by the bank-deposit flow "summary": { "items_total": number, "delivery_fee ⟨40 unchanged words⟩ in the network at all), date_not_deliverable, city_not_deliverable_for_item. Custom cake lines add: request_not_found (404 — wrong id/phone or staff removed it), quote_not_ready (409 — staff haven't priced it; check kapruka_custom_cake_status later), quote_expired (410 — submit a new kapruka_custom_cake_request). summary.items_total may differ from the quoted cake total by a few rupees (USD round-trip) — quote the summary numbers when asking for payment.
Certificate recorded, valid to 2026-11-21
Authorization not required
First tool surface recorded: 8 tools (server version 1.30.0)
Showing the latest 15 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
⟨308 unchanged words⟩ :"string"},"city":{"description":"MustSribeLanka orders: a Kapruka delivery city (canonical name from kapruka_list_delivery_cities) that EVERY cart item can reach. International gifts: the recipient's city/town abroad, as written. The order ships as one shipment, so food ⟨33 unchanged words⟩ ":"City","type":"string"},"country":{"anyOf":[{"maxLength":60,"type":"string"},{"type":"null"}],"default":null,"description":"International gifts only (required): the store country from kapruka_gift_countries.","title":"Country"},"date":{"description":"Delivery date in YYYY-MM-DD ⟨43 unchanged words⟩ ":{"default":"standard","description":"'international_gift' for products from kapruka_gift_country_products (recipient abroad; needs country, zip, zone where listed; date >= 3 days ahead). Otherwise 'standard' (default) or 'economy' — the cheaper ⟨38 unchanged words⟩ "title":"Type","type":"string"},"zip":{"anyOf":[{"maxLength":35,"minLength":1,"type":"string"},{"type":"null"}],"default":null,"description":"International gifts only (required): the recipient's postcode / ZIP.","title":"Zip"},"zone":{"anyOf":[{"maxLength":60,"type":"string"},{"type":"null"}],"default":null,"description":"International gifts only: required for Australia and the UAE — one of that country's listed zones (kapruka_gift_countries).","title":"Zone"}},"required":["address","city","date"],"title": ⟨69 unchanged words⟩ ","title":"Anonymous","type":"boolean"},"email":{"anyOf":[{"maxLength":120,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","type":"string"},{"type":"null"}],"default":null,"description":"Sender's email (international gifts: send it when you have it).","title":"Email"},"name":{"description":"Sender name ⟨28 unchanged words⟩
⟨55 unchanged words⟩ cart says whether an order is offered it. International gift store products carry `international_gift` {"country", "orderable", "store_url"}: they are delivered IN that country by Kapruka's partner (see kapruka_gift_countries), not in Sri Lanka. Discounts: `price` is what checkout charges, with ⟨285 unchanged words⟩
⟨157 unchanged words⟩ in their own currency; do not convert it. Gifts for recipients OUTSIDE Sri Lanka are not in this search: use kapruka_gift_countries / kapruka_gift_country_products. A row's `price` is the discounted price checkout ⟨286 unchanged words⟩
List the countries Kapruka delivers gifts IN (international gift stores). Use when the RECIPIENT is outside Sri Lanka — e.g. "send flowers to my sister in Dubai", "a cake for my son in Melbourne". These gifts are delivered by Kapruka's partner in that country, not shipped from Sri Lanka. They are NOT in kapruka_search_products; list a store with kapruka_gift_country_products. For each country: how many gifts are in stock now (0 = nothing can be ordered there right now — say so), the delivery fee (one fee per order, whatever the number of items), and for Australia…
List EVERY gift in stock in one country's store (international gifts), grouped by type. The stores are small (tens of products), so this returns the whole store: read it and choose for the customer — there is no keyword search for these products. Prices are exactly what checkout charges for the item (no website discounts apply to these stores); delivery is extra — one fee per order (zone fee in Australia / the UAE), shown at the top. Use the `id` with kapruka_get_product for full detail and with kapruka_create_order (delivery.type "international_gift"). Args: …
⟨158 unchanged words⟩ today.","title":"Delivery Date"},"gift_message":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"The gift message you will send to kapruka_create_order, if any. Pass it with `cart` so the economy delivery option is worked out the way checkout will.","title":"Gift Message"},"other_items_total":{"anyOf":[{"minimum":0, ⟨219 unchanged words⟩
⟨223 unchanged words⟩ date (YYYY-MM-DD, today-or-future Asia/Colombo), optional instructions, type ('standard' default | 'economy') - sender (Sender): name + anonymous ⟨69 unchanged words⟩ items_total + delivery_fee + addons_total "currency": str, "delivery_type": "standard" | "economy", "delivery_date": str, # the date checkout will use — may differ from the one sent "delivery_promise": str # economy only: quote as given }, "expires_at": str # ISO 8601 ⟨75 unchanged words⟩ quote the summary numbers when asking for payment. economy_not_available (HTTP 422): economy was requested but this order cannot go economy. Nothing is created. Tell the customer it goes by standard delivery (fee from kapruka_check_delivery) and, once they agree, resend with delivery.type 'standard' and their date. Economy-only items always go economy, even when 'standard' is sent; read summary.delivery_type and summary.delivery_date and tell the customer the date checkout will use. city_not_deliverable_for_item (HTTP 422): at least one ⟨87 unchanged words⟩
⟨415 unchanged words⟩ ":"Location Type","type":"string"},"type":{"default":"standard","description":"'standard' (default) or 'economy' — the cheaper courier option. Send 'economy' only when kapruka_check_delivery (with the cart) showed it and the customer chose it, or said the items go by economy only. Economy orders are dated 4 days ahead for you; `date` is then ignored.","title":"Type","type":"string"}},"required":["address","city"," ⟨107 unchanged words⟩
⟨26 unchanged words⟩ delivery scope, and a direct product URL. `economy_delivery` ("optional" | "only" | "only_5to7" | null) says whether the item can go by the cheaper economy courier; kapruka_check_delivery with the cart says whether an order is offered it. Discounts: `price` is what checkout charges, with ⟨285 unchanged words⟩
{"$defs":{"CheckDeliveryInput":{"additionalProperties":false,"properties":{"cart":{"anyOf":[{"items":{"$ref":"#/$defs/DeliveryCartLine"},"maxItems":30,"type":"array"},{"type":"null"}],"default":null,"description":"The items the customer is buying (product_id, quantity, optional icing_text) — the same lines you will send to kapruka_create_order. With it the answer gives the EXACT delivery fee checkout will charge; without it, only the most it can be.","title":"Cart"},"city":{"description":"Canonical city name ( ⟨16 unchanged words⟩ ":"City","type":"string"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The currency the customer will check out in (LKR or USD; GBP/AUD/EUR check out in USD). Decides which delivery fee applies: Sri Lankan customers pay a fee capped by the cart value, overseas customers a fixed USD fee. Default LKR.","title":"Currency"},"delivery_date":{"anyOf":[{"type":"string ⟨18 unchanged words⟩ today.","title":"Delivery Date"},"other_items_total":{"anyOf":[{"minimum":0,"type":"number"},{"type":"null"}],"default":null,"description":"LKR value of items not listed in `cart` (e.g. a quoted custom cake's total). Added to the cart value for the fee.","title":"Other Items Total"},"product_id":{"anyOf":[{"maxLength":80, ⟨80 unchanged words⟩ "required":["city"],"title":"CheckDeliveryInput","type":"object"},"DeliveryCartLine":{"description":"A catalogue cart line, the same shape kapruka_create_order takes.\n\nCustom cake lines cannot be priced here; pass the quote's total as\n`other_items_total` instead.","properties":{"icing_text":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"default":null,"description":"Set when the cake carries icing text — the checkout adds a small charge for it.","title":"Icing Text"},"product_id":{"maxLength":50,"minLength":3,"pattern":"^[A-Za-z0-9_\\-]+$","title":"Product Id","type":"string"},"quantity":{"default":1,"maximum":99,"minimum":1,"title":"Quantity","type":"integer"}},"required":["product_id"],"title":"DeliveryCartLine","type":"object"}},"properties": ⟨9 unchanged words⟩
⟨20 unchanged words⟩ with prices, stock status, images, andURLs.URLs, plus the category facets available for the query (facets.categories) — the names that work in `category` to narrow the same search. Supports cursor-based pagination — pass next_cursor from one ⟨17 unchanged words⟩ for broader discovery, refine the query orfilternarrowbywithcategorya facet instead. Queries must be at least 3 characters ⟨9 unchanged words⟩ "the", "a an") are rejected.ByRelevance:default,thecategoryAPIlandingmatchespagesANY(CATSYMsingleentriesquerywithword,price=0)soareextrafilteredwordsoutaddsoloosely related results rather than narrowing. Search the thing the customer wants (the head noun) andcontaincheckonlythepurchasableproductproducts.namesSetactuallyinclude_stubs=truecontaintoitincludebefore presenting them. Prices and min_price/max_price are both in `currency` — pass the customer's own budget in their own currency; do not convert it. Search results carry NO delivery-scope information. Food, hotel ⟨48 unchanged words⟩ 3 chars. - category (Optional[str]):CategoryAfilterfacet(e.g.name'Birthday',from'Flowers')a previous search's facets.categories - limit (int): Results per page, ⟨24 unchanged words⟩ [float]): Min price (inclusive) inthe requested currency`currency` - max_price (Optional[float]): Max price (inclusive) inthe requested currency`currency` - in_stock_only (bool): Restrict to in-stock ⟨12 unchanged words⟩ 'newest' | 'bestseller' - include_stubs (bool):Include category landing pagesDeprecated,(defaultnofalse)effect - response_format (str): 'markdown' (default) ⟨13 unchanged words⟩ ": [ { "id": str, "type": "product", "name": str, "summary": str, " ⟨35 unchanged words⟩ } ], "next_cursor": str | null,# null after page 3 even if upstream has more "total_estimate": int, # index hits for the query words (any-word match) "applied_filters": {"q": str, "limitcategory":intstr, "in_stock_onlycurrency":boolstr, ...}, "facets": {"categories": [{"name": str, "count": int}]}, "category_filter_dropped": str, # only when `category` was not a facet here "valid_categories": [str] # ...and the facet names that are } Error: "Error: <message>" or " ⟨7 unchanged words⟩
⟨11 unchanged words⟩ ,"default":null,"description":"Filter bySUBCATEGORYa SEARCH FACETNAMEname.—Everythesearchsameresponsevaluelists thewebsite's searchvalidusesonesinfor its`subcat=` parameter and shows in itswordsleftundersidebar,facets.categories (e.g. 'Kapruka Cakes', 'Fresh Flowers','Birthday', 'Greeting Cards', 'Cake And Flower'
⟨155 unchanged words⟩ LKR (default), USD, GBP, AUD,CAD,EUR - type (Optional[str]): Optional ⟨128 unchanged words⟩
⟨11 unchanged words⟩ Supported: LKR, USD, GBP, AUD,CAD,EUR","title":"Currency","type":" ⟨76 unchanged words⟩
⟨138 unchanged words⟩ LKR (default), USD, GBP, AUD,CAD,EUR - courtesy ({currency, per_usd}, optional ⟨93 unchanged words⟩
⟨218 unchanged words⟩ currency: LKR, USD, GBP, AUD,CAD,EUR.","title":"Currency","type":" ⟨64 unchanged words⟩
⟨195 unchanged words⟩ LKR (default), USD, GBP, AUD,CAD,EUR - min_price (Optional[float]): Min ⟨138 unchanged words⟩
⟨124 unchanged words⟩ Supported: LKR, USD, GBP, AUD,CAD,EUR","title":"Currency","type":" ⟨202 unchanged words⟩
{"$defs":{"CartItem":{"additionalProperties":false,"description":"One cart line — EITHER a catalogue product OR a quoted custom cake.\n\nCatalogue line: {\"product_id\": \"...\", \"quantity\": 1, \"icing_text\": \"...\"}\nCustom cake line: {\"custom_cake_request_id\": \"...\", \"phone\": \"+9477...\"}\nThe custom cake line is turned into the staff-quoted cake server-side\n(name, picture, price); quantity is always 1 and no price is ever sent.","properties":{"custom_cake_request_id":{"anyOf":[{"maxLength":80,"minLength":6,"type":"string"},{"type":"null"}],"default":null,"description":"request_id of a custom cake that kapruka_custom_cake_status reports as 'quoted'. Orders the staff-quoted cake (quantity 1). Requires `phone`.","title":"Custom Cake Request Id"},"icing_text":{"anyOf":[{"maxLength":120, ⟨7 unchanged words⟩ "Cake icing text. Silently ignored for non-cake products. Catalogue lines only.","title":"Icing Text"},"product_idphone":{"anyOf":[{"maxLength":30,"minLength":7,"type":"string"},{"type":"null"}],"default":null,"description":"KaprukaTheproductcustomer.phoneIDthe custom cake request was made with (e.g.custom'cakeXX000000'cake lines only).","title":"Phone"},"product_id":{"anyOf":[{"maxLength":80,"minLength":3,"titletype":"Product Idstring"},{"type":"stringnull"}],"quantity":{"default":1null,"description":"QuantityKapruka product ID (1–99e.g. 'cakeXX000000'). Catalogue line.","title":"Product Id"},"quantity":{"anyOf":[{"maximum":99,"minimum":1,"titletype":"Quantityinteger"},{"type":"integernull"}}],"requireddefault":[null,"product_iddescription"]:"Quantity (1–99, default 1). Catalogue lines only.","title":"Quantity"}},"title":"CartItem","type":"object" ⟨321 unchanged words⟩