Skip to main content

Discover products with Shopify Catalog

Shopify Catalog contains all eligible products sold across merchants on the Shopify platform, serving as a powerful implementation of product discovery in UCP. You can use the Catalog MCP server to search for products and retrieve detailed product information for your AI agent.

This tutorial shows you how to authenticate with the Catalog MCP server, search for products, and apply filters to refine results. In the end you'll arrive at a single selected product variant chosen by a buyer.


In this tutorial, you'll learn to:

  • Search for products across the global Shopify Catalog using natural language queries
  • Apply filters and parameters to refine product search results
  • Extract product variant IDs and shop domains for checkout


Anchor to Step 1: Create a custom catalogStep 1: Create a custom catalog

First, you need to create a catalog. Catalogs can allow agents to discover products across the entire Shopify platform, or some subset of more relevant filtered results, depending on the needs of your buyers.

  1. In Dev Dashboard click Catalogs from the sidebar.

  2. Click Create a catalog.

  3. The resulting screen provides many different options and overrides for the catalog. For now keep the defaults, which place no bounds on the price of results discovered across all of Shopify's products.

    Dev Dashboard catalog configuration with filter options
  4. Click Save catalog in the top right hand corner.

  5. When you return to the Catalogs landing page, click to Copy URL. It has the form https://discover.shopifyapps.com/global/v1/search/{your_catalog_id}. You can use this URL directly with the Catalog REST API, or the your_catalog_id as shown below when making tool calls.

  6. Add your your_catalog_id to the .env file you previously created:

    .env

    BEARER_TOKEN={your_token}
    CATALOG_ID={your_catalog_id}
    Sensitive variables

    Don't commit this file.


Anchor to Step 2: Search the CatalogStep 2: Search the Catalog

