Skip to main content
Glama

Price a shopping list for delivery

optimize_delivery
Read-only

Price a whole shopping list at every Israeli online supermarket that delivers to an address, and rank them on what the order actually costs: items + delivery fee + service fee. Call this ONCE with the full list — never price lines separately. This is SuperMCP's shopping-list tool for online supermarket delivery. ASK THE SHOPPER WHERE THEY LIVE BEFORE CALLING, whenever you can get it in the same breath. A city is enough. It is not a detail that sharpens the answer, it usually IS the answer: of the 531 towns whose coverage we hold, 386 are served by exactly one chain. It is also much the cheaper call, comparing the handful of storefronts that reach one town instead of every storefront in the country. Only when you cannot ask, or when showing the range now beats a round trip, call with no destination. It does not fail: it returns status=needs_destination, the same list priced at every storefront in the country, carrying only what an address does not decide — each storefront's shelf prices, its own delivery fee and its minimum order. NOT ONE of them was tested against a service area, so that reply names no cheapest, carries no handoffUrl and is not a recommendation. Quote it as a range, say we do not yet know who delivers to this shopper, ask for their city or street address, then send {continuation, city} to get the storefronts that actually reach them. THE HEADLINE FIGURE IS deliveredTotal, not the item subtotal: a ₪35.90 delivery fee outweighs most price differences between chains. But RANK on deliveredComparableTotal, never on deliveredTotal: totalScope is priced_lines_only, so a storefront that stocks four of your twelve items reports a small deliveredTotal precisely because it cannot fill the basket. Check pricedLines against requestedLines and say when the coverage is partial. A gap has two possible reasons and catalogVisibility says which. 'full_catalogue' means catalogSize is the retailer's complete published price file, so a line it did not price is a line it does not stock. 'partial_index' means WE cannot see the whole shop, because its prices are read off a website that cannot be paged, so the gap may be ours and the shop may well carry the missing items. Say which it is rather than telling a shopper a storefront does not stock something we simply never indexed. Both fields are null when the count has not loaded yet, which is not an empty shop. Read deliveryTerms.confidence before quoting: 'verified' was read from the retailer's own binding terms, 'reported' from a cited secondary source, 'unknown' means no fee is established and the ranking used an assumption (assumedDeliveryFee) that must not be repeated as a price. Anything other than verified or reported withholds the whole quotable tariff page, not just the fee: deliveryFee, freeDeliveryThreshold and nextFeeBreak all come back null together, because all three are read off the page we just declined to stand behind. Never fill one of them in from get_delivery_terms and quote it beside a fee this plan refused to give. minimumOrder is gated differently on purpose, lapsing only once the figure is past its 90-day recheck, so its presence is not evidence the fee beside it can be quoted. deliveryFeeIsFloor=true means the fee is a published lower bound, so quote it as 'from ₪X' and treat deliveredTotal as a minimum. meetsMinimum=false means the order cannot be placed as it stands; report amountToMinimum, the top-up needed. Those plans are still listed, after the orderable ones, so present them as options that need topping up rather than hiding them. Of several branches of one marketplace chain that all sit under their minimum, the one listed is the cheapest that is also nearest to its minimum, so the top-up you report is the smallest on offer there. Rank on cheapestDelivered only if the shopper will happily order twice: it prices missing lines at a market reference. bestSingleOrder is the fullest basket obtainable in one order. Both, and bestVerifiedTerms, carry totals only: find the storefront in plans by serviceSlug for its priced lines. When nextFeeBreak.worthTopUp is true, spending a little more makes the order cheaper overall — say so. A line carrying cheaperAlternative can be met for less AT THE SAME SHOP: it names the product, how many packs, what the line would cost instead, and the saving, promotions included. Every one is cheaper per 100g/ml/piece as well as per line, so it is a genuine saving rather than a smaller pack, and the saving can be quoted as it stands. Offer these unprompted when the shopper cares about price, and never silently swap them in — it is a different product and theirs to choose. Pin one by calling again with its productId. splitOrder, when it is not null, is the same list bought from two shops instead of one, with each leg's items, fees and its own handoffUrl. reason='cheaper' means it saves money after BOTH delivery fees; reason='more_of_the_list' means no one shop stocks everything and the second order fills the gap at extra cost, which saving reports as a negative. Volunteer it unprompted, and say which of the two it is. null means one order is the right answer here. If the shopper says a priced line is wrong, call suggest_similar_products with their Hebrew words and the rejected product_id, then call this tool again with that product_id on the line. Storefronts that cannot serve this basket come back in unavailableStores with a reason. By default only the actionable ones are listed: below_minimum_order, and price_feed_stale for a chain that delivers here but has published no prices for over a fortnight, which is therefore not in plans at all and must not be presented as an option. A plan flagged priceFeedStale is a milder case, over a week old: still worth comparing, but quote it as what the shop last published on priceFeedAsOf. If no storefront inside the fortnight can take the order, the abandoned ones come back in plans rather than leaving the shopper with nothing, and notes says so. unavailableStoresOmitted counts the rest, all ruled out on the address alone. A plan may carry venues: branches of one marketplace chain that priced this basket identically, collapsed into one row. Any slug in it works with get_delivery_terms. venuesOmitted counts further branches of that chain left out because each costs more and fills no line this row is missing. None of their figures are here and this row's are not theirs, so never quote a price for them; list_delivery_options names them all. By default only the recommended storefronts carry a lines breakdown; every other plan reports its totals and pricedLines with lines: []. That is not a gap — re-call with response_detail=standard only if you must compare the same item's price across chains. When the shopper settles on a storefront, give them that plan's handoffUrl: it opens the whole basket as one Hebrew page, every line with its price and its own product link. Hand over that one link rather than the per-line link fields, which leave the shopper opening a tab per item. Say that the page shows the prices this answer was built on.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cityNoCity name in Hebrew or English. Enough for chains that publish a settlement list, not enough for a storefront whose area is a polygon or a depot radius.
nearNo'lat,lng' string, e.g. '32.078,34.774'. Do not combine with address.
itemsNoThe shopping list. Required unless resuming with a continuation.
intentNoThe shopper's own framing of this shop, in their own words, e.g. 'ברביקיו ל-12 אנשים'. Not a summary of the item list — pass what THEY said the shop was for. Shown on the handoff page next to what was priced. Optional; omit rather than inventing one.
addressNoDelivery address in Israel, free text, e.g. 'מנדלסון 1, תל אביב'. Preferred: some storefronts publish a service area that only a street address can be tested against.
answersNoOne answer per question from the needs_confirmation reply.
slot_typeNoOnly two slots exist here: standard (default) is delivery to the door, pickup is click-and-collect, which is cheaper at the chains that offer it but means the shopper travels. Anything else is rejected.
preferenceNocheapest takes the lowest delivered total outright; balanced (default) prefers a storefront whose delivery terms we verified when the money is close.
membershipsNoMembership or card the shopper holds that unlocks a cheaper rate, e.g. ['credit_card'] for a Rami Levy card. Without it the public rate is quoted.
continuationNoOpaque token from a needs_confirmation, preview or needs_destination reply. The shopping list travels inside it, so send it with answers, or with the city or address that answers needs_destination, and nothing else.
include_clubNoApply loyalty-club item prices. Default true; they are flagged clubOnly.
include_couponNoApply coupon item prices. Default true; they are flagged couponOnly.
resolution_modeNofast (default) makes best-effort product choices and reports them in assumptions, each carrying a kind: generic_default (the line named no particular product, so the everyday one is the answer) needs no warning, substitution (the line named a product and got another) does. strict asks before choosing, but only where WE are unsure, so it prices a confidently-wrong line without stopping. preview stops for YOU: it returns status=preview with items and assumptions and prices nothing, then send its continuation on its own to price the same list without resolving it twice. Worth it on a long or unusual list, where pricing every storefront is the expensive half and a wrong pick otherwise costs a second full call.
response_detailNosummary (default) returns the line-by-line breakdown only for the storefronts the recommendations name; it folds marketplace venues that priced this basket identically into one plan carrying venues, drops the branches of a chain that cost more and fill no line a kept branch fills, counting them in venuesOmitted, and replaces the out-of-area storefronts with a count. standard adds the lines for every storefront, every venue and the full unavailable list: ask for it only when comparing the same item across chains. debug adds resolution internals.
max_split_storesNoHow many storefronts the returned splitOrder may spread the list over. Default 2. A third adds a third delivery fee, so it only wins when it reaches items the other two do not stock.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / response_detail / description
      Previous value: -"summary (default) returns every storefront's totals and coverage but the line-by-line breakdown only for the storefronts the recommendations name; it also collapses identical marketplace venues into one plan and replaces the out-of-area storefronts with a count. standard adds the lines for every storefront, every venue and the full unavailable list: ask for it only when comparing the same item across chains. debug adds resolution internals."New value: +"summary (default) returns the line-by-line breakdown only for the storefronts the recommendations name; it folds marketplace venues that priced this basket identically into one plan carrying venues, drops the branches of a chain that cost more and fill no line a kept branch fills, counting them in venuesOmitted, and replaces the out-of-area storefronts with a count. standard adds the lines for every storefront, every venue and the full unavailable list: ask for it only when comparing the same item across chains. debug adds resolution internals."
  2. Changed3 schema fields changed
    • addedInput schema / properties / city / minLength
      Added value: +1
    • changedInput schema / properties / continuation / description
      Previous value: -"Opaque token from a needs_confirmation reply. Send with answers and nothing else."New value: +"Opaque token from a needs_confirmation, preview or needs_destination reply. The shopping list travels inside it, so send it with answers, or with the city or address that answers needs_destination, and nothing else."
    • addedInput schema / properties / near / minLength
      Added value: +3
  3. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / pack_qty / type
      Previous value: -"number"New value: +"integer"
  4. Changed7 schema fields changed
    • addedInput schema / properties / intent
      Added value: +{
      +  "description": "The shopper's own framing of this shop, in their own words, e.g. 'ברביקיו ל-12 אנשים'. Not a summary of the item list — pass what THEY said the shop was for. Shown on the handoff page next to what was priced. Optional; omit rather than inventing one.",
      +  "type": "string"
      +}
    • changedInput schema / properties / items / items / properties / amount / description
      Previous value: -"Physical amount, e.g. 1.5 with unit=kg. Mutually exclusive with pack_qty."New value: +"Physical amount, e.g. 1.5 with unit=kg. Also the right field for a count of individual items: 24 with unit='יח' means 24 bottles however they are packaged, and the packs are divided out for you wherever the pack size is known. Where it is not, the count is priced as that many of the chosen listing and the line says so with assumptions reason unit_count_assumed: read it before quoting the total, because a mass or volume is exact where a count had to be guessed at. Mutually exclusive with pack_qty."
    • changedInput schema / properties / items / items / properties / pack_qty / description
      Previous value: -"Number of product packs to buy. Prefer pack_qty alone (no unit). Count units unit/units/יח sent with pack_qty are ignored."New value: +"Number of PACKS to buy, whatever each pack holds. Use it only when the shopper counted packs ('two six-packs', 'three cartons of eggs'). For a count of individual ITEMS ('24 bottles of beer', '40 plates') send amount with unit='יח' instead: a six-pack is one pack and six bottles, and pack_qty=24 there buys 144 bottles. Omit it when the shopper did not say a number: the line is priced as one pack and reported in assumptions. Do not invent a quantity."
    • addedInput schema / properties / max_split_stores
      Added value: +{
      +  "description": "How many storefronts the returned splitOrder may spread the list over. Default 2. A third adds a third delivery fee, so it only wins when it reaches items the other two do not stock.",
      +  "maximum": 3,
      +  "minimum": 2,
      +  "type": "integer"
      +}
    • changedInput schema / properties / resolution_mode / description
      Previous value: -"fast (default) makes best-effort product choices and reports them in assumptions. strict asks before choosing."New value: +"fast (default) makes best-effort product choices and reports them in assumptions, each carrying a kind: generic_default (the line named no particular product, so the everyday one is the answer) needs no warning, substitution (the line named a product and got another) does. strict asks before choosing, but only where WE are unsure, so it prices a confidently-wrong line without stopping. preview stops for YOU: it returns status=preview with items and assumptions and prices nothing, then send its continuation on its own to price the same list without resolving it twice. Worth it on a long or unusual list, where pricing every storefront is the expensive half and a wrong pick otherwise costs a second full call."
    • changedInput schema / properties / resolution_mode / enum
      Previous value: -[
      -  "fast",
      -  "strict"
      -]New value: +[
      +  "fast",
      +  "strict",
      +  "preview"
      +]
    • changedInput schema / properties / response_detail / description
      Previous value: -"summary (default) returns every storefront's totals and coverage but the line-by-line breakdown only for the storefronts the recommendations name. standard adds the lines for every storefront — ask for it only when comparing the same item across chains. debug adds resolution internals."New value: +"summary (default) returns every storefront's totals and coverage but the line-by-line breakdown only for the storefronts the recommendations name; it also collapses identical marketplace venues into one plan and replaces the out-of-area storefronts with a count. standard adds the lines for every storefront, every venue and the full unavailable list: ask for it only when comparing the same item across chains. debug adds resolution internals."
  5. Changed5 schema fields changed
    • addedInput schema / properties / items / items / properties / gtin / maxLength
      Added value: +64
    • addedInput schema / properties / items / items / properties / query / maxLength
      Added value: +200
    • addedInput schema / properties / memberships / items / maxLength
      Added value: +64
    • addedInput schema / properties / memberships / items / minLength
      Added value: +1
    • addedInput schema / properties / memberships / maxItems
      Added value: +10
  6. Changed2 schema fields changed
    • changedInput schema / properties / slot_type / description
      Previous value: -"standard (default) is delivery to the door. pickup is click-and-collect, which is cheaper at chains that offer it but means the shopper travels."New value: +"Only two slots exist here: standard (default) is delivery to the door, pickup is click-and-collect, which is cheaper at the chains that offer it but means the shopper travels. Anything else is rejected."
    • changedInput schema / properties / slot_type / enum
      Previous value: -[
      -  "standard",
      -  "pickup",
      -  "express"
      -]New value: +[
      +  "standard",
      +  "pickup"
      +]
  7. Changed2 schema fields changed
    • addedInput schema / properties / city / maxLength
      Added value: +100
    • addedInput schema / properties / near / maxLength
      Added value: +100
  8. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / query / description
      Previous value: -"Free-text product name."New value: +"Free-text product name, IN HEBREW. The catalogue is Hebrew, and a line is matched on the words the shopper used appearing in the product name, so a Latin brand ('Pampers', 'Coca Cola', 'Osem') matches nothing and the line is dropped as unresolvable. Write פמפרס, קוקה קולה, אוסם. Translate the shopper's wording rather than passing it through: an English shopping list still needs Hebrew queries here. Give a stated fat percentage exactly as they said it (קוטג' 5%), since it is matched exactly and is not guessed at."
  9. Changed1 schema field changed
    • addedInput schema / properties / response_detail
      Added value: +{
      +  "description": "summary (default) returns every storefront's totals and coverage but the line-by-line breakdown only for the storefronts the recommendations name. standard adds the lines for every storefront — ask for it only when comparing the same item across chains. debug adds resolution internals.",
      +  "enum": [
      +    "summary",
      +    "standard",
      +    "debug"
      +  ],
      +  "type": "string"
      +}
  10. First observed

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry readOnlyHint/openWorldHint/destructiveHint; the description carries the full behavioral burden and exceeds it. It discloses the needs_destination status flow, the open-world semantics of catalogVisibility ('partial_index' means WE cannot see the whole shop), trust tiers for deliveryTerms.confidence that gate the whole quotable tariff page, price_feed_stale 'must not be presented as an option', and the continuation-token sequencing. It also warns against silent substitutions ('never silently swap them in') and against quoting assumedDeliveryFee as a real price. Nothing contradicts the read-only/open-world annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is exceptionally long and front-loaded well — purpose first, usage second, then output semantics, then edge cases. But it repeats content already in the rich schema (e.g., response_detail line-breakdown behavior appears both in the enum description and in the tool body), adding redundancy. It is arguably appropriately sized for a 15-parameter tool with no output schema, but it is not concise; several sentences could be tightened without loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description shoulders full responsibility for return-value semantics, and it delivers comprehensively: deliveredTotal vs deliveredComparableTotal ranking, pricedLines/requestedLines coverage checks, catalogVisibility, deliveryTerms.confidence tiers, deliveryFeeIsFloor, meetsMinimum/amountToMinimum, cheapestDelivered/bestSingleOrder/bestVerifiedTerms, nextFeeBreak.worthTopUp, cheaperAlternative, splitOrder reasons, unavailableStores classification, venues/venuesOmitted, handoffUrl and status/continuation values. An agent has everything needed to invoke and interpret the result correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so each of the 15 parameters is already documented — several extensively (the query field's Hebrew requirement, pack_qty vs amount distinction). The description adds value mainly at orchestration level beyond the schema: the continuation-carrying flow ('The shopping list travels inside it'), the response_detail tradeoff tied to comparing items across chains, resolution_mode's preview sequence, and max_split_stores' third-fee tradeoff. This lifts it above the schema-only baseline, though most individual parameter semantics remain the schema's job.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line — 'Price a whole shopping list at every Israeli online supermarket that delivers to an address, and rank them on what the order actually costs: items + delivery fee + service fee' — states a specific verb, resource and scope in one sentence. It differentiates from siblings by name ('This is SuperMCP's shopping-list tool for online supermarket delivery') and later routes to suggest_similar_products, get_delivery_terms and list_delivery_options for adjacent concerns. The title confirms the same purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when/when-not guidance: 'Call this ONCE with the full list — never price lines separately', 'ASK THE SHOPPER WHERE THEY LIVE BEFORE CALLING, whenever you can get it in the same breath', and 'Only when you cannot ask, or when showing the range now beats a round trip, call with no destination.' It names concrete alternatives per condition (suggest_similar_products for a wrong line, get_delivery_terms for terms, list_delivery_options to enumerate venues) and even specifies re-call conditions ('re-call with response_detail=standard only if you must compare the same item's price across chains').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources