Skip to main content
Glama

Server Details

Free public MCP server for Kapruka.com — Sri Lanka's largest e-commerce platform.

If you are the author of this connector, you can claim ownership with GitHub, an HTTP challenge, or a DNS record. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
kapruka/mcp
GitHub Stars
21
Server Listing
Kapruka MCP Server

TDQS

A4.5/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct action: browsing (search/get/categories), delivery feasibility (check_delivery/list_delivery_cities), ordering (create_order), tracking (track_order), and card rendering (render_options_card). Even the two delivery-related tools are clearly separated by purpose—one lists cities, the other checks availability and rates.

Naming Consistency5/5

All tool names follow the consistent pattern `kapruka_` + snake_case `verb_noun`: check_delivery, create_order, get_product, list_categories, list_delivery_cities, render_options_card, search_products, track_order. The verb style is uniform and makes the action of each tool predictable.

Tool Count5/5

Eight tools is well-scoped for a commerce server covering product discovery, delivery checks, order creation, order tracking, and a chat-focused options card renderer. Every tool serves a distinct step in the shopping workflow without redundancy or bloat.

Completeness3/5

The main customer journey from search to order creation to tracking is covered. However, `kapruka_create_order` references `kapruka_custom_cake_status` and `kapruka_custom_cake_request`, which are not part of this tool set, leaving the custom-cake flow as a dead end for agents that follow the documented workflow.

Available Tools

8 tools
kapruka_check_deliveryA
Read-only
Inspect

Check whether Kapruka can deliver to a given city on a given date, and at what rate.

Returns the flat delivery rate (LKR), whether the requested date is available,
and — if not — the next available date plus reason. Kapruka delivers as a
single shipment per order at one flat rate regardless of item count.

Pass `product_id` whenever the customer has named a product: the answer then
also checks that ITEM's delivery scope (restaurant food, hotel cakes and
liquor only reach selected cities, typically the Colombo area). With a
product_id, `available` is true only if the date is open AND the item is
deliverable to that city. When `item_deliverable` is false, offer the
customer one of the returned `deliverable_cities` or an island-wide
alternative — do not attempt kapruka_create_order with the same city, it
will be rejected. An unknown product_id is silently ignored (no item fields
in the result), so check `item_deliverable` is present before relying on it.

Perishable codes (CAKE*, FLOWER*, COMBO*) additionally get a freshness
warning when the chosen delivery date is more than 1 day out.

Args:
    params (CheckDeliveryInput):
        - city (str): Canonical city name (e.g. 'Colombo 03', 'Galle')
        - delivery_date (Optional[str]): YYYY-MM-DD; defaults to today (LK time)
        - product_id (Optional[str]): Check the city against this item's delivery scope
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Delivery feasibility + rate in the requested format.

    JSON schema:
    {
      "city": str,
      "now": str,                       # ISO timestamp, Sri Lanka time
      "checked_date": str,              # YYYY-MM-DD
      "available": bool,                # date open AND (if product_id) item deliverable
      "rate": number,                   # flat LKR rate per order
      "currency": "LKR",
      "reason": str | null,             # date-block message, else "This item is not delivered to <City>."
      "next_available_date": str|null,  # only for date blocks
      "item_deliverable": bool,         # only when product_id resolved to a real product
      "deliverable_cities": [str],      # only when item_deliverable=false (capped at 60)
      "perishable_warning": str | null  # populated when product_id is perishable
    }
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnlyHint/openWorldHint, and the description adds substantial behavior beyond them: single flat rate regardless of item count, unknown product_id silently ignored, deliverable_cities capped at 60, next_available_date only present for date blocks, and freshness warnings for CAKE*/FLOWER*/COMBO* codes. These are non-obvious traits an agent must know to interpret results correctly.

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

Conciseness4/5

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

Front-loaded with purpose and returns, then usage rules, then Args — a sensible ordering. It is longer than necessary because the full JSON return schema is reproduced inline despite an output schema existing, making the Returns block partially redundant.

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?

Given a read-only lookup with conditional output fields, the description covers the decision branches (date block vs item scope vs unknown product), the rate model, and the follow-up action. Nothing an agent needs to avoid a wrong promise or a rejected order is missing.

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?