Next, create a script to search your new catalog using the Catalog MCP server with the search_global_products tool:

  1. Create a search-catalog.js file that sends a query to the Catalog MCP server:

    import 'dotenv/config';

    const bearerToken = process.env.BEARER_TOKEN;
    let catalogId = process.env.CATALOG_ID;

    fetch('https://discover.shopifyapps.com/global/mcp', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${bearerToken}`
    },
    body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'tools/call',
    id: 1,
    params: {
    name: 'search_global_products',
    arguments: {
    saved_catalog: catalogId,
    query: 'I need a crewneck sweater',
    context: 'buyer looking for sustainable fashion',
    limit: 3
    }
    }
    })
    })
    .then(res => res.json())
    .then(data => {
    if (data && data.result?.content?.[0]?.text) {
    // Parse the stringified text field
    data.result.content[0].text = JSON.parse(data.result.content[0].text);
    }
    if (data) {
    console.log(JSON.stringify(data, null, 2));
    }
    })
    .catch(err => console.error('Request failed:', err));
    {
    "jsonrpc": "2.0",
    "method": "tools/call",
    "id": 1,
    "params": {
    "name": "search_global_products",
    "arguments": {
    "saved_catalog": "<CATALOG_ID>",
    "query": "I need a crewneck sweater",
    "context": "buyer looking for sustainable fashion",
    "limit": 3
    }
    }
    }
    {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
    "content": [
    {
    "type": "text",
    "text": {
    "offers": [
    {
    "id": "gid://shopify/p/abc123def456",
    "title": "Organic Cotton Crewneck Sweater",
    "description": "A sustainably made crewneck sweater crafted from 100% organic cotton with a relaxed fit.",
    "images": [
    {
    "url": "https://cdn.shopify.com/s/files/example/organic-cotton-crewneck.jpg",
    "altText": "Organic Cotton Crewneck Sweater - EcoWear",
    "product": {
    "id": "gid://shopify/Product/1234567890",
    "title": "Organic Cotton Crewneck Sweater",
    "onlineStoreUrl": "https://ecowear-example.myshopify.com/products/organic-cotton-crewneck?variant=11111111111&_gsid=example123",
    "shop": {
    "name": "EcoWear",
    "onlineStoreUrl": "https://ecowear-example.myshopify.com"
    }
    }
    }
    ],
    "options": [
    {
    "name": "Size",
    "values": [
    { "value": "S", "availableForSale": true, "exists": true },
    { "value": "M", "availableForSale": true, "exists": true },
    { "value": "L", "availableForSale": true, "exists": true }
    ]
  2. Execute the script from your terminal:

    Terminal

    node search-catalog.js

    The response includes product titles, descriptions, pricing, images, and detailed variant information for each matching product.

  3. You can use data from the returned UniversalProduct resource to display custom components, so that buyers can interact with individual products. For example:

    let response = JSON.parse(data.result.content[0].text);
    let offer = response.offers[buyerSelectedIndex];

    // Extract product data
    let product = {
    title: offer.title,
    price: offer.priceRange.min.amount,
    currency: offer.priceRange.min.currencyCode,
    image: offer.images[0]?.url,
    url: offer.url
    };

    let card = `
    <div class="product-card">
    <img src="${product.image}" alt="${product.title}" />
    <h3>${product.title}</h3>
    <p>${product.currency} $${parseFloat(product.price).toFixed(2)}</p>
    <a href="${product.url}">View Product</a>
    </div>
    `;

Anchor to Step 3: Apply query parametersStep 3: Apply query parameters

Buyers can supply additional context that can be used to refine your catalog search by adding filters for price, shipping location, availability, and other criteria.

For example, we can limit results to products between $50 and $200, shippable to the United States, and that can be second-hand items:

import 'dotenv/config';

const bearerToken = process.env.BEARER_TOKEN;
let catalogId = process.env.CATALOG_ID;

fetch('https://discover.shopifyapps.com/global/mcp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${bearerToken}`
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
id: 1,
params: {
name: 'search_global_products',
arguments: {
saved_catalog: catalogId,
query: 'I need a crewneck sweater',
context: 'buyer looking for sustainable fashion',
include_secondhand: true,
min_price: 50,
max_price: 200,
ships_to: 'US',
limit: 3
}
}
})
})
.then(res => res.json())
.then(data => {
if (data && data.result?.content?.[0]?.text) {
// Parse the stringified text field
data.result.content[0].text = JSON.parse(data.result.content[0].text);
}
if (data) {
console.log(JSON.stringify(data, null, 2));
}
})
.catch(err => console.error('Request failed:', err));
{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 1,
"params": {
"name": "search_global_products",
"arguments": {
"saved_catalog": "<CATALOG_ID>",
"query": "I need a crewneck sweater",
"context": "buyer looking for sustainable fashion",
"include_secondhand": true,
"min_price": 50,
"max_price": 200,
"ships_to": "US",
"limit": 3
}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": {
"offers": [
{
"id": "gid://shopify/p/xyz789abc123",
"title": "Organic Cotton Crewneck Sweater",
"description": "A soft crewneck sweater crafted from 100% organic cotton with a relaxed fit for everyday comfort.",
"images": [
{
"url": "https://cdn.shopify.com/s/files/example/organic-cotton-crewneck.jpg",
"altText": "Organic Cotton Crewneck Sweater - EcoWear",
"product": {
"id": "gid://shopify/Product/1111111111111",
"title": "Organic Cotton Crewneck Sweater",
"onlineStoreUrl": "https://ecowear-example.myshopify.com/products/organic-cotton-crewneck?variant=11111111111&_gsid=example123",
"shop": {
"name": "EcoWear",
"onlineStoreUrl": "https://ecowear-example.myshopify.com"
}
}
}
],
"options": [
{
"name": "Size",
"values": [
{ "value": "S", "availableForSale": true, "exists": true },
{ "value": "M", "availableForSale": true, "exists": true },
{ "value": "L", "availableForSale": true, "exists": true }
]
}
],
"priceRange": {
"min": { "amount": "89.00", "currencyCode": "USD" },
"max": { "amount": "89.00", "currencyCode": "USD" }
},
"products": [
{
"id": "gid://shopify/Product/1111111111111",
"title": "Organic Cotton Crewneck Sweater",
"checkoutUrl": "https://ecowear-example.myshopify.com/cart/11111111111:1?_gsid=example123&payment=shop_pay",
"description": "A sustainable everyday essential. This crewneck sweater is made from certified organic cotton grown without harmful pesticides.",
"onlineStoreUrl": "https://ecowear-example.myshopify.com/products/organic-cotton-crewneck?variant=11111111111&_gsid=example123",
"price": { "amount": "89.00", "currencyCode": "USD" },
"rating": { "value": 4.8, "count": 124 },
"availableForSale": true,
"shop": {
"name": "EcoWear",
"paymentSettings": {
"supportedDigitalWallets": ["SHOPIFY_PAY"],
"acceptedCardBrands": ["visa", "master", "american_express"]
},
"onlineStoreUrl": "https://ecowear-example.myshopify.com",
"id": "gid://shopify/Shop/1111111111"
},
"selectedProductVariant": {
"id": "gid://shopify/ProductVariant/11111111111?shop=1111111111",
"availableForSale": true,
"options": [{ "name": "Size", "value": "M" }],
"price": { "amount": "89.00", "currencyCode": "USD" }
},
"secondhand": false,
"requiresSellingPlan": false
}
],
"availableForSale": true,
"rating": { "value": 4.8, "count": 124 },
"uniqueSellingPoint": "Made from 100% certified organic cotton for eco-conscious comfort.",
"topFeatures": ["100% organic cotton fabric", "Relaxed fit for everyday comfort", "Ribbed cuffs and hem", "Classic crew neckline"],
"url": "https://discover.shopifyapps.com/global/v1/p/xyz789abc123?_gsid=example123&available_for_sale=1&query=crewneck+sweater&ships_to=US"
},
{
"id": "gid://shopify/p/def456ghi789",
"title": "Recycled Wool Blend Crewneck",
"description": "A cozy crewneck sweater made from recycled wool blend with a modern oversized silhouette.",
"priceRange": {
"min": { "amount": "125.00", "currencyCode": "USD" },
"max": { "amount": "125.00", "currencyCode": "USD" }
},
"availableForSale": true,
"rating": { "value": 4.6, "count": 89 },
"uniqueSellingPoint": "Made from 70% recycled wool for warmth with minimal environmental impact.",
"url": "https://discover.shopifyapps.com/global/v1/p/def456ghi789?_gsid=example123&available_for_sale=1&query=crewneck+sweater&ships_to=US"
},
{
"id": "gid://shopify/p/mno321pqr654",
"title": "Vintage Striped Crewneck",
"description": "A pre-loved vintage crewneck sweater with classic rugby stripes in excellent condition.",
"priceRange": {
"min": { "amount": "68.00", "currencyCode": "USD" },
"max": { "amount": "68.00", "currencyCode": "USD" }
},
"products": [
{
"id": "gid://shopify/Product/3333333333333",
"title": "Vintage Striped Crewneck",
"secondhand": true,
"requiresSellingPlan": false
}
],
"availableForSale": true,
"rating": { "value": 4.9, "count": 42 },
"uniqueSellingPoint": "Pre-loved vintage piece in excellent condition, sustainable fashion at its best.",
"url": "https://discover.shopifyapps.com/global/v1/p/mno321pqr654?_gsid=example123&available_for_sale=1&include_secondhand=1&query=crewneck+sweater&ships_to=US"
}
],
"instructions": "Use markdown to render product titles as links to their respective product pages using the URL property.\n"
}
}
],
"isError": false
}
}

