Loading
Shopify-Global-Catalog-Migration.webp
Web DevelopmentBy SDX Development

Share this article

On November 2, 2026, Shopify will stop serving traffic to its Global Catalog REST API. Deprecated since April, this multi-merchant product discovery service will no longer respond on its old /global/... endpoints. Announced on October 9, 2026, the deadline requires migrating affected integrations to Global Catalog MCP, which follows the Universal Commerce Protocol (UCP).

This change does not mean Shopify is removing all of its REST APIs: it specifically affects Global Catalog, which is used to search for products across multiple Shopify stores. For an e-commerce integration, SaaS, or shopping agent developer, migration requires more than replacing a URL: you need to adapt the transport, the tools being called, identifiers, the agent profile, and response schemas. Here are four REST → MCP conversions, followed by a validation method to use before the shutdown.

Key takeaway

A firm date, three MCP tools

Starting November 2, 2026, calls to https://discover.shopifyapps.com/global/... will fail, including calls for saved catalogs. Shopify recommends using search_catalog, get_product, and lookup_catalog via https://catalog.shopify.com/api/ucp/mcp. The existing bearer token can be kept, but the request and response formats are changing.

In this article

Which Shopify integrations will stop working on November 2?

Only clients of the legacy Global Catalog REST API are affected. This is the service that allowed users to discover and retrieve products from more than one store, on the discover.shopifyapps.com domain. Shopify says all corresponding /global/... paths will be shut down, including saved catalog endpoints.

This is not the shutdown of the Admin API, nor of the Storefront API, nor a mandatory migration of all stores to MCP. Shopify also distinguishes Storefront Catalog MCP from Global Catalog MCP for agents limited to a single merchant's catalog. So start by auditing the domains and routes your application uses: don't change integrations that are not affected.

The official mapping: four REST endpoints to three MCP tools

Old REST call New MCP/UCP tool Parameter to adapt
GET /global/v2/search search_catalog catalog.query and filters
GET /global/v2/p/{upid} get_product catalog.id = gid://shopify/p/{upid}
GET /global/v2/p/by-variant/{vid} get_product catalog.id = gid://shopify/ProductVariant/{vid}
POST /global/v2/lookup lookup_catalog catalog.ids, 1 to 50 identifiers

Shopify published this mapping on October 9. With MCP, you don't call four separate HTTP paths: you send a JSON-RPC tools/call request to a single entry point, and the tool name appears in params.name. Business arguments are grouped under params.arguments.catalog.

Set up the client: MCP endpoint, UCP profile, and authentication

The destination endpoint is https://catalog.shopify.com/api/ucp/mcp. Every call must include params.arguments.meta.ucp-agent.profile, which is the URL of your agent's UCP profile. This profile indicates the capabilities the agent claims; the server negotiates the available tools and fields. The following examples use an illustrative profile hosted by Shopify, which should be replaced with your application's profile in production.

To expose global tools and their enriched fields, Shopify specifies that a custom profile must declare the base capabilities dev.ucp.shopping.catalog.search and dev.ucp.shopping.catalog.lookup, as well as the dev.shopify.catalog.global extension. An extension without its base capability is not sufficient.

The existing bearer authentication can be kept: tokens created from Dev Dashboard client credentials remain usable. However, the request body is no longer JSON specific to the old REST endpoint. The code below illustrates HTTP transport to MCP; the actual configuration depends on the MCP client and session management you use.

appel-mcp.shBASH
# Save the first JSON as 01-search-catalog.json
# Use a personal/server token obtained via the Dev Dashboard.
curl -X POST 'https://catalog.shopify.com/api/ucp/mcp' \
  -H 'Authorization: Bearer <SHOPIFY_CATALOG_TOKEN>' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data-binary @01-search-catalog.json

Note: the 01-search-catalog.json file must contain the complete envelope shown in the following example. Never put a real token in a public file, browser, or demo repository; use your backend's secrets.

Tutorial: Migrate four REST requests without losing their logic

1. Multi-merchant search: GET /global/v2/search → search_catalog

Before: the backend queried GET https://discover.shopifyapps.com/global/v2/search, with its REST search parameters. After: it calls search_catalog with a text query in catalog.query, the buyer's country in catalog.context.address_country, and the limit in catalog.pagination.limit.