The Args section restates the schema's parameter documentation (city format, ISO date defaulting to today) and adds semantic depth on product_id — that it scopes the city check to the item and that an unresolvable ID is silently dropped. Context reports 0% schema coverage, so this compensation is valuable, though the city/date/response_format lines largely mirror the schema text.

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?

Opens with a specific verb+resource+scope: 'Check whether Kapruka can deliver to a given city on a given date, and at what rate.' It also distinguishes itself from siblings by warning that kapruka_create_order will be rejected for the same city, so an agent can route correctly without opening other schemas.

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?

States explicit when-to-use ('Pass product_id whenever the customer has named a product') and what to do when the answer is negative ('offer the customer one of the returned deliverable_cities or an island-wide alternative — do not attempt kapruka_create_order'). Also gives the fallback path if product_id is unknown, which is a genuine decision rule.

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

kapruka_create_orderA
Idempotent
Inspect

Create a guest-checkout order on Kapruka and return a click-to-pay link.

Builds a Kapruka order from the supplied cart + recipient + delivery + sender,
then returns a checkout URL the customer opens in a browser to complete payment.
No Kapruka account is required. Prices are locked for the lifetime of the link
(60 minutes) — the customer pays exactly the quoted grand total even if the
catalog price changes meanwhile.

Free public tier limits: 30 orders per hour per client IP. Cart up to 30 items,
quantity up to 99 per item. A fresh idempotency key is generated per call so
retries on transient errors return the same checkout URL rather than duplicates.

Args:
    params (CreateOrderInput):
        - cart (list[CartItem]): 1–30 lines. Catalogue 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 (E.164 +9477… or local 077…)
        - delivery (Delivery): address, city (must be Kapruka-deliverable — use kapruka_list_delivery_cities), location_type (house/apartment/office/other, default house), date (YYYY-MM-DD, today-or-future Asia/Colombo), optional instructions
        - sender (Sender): name + anonymous flag
        - gift_message (Optional[str]): Up to 300 chars
        - currency (str): LKR (default), USD, GBP, AUD, CAD, EUR
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Order confirmation with checkout URL.

    JSON schema:
    {
      "checkout_url": str,           # Open in browser to pay (no login required)
      "order_ref": str,              # e.g. "ORD-20260520-7823"
      "order_id": str,               # id used by the bank-deposit flow
      "summary": {
        "items_total":   number,
        "delivery_fee":  number,
        "addons_total":  number,
        "grand_total":   number,     # items_total + delivery_fee + addons_total
        "currency":      str
      },
      "expires_at": str              # ISO 8601 — link stops working after this
    }

    Error: "Error (<code>): <message>" on failure. Common codes:
      empty_cart, missing_field, past_delivery_date, product_not_found,
      product_out_of_stock, city_not_deliverable (city not 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.

    city_not_deliverable_for_item (HTTP 422): at least one cart item (food /
    hotel cake / liquor) cannot reach delivery.city. NOTHING is created — the
    API never places a partial order and neither should you. The error text
    names every blocking item and lists the cities the whole cart CAN go to.
    Tell the customer which item blocks the order and offer to (a) change the
    city to one of those, or (b) remove/replace that item. Never retry with
    the same city. Avoid this entirely by calling kapruka_check_delivery with
    `product_id` for each limited item before ordering.
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=false, idempotentHint=true), the description discloses critical runtime behavior: prices are locked for 60 minutes, a fresh idempotency key prevents duplicate orders, free-tier limits apply, and the API never creates partial orders on delivery failures. It explains error codes such as city_not_deliverable_for_item and tells the agent exactly what to do in that case. No contradiction with annotations.

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

Conciseness5/5

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

The description is long but densely informative, with a clear top-line summary followed by structured Args and Returns sections. Every paragraph adds operational value: limits, idempotency, error codes, and customer-handling advice. The most important behavioral facts are front-loaded.

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?

For a complex order-creation tool, the description covers all necessary context: input semantics, price locking, rate limits, idempotency, return schema, error codes, and recovery steps. It also references the relevant sibling tools for pre-flight checks, making the full workflow discoverable in one place.

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

