Skip to Content
Catalog

Catalog

Agents discover products two ways:

  • Global catalog — search across every Artos store in one call. Each result is annotated with the store that sells it, so you can route follow-up cart/checkout calls to the right store.
  • Per-store catalog — browse or look up within a single store once you know its slug.

The global catalog is read-only: there is no cross-store cart. Discover globally, then run a per-store checkout (see Checkout).

Tools

Bridge tool (Path A)Raw UCP tool (Path B)Scope
search_productssearch_catalog @ /mcpGlobal search
lookup_productslookup_catalog @ /mcpResolve by id/handle/SKU/barcode (global)
get_product_globalget_product @ /mcpFull detail by id, any store
view_productget_product @ /s/:slug/mcpFull detail within a store

Two shapes, one catalog

The bridge flattens arguments; raw UCP wraps them. Money differs too — read this before copying filters.

Path A (bridge search_products) — flat args, price in major units (dollars):

{ "query": "running shoes", "filters": { "price": { "max": 100, "currency": "USD" } }, "sort": "price_asc" }

Path B (raw search_catalog) — args wrapped under catalog, price in minor units (integer cents), and meta["ucp-agent"].profile is required on every call:

{ "name": "search_catalog", "arguments": { "catalog": { "query": "running shoes", "filters": { "price": { "max": 10000 } }, "sort": "price_asc" }, "meta": { "ucp-agent": { "profile": "https://your-app.example/.well-known/ucp" } } } }

With the @artos-commerce/ucp-client SDK you skip the envelope and unit conversion entirely — shop.searchProducts({ query, filters }) takes filters in major units (like Path A) and client.callGlobalTool('search_catalog', …) exposes the raw tool when you need it:

const results = await shop.searchProducts({ query: 'running shoes', filters: { price: { max: 100, currency: 'USD' } }, });

Natural language → filters

Map the buyer’s request onto structured filters. A search needs a query and/or filters — calling with only pagination returns nothing.

Buyer saysFilter
”under $100”filters.price.max (dollars on Path A, cents on Path B)
“red ones”filters.attributes: [{ "name": "Color", "value": "Red" }]
”on sale”, “eco-friendly”filters.tags: ["sale"]
”running shoes” (a category)filters.categories: ["shoes"] (fuzzy; partial matches the full taxonomy path)
“from Energy Sport”filters.seller: "energy-sport" (fuzzy: slug, name, or description)
“cheapest first”sort: "price_asc" (price_desc, or newest default)
“include sold out”filters.available: false (out-of-stock hidden by default)

Responses echo facets.categories and facets.sellers. Feed a facet back as a filter to refine (“what categories does this shop carry?” → search with filters.seller, read facets.categories).

Multi-store routing

Global search annotates each product with its seller under the sanctioned UCP extension point metadata.artos_seller:

{ "metadata": { "artos_seller": { "slug": "energy-sport", "name": "Energy Sport", "endpoint": "https://api.artos.sh/s/energy-sport" } } }

Use metadata.artos_seller.slug as the store_slug for create_cart / create_checkout. To buy from multiple shops, run a separate checkout per store.

MCP Apps widgets

On Path A, search_products and view_product carry an MCP App UI resource (_meta.ui.resourceUri) so hosts like Claude render an inline product grid / detail card instead of raw JSON.

Last updated on