01-search-catalog.jsonJSON
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 1,
  "params": {
    "name": "search_catalog",
    "arguments": {
      "meta": {
        "ucp-agent": {
          "profile": "https://shopify.dev/ucp/agent-profiles/examples/2026-08-25/valid-with-capabilities.json"
        }
      },
      "catalog": {
        "query": "running shoes",
        "context": {
          "address_country": "FR",
          "language": "fr"
        },
        "pagination": {
          "limit": 10
        }
      }
    }
  }
}

The UCP response groups products and their offers from multiple merchants. Depending on the search, filters, availability information, and enriched data may affect the result: check your business-facing display rather than assuming the REST schema remains unchanged.

2. Product details: GET /global/v2/p/{upid} → get_product

Before: product details were retrieved via GET https://discover.shopifyapps.com/global/v2/p/{upid}. After: the get_product tool takes a canonical identifier in the format gid://shopify/p/{upid} in catalog.id.

02-get-product.jsonJSON
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 2,
  "params": {
    "name": "get_product",
    "arguments": {
      "meta": {
        "ucp-agent": {
          "profile": "https://shopify.dev/ucp/agent-profiles/examples/2026-08-25/valid-with-capabilities.json"
        }
      },
      "catalog": {
        "id": "gid://shopify/p/7f3a2b8c1d9e",
        "context": {
          "address_country": "FR"
        }
      }
    }
  }
}

The tool can return options, variants, and availability signals, and help refine the selection. Replacing the REST path with a GID string in the right place is essential: simply passing the old raw identifier in the new format may return an incorrect result or no result at all.

3. Variant: GET /global/v2/p/by-variant/{vid} → get_product

Before: the variant lookup used GET https://discover.shopifyapps.com/global/v2/p/by-variant/{vid}. After: call the same get_product tool, but with gid://shopify/ProductVariant/{vid}. This distinction matters for an assistant starting with a specific reference rather than an overall product listing.

03-get-variant.jsonJSON
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 3,
  "params": {
    "name": "get_product",
    "arguments": {
      "meta": {
        "ucp-agent": {
          "profile": "https://shopify.dev/ucp/agent-profiles/examples/2026-08-25/valid-with-capabilities.json"
        }
      },
      "catalog": {
        "id": "gid://shopify/ProductVariant/87654321",
        "context": {
          "address_country": "FR"
        }
      }
    }
  }
}

When the agent needs to select a color or size, the optional catalog.selected array lets you pass choices in the form {"name":"Color","label":"Black"}. get_product responses expose the actual selections and the available or exists indicators.

4. Batch lookup: POST /global/v2/lookup → lookup_catalog

Before: multiple references could be resolved via POST https://discover.shopifyapps.com/global/v2/lookup. After: pass the list in catalog.ids, containing between 1 and 50 identifiers per call. The service accepts product and variant GIDs, as well as supported Shopify product URLs.

04-lookup-catalog.jsonJSON
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 4,
  "params": {
    "name": "lookup_catalog",
    "arguments": {
      "meta": {
        "ucp-agent": {
          "profile": "https://shopify.dev/ucp/agent-profiles/examples/2026-08-25/valid-with-capabilities.json"
        }
      },
      "catalog": {
        "ids": [
          "gid://shopify/p/7f3a2b8c1d9e",
          "gid://shopify/ProductVariant/87654321"
        ],
        "context": {
          "address_country": "FR"
        }
      }
    }
  }
}

Plan to split large batches into groups of no more than 50. Shopify specifies that identifiers pointing to the same product may be grouped, and IDs that cannot be found appear, among other forms, as not_found messages: this is not always a one-input, one-output-row mapping.

What if the application uses saved catalogs?

The old REST URLs dedicated to saved catalogs will also stop working. With UCP, you need to pass the ID of the catalog configured in the Dev Dashboard via catalog.catalog_id, within the same catalog object. This ID is added to the other business parameters, such as query; it is no longer a URL segment.

In a search_catalog call, the saved catalog's filters constrain the search. Shopify also specifies that a saved search prefix can be combined with catalog.query. The old alias catalog.saved_catalog_slug is documented as deprecated: use catalog.catalog_id for a new integration.