Parameters5/5

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

Even though the schema already documents parameters, the description adds essential meaning: cart lines can be mixed catalogue and custom-cake items, custom cake lines require a quoted request_id and phone and never include a price, delivery.city must be Kapruka-deliverable, and response_format controls markdown vs JSON output. It also explains the semantic distinction between city_not_deliverable and city_not_deliverable_for_item.

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 description opens with a specific verb and resource: 'Create a guest-checkout order on Kapruka and return a click-to-pay link.' It immediately states the core behavior, what is returned, and the key constraints (no account required, 60-minute price lock), making the tool's purpose unmistakable and distinct from the sibling tools.

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?

The description gives concrete when-to-use guidance: place a custom cake order only after the customer accepts the quoted total, verify deliverability with kapruka_list_delivery_cities and kapruka_check_delivery before ordering, and never retry with the same city after a city_not_deliverable_for_item error. It also clearly states when not to proceed, such as when a quote is not ready or expired.

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

kapruka_get_productA
Read-onlyIdempotent
Inspect

Fetch full details for a single Kapruka product by its product ID.

Returns name, description, price (with optional currency conversion), stock status,
images, variants, shipping info, delivery scope, and a direct product URL.

Delivery scope: most gifts ship island-wide, but restaurant food, hotel cakes
and liquor only reach a limited city set (typically the Colombo area). The
`delivery` object is the authority — search results do NOT carry it. When
`delivery.island_wide` is false, tell the customer up front that the item is
delivered only to selected cities, and confirm their city with
kapruka_check_delivery(city, product_id) before promising anything. If
`deliverable_city_count` exceeds the returned list, the list is truncated —
say "and more", don't treat it as complete.

Note: Some IDs starting with 'CATSYM' are category landing pages, not purchasable
products — this tool will flag those clearly.

Args:
    params (GetProductInput):
        - product_id (str): Kapruka product ID (e.g. 'cakeXX000000')
        - currency (str): Price currency — LKR (default), USD, GBP, AUD, CAD, EUR
        - type (Optional[str]): Optional type hint (e.g. 'specialgifts')
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Product details in the requested format.

    JSON schema:
    {
      "id": str,
      "name": str,
      "description": str,
      "summary": str,
      "price": {"amount": float, "currency": str},
      "compare_at_price": {"amount": float, "currency": str} | null,
      "in_stock": bool,
      "stock_level": str,           # "low" | "medium" | "high"
      "category": {"id": str, "name": str, "slug": str, "path": str},
      "variants": [{"id": str, "name": str, "sku": str, "price": {...},
                    "in_stock": bool, "stock_level": str, "attributes": {...}}],
      "images": [str],              # list of full-resolution image URLs
      "attributes": {"type": str, "subtype": str, "weight": str, "vendor": str},
      "shipping": {"ships_from": str, "ships_internationally": bool, "restricted_countries": [str]},
      "delivery": {
        "island_wide": bool,
        "deliverable_city_count": int,   # only when island_wide=false; TRUE total
        "deliverable_cities": [str]      # only when island_wide=false; capped at 60
      },
      "rating": null,
      "url": str
    }

    Error: "Error: <message>" on failure.
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so safety is covered. The description goes well beyond that: it explains delivery scope rules, that the `delivery` object is authoritative, how to handle truncated city lists ('say "and more"'), and that CATSYM IDs are flagged as non-products. This is rich operational context.

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 front-loaded with the core purpose and behavioral guidance, but includes redundant 'Args' and 'Returns' sections that duplicate the input schema and output schema. These sections add length without value, lowering the conciseness score.

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?

Given the tool's complexity (delivery quirks, truncated city lists, special CATSYM IDs) and the presence of a detailed output schema, the description covers everything an agent needs to interpret results and act correctly. Error format is also noted.

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

Parameters3/5

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

The input schema already includes descriptions for all four parameters (type, currency, product_id, response_format), giving high effective coverage. The description's 'Args' section repeats the same examples and accepted values without adding new meaning, so baseline 3 is appropriate.

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?

