get-products
Retrieve products from a Shopify store by title search with configurable result limits to manage inventory data.
Tool call template
This tool declares no required parameters. Add optional parameters from the input schema as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {},
"name": "get-products"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| searchTitle | No | ||
| limit | No |
Implementation Reference
- src/tools/getProducts.ts:23-207 (handler)The core implementation of the 'get-products' tool, including the execute handler that queries the Shopify GraphQL API for products with support for search, pagination, and detailed product information extraction.
const getProducts = { name: "get-products", description: "Get all products or search by title, including SEO-relevant fields and pagination support", schema: GetProductsInputSchema, // Add initialize method to set up the GraphQL client initialize(client: GraphQLClient) { shopifyClient = client; }, execute: async (input: GetProductsInput) => { try { const { searchTitle, limit, after, before, reverse } = input; // Create query based on whether we're searching by title or not const query = gql` query GetProducts( $first: Int $last: Int $after: String $before: String $query: String $reverse: Boolean ) { products( first: $first last: $last after: $after before: $before query: $query reverse: $reverse ) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { id title description descriptionHtml handle status createdAt updatedAt totalInventory priceRangeV2 { minVariantPrice { amount currencyCode } maxVariantPrice { amount currencyCode } } images(first: 1) { edges { node { url altText } } } variants(first: 5) { edges { node { id title price inventoryQuantity sku } } } } } } } `; const variables = { first: before ? undefined : limit, last: before ? limit : undefined, after, before, query: searchTitle ? `title:*${searchTitle}*` : undefined, reverse }; const data = (await shopifyClient.request(query, variables)) as { products: { pageInfo: { hasNextPage: boolean; hasPreviousPage: boolean; startCursor: string; endCursor: string; }; edges: Array<{ cursor: string; node: any; }>; }; }; // Extract and format product data const products = data.products.edges.map((edge) => { const product = edge.node; // Format variants const variants = product.variants.edges.map((variantEdge: any) => ({ id: variantEdge.node.id, title: variantEdge.node.title, price: variantEdge.node.price, inventoryQuantity: variantEdge.node.inventoryQuantity, sku: variantEdge.node.sku })); // Get first image if it exists const imageUrl = product.images.edges.length > 0 ? product.images.edges[0].node.url : null; /** * @typedef {Object} Product * @property {string} id - The unique GID of the product * @property {string} title - The product title, optimized for SEO * @property {string} description - The plain text description of the product * @property {string} descriptionHtml - The HTML formatted description of the product * @property {string} handle - The URL-friendly handle/slug of the product * @property {string} status - Current status of the product (e.g., ACTIVE, ARCHIVED) * @property {string} createdAt - Product creation timestamp * @property {string} updatedAt - Last update timestamp * @property {number} totalInventory - Total available inventory across all variants */ return { id: product.id, title: product.title, description: product.description, descriptionHtml: product.descriptionHtml, handle: product.handle, status: product.status, createdAt: product.createdAt, updatedAt: product.updatedAt, totalInventory: product.totalInventory, priceRange: { minPrice: { amount: product.priceRangeV2.minVariantPrice.amount, currencyCode: product.priceRangeV2.minVariantPrice.currencyCode }, maxPrice: { amount: product.priceRangeV2.maxVariantPrice.amount, currencyCode: product.priceRangeV2.maxVariantPrice.currencyCode } }, imageUrl, variants, cursor: edge.cursor }; }); return { products, pageInfo: { hasNextPage: data.products.pageInfo.hasNextPage, hasPreviousPage: data.products.pageInfo.hasPreviousPage, startCursor: data.products.pageInfo.startCursor, endCursor: data.products.pageInfo.endCursor } }; } catch (error) { console.error("Error fetching products:", error); throw new Error( `Failed to fetch products: ${ error instanceof Error ? error.message : String(error) }` ); } } }; - src/tools/getProducts.ts:6-12 (schema)Zod schema defining the input parameters for the get-products tool, including search, limit, and pagination options.
const GetProductsInputSchema = z.object({ searchTitle: z.string().optional().describe("Optional search term to filter products by title"), limit: z.number().default(10).describe("Maximum number of products to return (default: 10)"), after: z.string().optional().describe("Cursor for pagination - get items after this cursor"), before: z.string().optional().describe("Cursor for pagination - get items before this cursor"), reverse: z.boolean().optional().default(false).describe("Reverse the order of the returned products") }); - src/index.ts:94-106 (registration)Registration of the 'get-products' tool with the MCP server, using a simplified input schema and delegating execution to the imported getProducts.execute.
server.tool( "get-products", { searchTitle: z.string().optional(), limit: z.number().default(10) }, async (args) => { const result = await getProducts.execute(args); return { content: [{ type: "text", text: JSON.stringify(result) }] }; } ); - src/index.ts:69-69 (registration)Initialization of the getProducts tool with the Shopify GraphQL client instance.
getProducts.initialize(shopifyClient); - src/index.ts:12-12 (registration)Import of the getProducts tool module.
import { getProducts } from "./tools/getProducts.js";