Adapt UCP schemas in your application code

The difference goes beyond calling a tool. Shopify's examples return structured content in result.structuredContent: products have new fields, a ucp envelope describes negotiated capabilities and versions, and pagination may include cursor and has_next_page. Amounts such as price_range.min.amount are expressed in minor currency units: don't display them directly as euros or dollars.

An adapter between the MCP client and the application reduces the risk of coupling the entire front end to the transport schema. This short JavaScript example assumes an MCP client has already decoded the JSON-RPC response and does not replace full validation of business data:

catalog-adapter.jsJAVASCRIPT
// JSON-RPC response already decoded by the MCP client
function normalizeCatalogResponse(rpcResponse) {
  if (rpcResponse.error) {
    throw new Error(rpcResponse.error.message || "MCP error");
  }

  const data = rpcResponse.result?.structuredContent;
  if (!data) {
    throw new Error("Structured UCP response missing");
  }

  return {
    products: Array.isArray(data.products) ? data.products : [],
    messages: Array.isArray(data.messages) ? data.messages : [],
    pagination: data.pagination ?? null,
  };
}

// data.products[i].price_range.min.amount: amount in minor units
// data.messages may include a "not_found" code for an unknown ID

Another important nuance for comparison tools: Shopify marks some catalog attributes as Inferred (enriched descriptions, normalized options, inferred features). They may be incomplete or approximate. Don't automatically present them as claims made by the merchant. For prices, variants, checkout links, and availability, verify the schemas and business rules before going live.

Test the migration before the shutdown

Shopify provides the AI Toolkit and UCP CLI to test the tools without first integrating an entire custom client. The following commands use the documented syntax, with example values and a French buyer country:

catalog-cli.shBASH
# Search test, following the examples in the Shopify UCP CLI
ucp catalog search \
  --set /query='running shoes' \
  --set /context/address_country=FR \
  --view :compact --format md

# Test lookup for a known variant
ucp catalog lookup \
  --set '/ids/0=gid://shopify/ProductVariant/87654321'

To secure the cutover, prepare a small test set that includes a text query, an existing product, an existing variant, an unknown variant, a batch of more than 50 IDs to split up, and a search targeting a saved catalog. Compare the results against expected business behavior: missing fields, grouping, pagination, pricing, and localization. Monitor the frequency of not_found errors, latency, and UCP policy restrictions.

Migration checklist before November 2

  1. Inventory calls to discover.shopifyapps.com/global/... and the clients affected.
  2. Map the four routes to search_catalog, get_product, and lookup_catalog.
  3. Configure the UCP profile and its capabilities, with meta.ucp-agent.profile in every call.
  4. Keep authentication server-side and verify the existing bearer token.
  5. Convert identifiers to GIDs and use catalog.catalog_id for saved catalogs.
  6. Test the new responses, especially minor-unit amounts, pagination, not_found cases, and inferred fields.

REST → MCP: an interesting precedent, not the end of traditional APIs

The lesson goes beyond Shopify. For a workflow where an agent dynamically chooses a tool to discover products, an MCP interface combined with UCP schemas and capability negotiation can simplify interoperability between providers and assistants. The server exposes named business operations rather than a series of specialized URLs; the agent can choose search_catalog, then get_product based on its goal.

But MCP is not a universal replacement for REST. Traditional web APIs and GraphQL schemas remain suitable for other applications: predictable interfaces, data synchronization, administrative operations, or store-to-store integration. Here, Shopify is modernizing a specific agent-oriented, multi-merchant discovery use case. The real architectural criterion is the need for agent/tool interoperability, not the idea that one protocol is inherently better in every scenario.

So for an e-commerce SaaS or assistant, the practical decision is simple: migrate Global Catalog REST calls now, isolate the new dependency behind a data adapter, keep a suite of business tests, and adopt MCP more broadly only where the nature of the workflow justifies it.

Official sources and documentation Shopify · UCP

WEB DEVELOPMENT

Prepare your web application for future changes.

PHP migration, CMS update or framework evolution: identify compatibility points and validate essential user journeys before going live.

  • Dependencies checked for compatibility
  • Essential user journeys tested in pre-production
  • Go-live with rollback capability