get-products
Retrieve products from a Shopify store by title search with configurable result limits to manage inventory data.
Input Schema
TableJSON 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";