States a specific verb ('Fetch full details') and resource ('a single Kapruka product'), and distinguishes itself from siblings by scope ('single product by its product ID') and special handling ('CATSYM' IDs are category pages). An agent can immediately tell this is the detail-lookup tool, not a search or list tool.

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?

Explicitly names the alternative tool kapruka_check_delivery and the condition for using it ('confirm their city with kapruka_check_delivery(city, product_id) before promising anything'). It also clarifies that search results lack the delivery object, implying this tool is for post-search detail retrieval. No ambiguity about when to use it.

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

kapruka_list_categoriesA
Read-onlyIdempotent
Inspect

List top-level Kapruka product categories by name with browse URLs.

Returns category names (usable as the `category` filter on kapruka_search_products)
plus the public Kapruka.com URL for each category landing page — useful for shopping
agents that want to send users directly to a category to browse. Internal IDs and
product counts are not exposed. Results are cached for 30 minutes server-side.

Args:
    params (ListCategoriesInput):
        - depth (int): Sub-category levels to include, 1 or 2 (default 1)
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Category tree in the requested format.

    JSON schema:
    {
      "categories": [
        {
          "name": str,
          "url": str,                  # kapruka.com category landing page
          "children": [{"name": str, "url": str, "children": [...]}]
        }
      ]
    }

    Error: "Error: <message>" on failure.
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

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

Beyond annotations (readOnlyHint, etc.), the description discloses that 'Internal IDs and product counts are not exposed' and 'Results are cached for 30 minutes server-side.' It also details the error format, adding valuable behavioral context.

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

Conciseness4/5

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

The description is well-structured with a clear summary, Args, Returns, and error format. It is slightly long due to the embedded JSON schema, but each section contributes to usability.

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?

All relevant aspects are covered: purpose, parameter semantics, output schema, limitations, caching, and error handling. The cross-reference to kapruka_search_products aids contextual understanding within the sibling set.

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

Parameters3/5

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

The description's Args section restates the schema's parameter descriptions without adding new meaning. The schema already fully documents depth and response_format, so the baseline of 3 applies.

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 description clearly states the tool's function: 'List top-level Kapruka product categories by name with browse URLs.' It also distinguishes itself from siblings by noting the returned names are usable as a filter on kapruka_search_products, making its purpose specific and non-overlapping.

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

Usage Guidelines4/5

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

Guidance is provided: 'useful for shopping agents that want to send users directly to a category to browse' and relationships to kapruka_search_products are mentioned. While it doesn't explicitly state when not to use it, the context strongly implies its role versus searching.

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

kapruka_list_delivery_citiesA
Read-onlyIdempotent
Inspect

List or search Sri Lankan cities Kapruka delivers to.

Use the `query` param to filter (e.g. "colombo" → all Colombo zones,
"anur" → Anuradhapura). Without a query you get the first 25 cities
alphabetically, which is rarely what an agent needs — pass a query.

Returns canonical city names (use these as the `city` argument to
kapruka_check_delivery) plus any common aliases / vernacular spellings.

Args:
    params (ListDeliveryCitiesInput):
        - query (Optional[str]): Partial match filter
        - limit (int): Max results, 1–50 (default 25)
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Cities list in the requested format.

    JSON schema:
    {
      "cities": [{"name": str, "aliases": [str]}],
      "total_matched": int,
      "showing": int
    }
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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

Adds substantial behavioral detail beyond annotations: default shows first 25 cities alphabetically, query enables partial case-insensitive match, response_format can be markdown or json, and returns canonical names plus aliases. The caveat about the default being rarely needed is honest and useful.

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

Conciseness5/5

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

Well-structured and front-loaded: opening purpose, usage guidance, Args section, and Returns with JSON schema. Each sentence contributes relevant information without unnecessary verbosity.

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?

Given the tool's list/search functionality and available output schema, the description covers default behavior, filtering, response formats, and return structure. It even includes a JSON schema excerpt, making it complete for an agent to call 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?

The description restates parameter names and types, but also adds illustrative examples and meaning beyond the schema. It explains the query behavior with concrete examples and clarifies that returned names should be used as the `city` argument, enriching parameter semantics.

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?

Clearly states it lists or searches Sri Lankan cities Kapruka delivers to, with a specific verb (list/search) and resource (cities). It distinguishes from sibling kapruka_check_delivery by noting it returns canonical city names to use as the `city` argument for that tool.

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