Anchor to Step 4: Lookup product detailsStep 4: Lookup product details

At this point your search has resulted in three products, and the buyer might be interested in investigating additional details about them. Lookup within Catalog allows you to render product details not available already in Search (for example, all variants, detailed pricing, availability, and shop details) so buyers can explore available options and offers.

If the buyer chooses an unavailable option, the API will relax those options to find an available variant. See the get_global_product_details tool documentation for more information about options preferences.

In this example, you'll modify the script to arbitrarily select a product variant result, then leverage Lookup to get additional information about that product.

  1. The Catalog returns products grouped by Universal Product ID (UPID). Each product includes shop information and variant details:

    import 'dotenv/config';

    const bearerToken = process.env.BEARER_TOKEN;
    let catalogId = process.env.CATALOG_ID;

    fetch('https://discover.shopifyapps.com/global/mcp', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${bearerToken}`
    },
    body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'tools/call',
    id: 1,
    params: {
    name: 'search_global_products',
    arguments: {
    saved_catalog: catalogId,
    query: 'I need a crewneck sweater',
    context: 'buyer looking for sustainable fashion',
    include_secondhand: true,
    min_price: 50,
    max_price: 200,
    ships_to: 'US',
    limit: 3
    }
    }
    })
    })
    .then(res => res.json())
    .then(data => {
    // Parse the text field to get the actual offers object
    if (data.result && data.result.content && data.result.content[0]) {
    const offersData = JSON.parse(data.result.content[0].text);
    }
    // Extract first offer ID and call get_global_product_details
    if (data.result && data.result.content && data.result.content[0]) {
    const textContent = JSON.parse(data.result.content[0].text);
    if (textContent.offers && textContent.offers.length > 0) {
    const fullId = textContent.offers[0].id;
    // Extract UPID from gid://shopify/p/{UPID}
    const upid = fullId.split('/p/')[1];
    // Call get_global_product_details with the extracted ID
    return fetch('https://discover.shopifyapps.com/global/mcp', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${bearerToken}`
    },
    body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'tools/call',
    id: 2,
    params: {
    name: 'get_global_product_details',
    arguments: {
    upid: upid,
    product_options: [{
    key: 'Size',
    values: ['Large (L)']
    }]
    }
    }
    })
    });
    }
    }
    })
    .then(res => res ? res.json() : null)
    .then(data => {
    if (data && data.result?.content?.[0]?.text) {
    // Parse the stringified text field
    data.result.content[0].text = JSON.parse(data.result.content[0].text);
    }
    if (data) {
    console.log(JSON.stringify(data, null, 2));
    }
    })
    .catch(err => console.error('Request failed:', err));
    {
    "jsonrpc": "2.0",
    "method": "tools/call",
    "id": 2,
    "params": {
    "name": "get_global_product_details",
    "arguments": {
    "upid": "<UPID>"
    }
    }
    }
    {
    "jsonrpc": "2.0",
    "id": 2,
    "result": {
    "content": [
    {
    "type": "text",
    "text": {
    "product": {
    "id": "gid://shopify/p/xyz789abc123",
    "title": "Organic Cotton Crewneck Sweater",
    "description": "A soft crewneck sweater crafted from 100% organic cotton with a relaxed fit for everyday comfort.",
    "images": [
    {
    "url": "https://cdn.shopify.com/s/files/example/organic-cotton-crewneck-front.jpg",
    "altText": "Organic Cotton Crewneck Sweater - Front"
    },
    {
    "url": "https://cdn.shopify.com/s/files/example/organic-cotton-crewneck-back.jpg",
    "altText": "Organic Cotton Crewneck Sweater - Back"
    },
    {
    "url": "https://cdn.shopify.com/s/files/example/organic-cotton-crewneck-detail.jpg",
    "altText": "Organic Cotton Crewneck Sweater - Detail"
    }
    ],
    "options": [
    {
    "name": "Size",
    "values": [
    { "value": "S", "availableForSale": true, "exists": true },
    { "value": "M", "availableForSale": true, "exists": true },
    { "value": "L", "availableForSale": true, "exists": true }
    ]
    }
    ],
    "priceRange": {
    "min": { "amount": "89.00", "currencyCode": "USD" },
    "max": { "amount": "89.00", "currencyCode": "USD" }
    },
    "products": [
    {
    "id": "gid://shopify/Product/1111111111111",
    "title": "Organic Cotton Crewneck Sweater",
    "checkoutUrl": "https://ecowear-example.myshopify.com/cart/11111111111:1?_gsid=example123&payment=shop_pay",
    "description": "A sustainable everyday essential. This crewneck sweater is made from certified organic cotton grown without harmful pesticides.",
    "onlineStoreUrl": "https://ecowear-example.myshopify.com/products/organic-cotton-crewneck?variant=11111111111&_gsid=example123",
    "price": { "amount": "89.00", "currencyCode": "USD" },
    "rating": { "value": 4.8, "count": 124 },
    "availableForSale": true,
    "shop": {
    "name": "EcoWear",
    "paymentSettings": {
    "supportedDigitalWallets": ["SHOPIFY_PAY"],
    "acceptedCardBrands": ["visa", "master", "american_express"]
    },
    "onlineStoreUrl": "https://ecowear-example.myshopify.com",
    "id": "gid://shopify/Shop/1111111111"
    },
    "selectedProductVariant": {
    "id": "gid://shopify/ProductVariant/11111111111?shop=1111111111",
    "availableForSale": true,
    "options": [{ "name": "Size", "value": "M" }],
    "price": { "amount": "89.00", "currencyCode": "USD" },
    "selectionState": { "type": "match", "requestedFilters": [] }
    },
    "secondhand": false,
    "requiresSellingPlan": false
    }
    ],
    "availableForSale": true,
    "rating": { "value": 4.8, "count": 124 },
    "uniqueSellingPoint": "Made from 100% certified organic cotton for eco-conscious comfort.",
    "topFeatures": [
    "100% organic cotton fabric provides breathable comfort",
    "Relaxed fit for everyday wear",
    "Ribbed cuffs and hem for a polished look",
    "Classic crew neckline",
    "Pre-washed for softness"
    ],
    "techSpecs": [
    "Material: 100% Organic Cotton",
    "Fit: Relaxed",
    "Neckline: Crew",
    "Pattern: Solid",
    "Color: Natural Beige",
    "Available Sizes: S, M, L, XL"
    ],
    "sharedAttributes": [
    { "name": "Neckline", "values": ["Crew"] },
    { "name": "Age group", "values": ["Adults"] },
    { "name": "Pattern", "values": ["Solid"] },
    { "name": "Fabric", "values": ["Cotton", "Organic"] },
    { "name": "Target gender", "values": ["Unisex"] },
    { "name": "Color", "values": ["Beige", "Natural"] }
    ],
    "url": "https://discover.shopifyapps.com/global/v1/p/xyz789abc123?_gsid=example123&available_for_sale=1&ships_to=US"
    },
    "instructions": "Use markdown to render product titles as links to their respective product pages using the URL property.\n"
    }
    }
    ],
    "isError": false
    }
    }

    Notice the script gets details for the size the buyer actually wants to order using the product_options argument.

    In reality, your agent would retrieve real responses from a buyer at this point when calling the get_global_product_details tool. In this demo, the first result in the array of resulting products was chosen to stand-in for this behavior.

  2. Inspect the response for the buyer's selected product variant id.

    The buyer has made a selection, narrowing down their initial search into a particular product variant found at .result.content[0].text.product.products[0].selectedProductVariant in the previous response.

    Product variant line item

    {
    "id": "gid://shopify/ProductVariant/11111111111?shop=1111111111",
    "availableForSale": true,
    "options": [
    {
    "name": "Size",
    "value": "M"
    }
    ],
    "price": {
    "amount": "89.00",
    "currencyCode": "USD"
    },
    "image": {
    "url": "https://cdn.shopify.com/s/files/example/organic-cotton-crewneck-front.jpg",
    "altText": "Organic Cotton Crewneck Sweater - EcoWear"
    },
    "selectionState": {
    "type": "match",
    "requestedFilters": []
    }
    }
  3. Retrieve the store's domain for the selected product variant.

    In that same response, you will also need to retrieve and export a shopDomain for the product variant selected by the buyer. This value is located within the response at onlineStoreUrl within .result.content[0].text.product.products[0].shop:

    Shop details

    {
    "name": "EcoWear",
    "paymentSettings": {
    "supportedDigitalWallets": [
    "SHOPIFY_PAY"
    ],
    "acceptedCardBrands": [
    "visa",
    "master",
    "american_express"
    ]
    },
    "onlineStoreUrl": "https://ecowear-example.myshopify.com",
    "privacyPolicy": {
    "url": "https://ecowear-example.myshopify.com/policies/privacy"
    },
    "refundPolicy": {
    "url": "https://ecowear-example.myshopify.com/policies/refund"
    },
    "termsOfService": {
    "url": "https://ecowear-example.myshopify.com/policies/terms"
    },
    "shippingPolicy": {
    "url": "https://ecowear-example.myshopify.com/policies/shipping"
    },
    "id": "gid://shopify/Shop/1111111111"
    }

You will use this selected product variant id and the shopDomain when completing checkout in the next tutorial.



Was this page helpful?