search-shopify
Search across Shopify store content including products, articles, blogs, and pages using specific queries to find relevant information quickly.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The search query to find content across the store | |
| types | No | Types of resources to search for. If not specified, searches all types. | |
| first | No | Number of results to return (max 50) |
Implementation Reference
- src/tools/searchShopify.ts:42-134 (handler)The execute method implements the core logic of the 'search-shopify' tool, querying Shopify GraphQL for articles, blogs, pages, and products based on the input query and types, then formatting and returning the results.async execute(input: SearchShopifyInput) { try { // We'll query each type separately since Shopify doesn't have a unified search endpoint const queries = { ARTICLE: gql` query SearchArticles($query: String!, $first: Int!) { articles(first: $first, query: $query) { nodes { id title handle summary blog { title } } } } `, BLOG: gql` query SearchBlogs($query: String!, $first: Int!) { blogs(first: $first, query: $query) { nodes { id title handle } } } `, PAGE: gql` query SearchPages($query: String!, $first: Int!) { pages(first: $first, query: $query) { nodes { id title handle bodySummary } } } `, PRODUCT: gql` query SearchProducts($query: String!, $first: Int!) { products(first: $first, query: $query) { nodes { id title handle description } } } ` }; const types = input.types || ["ARTICLE", "BLOG", "PAGE", "PRODUCT"]; const results: Record<string, any> = {}; // Execute queries for each requested type await Promise.all( types.map(async (type) => { try { const data = await shopifyClient.request(queries[type], { query: input.query, first: input.first }) as SearchResponse; const key = type.toLowerCase() + "s"; results[type.toLowerCase()] = data[key].nodes.map((node: SearchNode) => ({ id: node.id, title: node.title, handle: node.handle, summary: node.summary || node.bodySummary || node.description || null, ...(node.blog ? { blogTitle: node.blog.title } : {}) })); } catch (error) { console.error(`Error searching ${type}:`, error); results[type.toLowerCase()] = []; } }) ); return { results }; } catch (error) { console.error("Error searching Shopify:", error); throw new Error( `Failed to search Shopify: ${error instanceof Error ? error.message : String(error)}` ); } }
- src/tools/searchShopify.ts:5-9 (schema)Zod schema defining the input validation for the search-shopify tool: query (required string), types (optional array of resource types), first (optional number, default 10, max 50).const SearchShopifyInputSchema = z.object({ query: z.string().min(1).describe("The search query to find content across the store"), types: z.array(z.enum(["ARTICLE", "BLOG", "PAGE", "PRODUCT"])).optional().describe("Types of resources to search for. If not specified, searches all types."), first: z.number().min(1).max(50).optional().default(10).describe("Number of results to return (max 50)") });
- src/index.ts:286-295 (registration)MCP server registration of the 'search-shopify' tool, using the schema from the imported tool object and delegating execution to searchShopify.execute.server.tool( "search-shopify", searchShopify.schema.shape, async (args: z.infer<typeof searchShopify.schema>) => { const result = await searchShopify.execute(args); return { content: [{ type: "text", text: JSON.stringify(result) }] }; } );