Usage Guidelines4/5

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

Provides explicit usage guidance: warns that without a query the default alphabetical limit is rarely what an agent needs, and gives example filters ('colombo' → Colombo zones, 'anur' → Anuradhapura). It implies the relationship to kapruka_check_delivery but does not state when to avoid using this tool.

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

kapruka_render_options_cardA
Read-onlyIdempotent
Inspect

Render 1-4 products as ONE shareable JPEG "menu" card and return its URL.

The card shows each product's photo with a big numbered badge (the ref you
assign), and its name + price printed under the photo. Built for chat
commerce (WhatsApp): send the image, tell the customer "reply 1, 2 or 3",
and they pick without opening links. No AI is involved — the image is
server-composited from the live catalog data, so prices match what the
product tools return.

Ref numbering contract: refs are yours to assign — use sequential numbers
per conversation and NEVER reuse one (if the first card was 1-3, the next
card starts at 4). A number must keep meaning the same product for the whole
conversation.

Args:
    params (RenderOptionsCardInput):
        - items (list[CardProduct]): 1-4 of {product_id, ref}
        - currency (str): LKR (default), 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": str,              # public JPEG URL — send this as the image
      "items": [{"ref": int, "product_id": str, "name": str,
                  "price": {"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 failed to load (omitted from card)
    }

    Error: "Error: <message>" when no product could be loaded.
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

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

Annotations declare readOnly=true, openWorld=true, idempotent=true, destructive=false. The description adds behavior beyond annotations: server-side compositing from live catalog data, no AI involvement, ref numbering contract, 'unavailable' product handling, and exact error string format. It also explains the courtesy echo behavior. This meaningfully enriches the annotation-only picture.

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

Conciseness5/5

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

The description is compact but high-value: a one-sentence core, a short context paragraph, a clear ref-numbering contract, a concise args section, and a return structure. Every section earns its place, and critical constraints (never reuse refs, courtesy only applies to USD, unavailable handling) are front-loaded or highlighted.

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?

The description covers the output format (card_url, items, courtesy, unavailable), the error format, the ref-numbering contract, the courtesy rate echo behavior, and how the card should be used. Combined with the detailed input schema and annotations, there is no missing information an agent needs to call this correctly.

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

Parameters3/5

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

Schema description coverage is 0%, and the nested schema objects (CardProduct, Courtesy) already document parameters well. The description adds high-level meaning for `items` (the card display and ref badges), `currency` (listed options), and `courtesy` (echoed caller's rate), but much of the semantic detail lives in the input schema itself. The description does not repeat or expand on footer_note semantics beyond the schema. Given the rich schema, this is adequate.

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?

Description states a specific verb+resource ('Render 1-4 products as ONE shareable JPEG menu card and return its URL'), plus the numbered-badge interaction contract for chat commerce. It clearly distinguishes itself from product lookup tools by emphasizing the composite image output.

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

Usage Guidelines4/5

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

The description explains exactly when this tool is appropriate: when presenting product choices in chat commerce where customers reply with numbers. It doesn't explicitly name alternative tools to use instead in other contexts, but its use case (WhatsApp chat commerce) is sufficiently distinct and the sibling list makes alternatives visible.

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

kapruka_search_productsA
Read-onlyIdempotent
Inspect

Search for products on Kapruka.com by keyword, with optional category filter and pagination.

Returns a ranked list of matching products with prices, stock status, images, and URLs.
Supports cursor-based pagination — pass next_cursor from one response into the next call.
Pagination is capped at 3 pages per query to discourage catalog enumeration; for broader
discovery, refine the query or filter by category instead.

Queries must be at least 3 characters and contain specific terms — pure stopword queries
(e.g. "the", "a an") are rejected.

By default, category landing pages (CATSYM entries with price=0) are filtered out so results
contain only purchasable products. Set include_stubs=true to include them.

Search results carry NO delivery-scope information. Food, hotel cakes and liquor
are delivered only to selected cities — never infer deliverability from a search
hit. Before quoting delivery on a specific item, call kapruka_get_product (read
`delivery.island_wide`) or kapruka_check_delivery with `product_id`.

Args:
    params (SearchProductsInput):
        - q (str): Search query (e.g. 'birthday cake', 'roses', 'tea gift'). Min 3 chars.
        - category (Optional[str]): Category filter (e.g. 'Birthday', 'Flowers')
        - limit (int): Results per page, 1–50 (default 10)
        - cursor (Optional[str]): Pagination cursor from previous response
        - currency (str): LKR (default), USD, GBP, AUD, CAD, EUR
        - min_price (Optional[float]): Min price (inclusive) in the requested currency
        - max_price (Optional[float]): Max price (inclusive) in the requested currency
        - in_stock_only (bool): Restrict to in-stock items (default false)
        - sort (str): 'relevance' | 'price_asc' | 'price_desc' | 'newest' | 'bestseller'
        - include_stubs (bool): Include category landing pages (default false)
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Search results in the requested format.

    JSON schema:
    {
      "results": [
        {
          "id": str,
          "name": str,
          "summary": str,
          "price": {"amount": float | null, "currency": str},
          "compare_at_price": {"amount": float, "currency": str} | null,
          "in_stock": bool,
          "stock_level": str,
          "image_url": str | null,
          "category": {"id": str, "name": str, "slug": str},
          "rating": null,
          "ships_internationally": bool,
          "url": str
        }
      ],
      "next_cursor": str | null,    # null after page 3 even if upstream has more
      "applied_filters": {"q": str, "limit": int, "in_stock_only": bool}
    }

    Error: "Error: <message>" or "No products found for '<query>'" on failure.
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

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

Even though annotations already declare readOnlyHint, openWorldHint, and idempotentHint, the description adds significant non-obvious behaviors: pagination is capped at 3 pages, category landing pages are filtered by default, stopword-only queries are rejected, and deliverability must never be inferred from search results. These traits materially affect how an agent should interpret and act on results.

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

Conciseness4/5

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

The description is long but well-organized: a one-line purpose, early warnings about pagination and query constraints, then structured Args and Returns sections. Some redundancy exists because the Args block repeats nested schema content and the return narrative duplicates the output schema, so it is not maximally compressed.

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?

For a search tool with many parameters, the description covers input constraints, pagination behavior, result format with JSON schema, error strings, and cross-tool delivery caveats. It also names sibling tools for follow-up actions, leaving no critical gap for an agent deciding how and when to call it.

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?

The description's Args block fully compensates for the reported 0% schema coverage by listing every parameter with type, default, and examples. It adds meaningful behavioral details such as cursor chaining and the include_stubs flag, though much of this information is also present in the nested schema descriptions.

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 description opens with a specific verb and resource: 'Search for products on Kapruka.com by keyword' and immediately states what is returned (prices, stock status, images, URLs). It also mentions pagination and category filtering, making its scope unambiguous relative to siblings like kapruka_get_product and kapruka_list_categories.

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?

The description explicitly tells agents when not to rely on this tool, stating that search results carry no delivery-scope information and directing them to call kapruka_get_product or kapruka_check_delivery before quoting delivery. It also discourages catalog enumeration by capping pagination and advising refinement or category filtering instead.

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

kapruka_track_orderA
Read-only
Inspect

Look up status and delivery progress for a Kapruka order by order number.

Returns current status (received / confirmed / out-for-delivery / delivered /
cancelled), the recipient and delivery details on file, a timestamped progress
timeline, the cart contents, and flags for whether a delivery photo or video is
available. Use this after a customer has placed and paid for an order and reads
back the order number from their confirmation email or the order complete page.

The order number is NOT the `order_ref` returned by kapruka_create_order
(which is the pre-payment checkout reference). Once the customer completes
payment in the browser, Kapruka emails them a separate order number — that
is what this tool expects.

Args:
    params (TrackOrderInput):
        - order_number (str): Kapruka order number (e.g. 'VIMP34456CB2')
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Order tracking details in the requested format.

    JSON schema:
    {
      "order_number": str,
      "pnref": str,                 # internal payment reference (numeric; not the same as order_number)
      "status": str,                # received | confirmed | shipped | delivered | cancelled | ...
      "status_display": str,        # human label
      "order_date": str,            # human-formatted, Asia/Colombo
      "delivery_date": str,         # human-formatted
      "shipped_date": str | null,
      "amount": str,                # LKR string (e.g. "15500.00")
      "payment_method": str,
      "comments": str | null,
      "recipient": {"name": str, "phone": str, "address": str, "city": str},
      "greeting_message": str | null,
      "special_instructions": str | null,
      "progress": [{"step": str, "timestamp": str}],
      "live_tracking_available": bool,
      "has_delivery_video": bool,
      "has_delivery_photo": bool,
      "items": [{"product_id": str, "name": str, "quantity": int, "selling_price": float}]
    }

    Error: "Error: <message>" on failure (e.g. order not found).
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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

The description goes far beyond the annotations by detailing the exact statuses returned, the contents of the progress timeline, availability of delivery photo/video flags, and the error message format. Even though readOnlyHint and destructiveHint are already provided, the description adds meaningful behavioral context (e.g., live_tracking_available boolean, payment reference field) that helps an agent anticipate results.

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

Conciseness5/5

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

The description is well-organized: it starts with the core purpose, provides usage context, lists parameters, and includes a return schema. Every sentence contributes value, and the structure makes it easy to scan. The embedded JSON schema is verbose but justified given the complex return payload.

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?

Given the tool's complexity (multiple statuses, nested recipient/items objects, error handling), the description is comprehensive. It explains when to use it, what input to provide, what output to expect, and includes the caveat about order_ref. The annotations and detailed schema round out the context, making the tool fully actionable.

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

Parameters3/5

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

The description's Args section essentially mirrors the input schema, which already contains detailed descriptions for both parameters, including the crucial order_ref distinction. Thus, the description adds little new semantic meaning beyond what the schema provides. The example format ('VIMP34456CB2') is helpful but not a significant increment.

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 description uses a specific verb ('Look up') and resource ('status and delivery progress for a Kapruka order by order number'), clearly distinguishing it from sibling tools like kapruka_create_order. It also outlines the exact output, making the purpose unmistakable.

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?

It explicitly states when to use the tool ('after a customer has placed and paid for an order and reads back the order number from their confirmation email or the order complete page') and warns against using the order_ref from kapruka_create_order. This provides clear when-to-use and when-not-to-use guidance, effectively differentiating it from related tools.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool update
    • Changedkapruka_search_products1 field changed
      • changedInput schema / $defs / SearchProductsInput / properties / category / description
        Previous value: -"Filter by category name (e.g. 'Birthday', 'Cakes', 'Flowers'). Case-insensitive."New value: +"Filter by SUBCATEGORY FACET 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') 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`."
  2. 1 tool update
    • Changedkapruka_render_options_card3 fields changed
      • addedInput schema / $defs / Courtesy
        Added value: +{
        +  "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"
        +}
      • addedInput schema / $defs / RenderOptionsCardInput / properties / courtesy
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/Courtesy"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional: print '≈ <home currency>' under each USD price (see Courtesy). Ignored unless currency is USD."
        +}
      • addedInput schema / $defs / RenderOptionsCardInput / properties / footer_note
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 60,
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional short note appended to the footer's reply hint, e.g. 'Checkout charges USD'.",
        +  "title": "Footer Note"
        +}
  3. 1 tool update
    • Changedkapruka_create_order17 fields changed
      • addedInput schema / $defs / CartItem / description
        Added value: +"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."
      • addedInput schema / $defs / CartItem / properties / custom_cake_request_id
        Added value: +{
        +  "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"
        +}
      • changedInput schema / $defs / CartItem / properties / icing_text / description
        Previous value: -"Cake icing text. Silently ignored for non-cake products."New value: +"Cake icing text. Silently ignored for non-cake products. Catalogue lines only."
      • addedInput schema / $defs / CartItem / properties / phone
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxLength": 30,
        +      "minLength": 7,
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "The customer.phone the custom cake request was made with (custom cake lines only).",
        +  "title": "Phone"
        +}
      • addedInput schema / $defs / CartItem / properties / product_id / anyOf
        Added value: +[
        +  {
        +    "maxLength": 80,
        +    "minLength": 3,
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / $defs / CartItem / properties / product_id / default
        Added value: +null
      • changedInput schema / $defs / CartItem / properties / product_id / description
        Previous value: -"Kapruka product ID (e.g. 'cakeXX000000')."New value: +"Kapruka product ID (e.g. 'cakeXX000000'). Catalogue line."
      • removedInput schema / $defs / CartItem / properties / product_id / maxLength
        Removed value: -80
      • removedInput schema / $defs / CartItem / properties / product_id / minLength
        Removed value: -3
      • removedInput schema / $defs / CartItem / properties / product_id / type
        Removed value: -"string"
      • addedInput schema / $defs / CartItem / properties / quantity / anyOf
        Added value: +[
        +  {
        +    "maximum": 99,
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / $defs / CartItem / properties / quantity / default
        Previous value: -1New value: +null
      • changedInput schema / $defs / CartItem / properties / quantity / description
        Previous value: -"Quantity (1–99)."New value: +"Quantity (1–99, default 1). Catalogue lines only."
      • removedInput schema / $defs / CartItem / properties / quantity / maximum
        Removed value: -99
      • removedInput schema / $defs / CartItem / properties / quantity / minimum
        Removed value: -1
      • removedInput schema / $defs / CartItem / properties / quantity / type
        Removed value: -"integer"
      • removedInput schema / $defs / CartItem / required
        Removed value: -[
        -  "product_id"
        -]
  4. 2 tool updates
    • Changedkapruka_check_delivery2 fields changed
      • changedInput schema / $defs / CheckDeliveryInput / properties / product_id / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "maxLength": 80,
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / $defs / CheckDeliveryInput / properties / product_id / description
        Previous value: -"Optional product ID. If provided and the product looks perishable (cake/flower/combo codes), a freshness warning is added when the chosen date is more than 1 day out."New value: +"Product ID to check the city AGAINST THAT ITEM'S delivery scope. Food, hotel cakes and liquor only reach selected cities — always pass this when a customer names a product and a city, and only promise delivery if `available` is true. Also adds a freshness warning for perishable codes (cake/flower/combo) when the date is >1 day out."
    • Changedkapruka_create_order1 field changed
      • changedInput schema / $defs / Delivery / properties / city / description
        Previous value: -"Must be a Kapruka delivery city — use kapruka_list_delivery_cities to look up valid names."New value: +"Must be a Kapruka delivery city (canonical name from kapruka_list_delivery_cities) that EVERY cart item can reach. The order ships as one shipment, so food / hotel cake / liquor items restrict the whole cart to their city set — verify with kapruka_check_delivery(city, product_id) first; otherwise the order is rejected with city_not_deliverable_for_item."
  5. 2 tool updates
    • Changedkapruka_create_order1 field changed
      • changedInput schema / $defs / CartItem / properties / product_id / description
        Previous value: -"Kapruka product ID (e.g. 'cake00ka002034')."New value: +"Kapruka product ID (e.g. 'cakeXX000000')."
    • Changedkapruka_get_product1 field changed
      • changedInput schema / $defs / GetProductInput / properties / product_id / description
        Previous value: -"Kapruka product ID (e.g. 'cake00ka002034', 'EF_PC_CHOC0V2774P00065')"New value: +"Kapruka product ID (e.g. 'cakeXX000000', 'EF_PC_CHOC0V2774P00065')"
  6. 3 tool updates
    • Removedkapruka_customer_addresses
    • Removedkapruka_customer_details
    • Removedkapruka_order_history
  7. 3 tool updates
    • Addedkapruka_customer_addresses
    • Addedkapruka_customer_details
    • Addedkapruka_order_history
  8. 1 tool update
    • Addedkapruka_render_options_card
  9. 1 tool update
    • Addedkapruka_track_order
  10. 1 tool update
    • Addedkapruka_create_order
  11. 5 tool updates
    • First observedkapruka_check_delivery
    • First observedkapruka_get_product
    • First observedkapruka_list_categories
    • First observedkapruka_list_delivery_cities
    • First observedkapruka_search_products

Related MCP Connectors

Related MCP Servers

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.