UNPKG

amazon-seller-mcp

Version:

Model Context Protocol (MCP) client for Amazon Selling Partner API

263 lines 10.5 kB
/** * Catalog tools for Amazon Selling Partner API */ // Third-party dependencies import { z } from 'zod'; import { CatalogClient, } from '../api/catalog-client.js'; /** * Register catalog tools with the tool manager * * @param toolManager Tool registration manager * @param authConfig Authentication configuration */ export function registerCatalogTools(toolManager, authConfig) { const catalogClient = new CatalogClient(authConfig); // Register search catalog tool toolManager.registerTool('search-catalog', { title: 'Search Amazon Catalog', description: 'Search for products in the Amazon catalog', inputSchema: z.object({ keywords: z.string().describe('Search keywords'), brandNames: z.array(z.string()).optional().describe('List of brand names to filter by'), pageSize: z .number() .min(1) .max(20) .optional() .describe('Number of results per page (1-20)'), pageToken: z.string().optional().describe('Token for pagination'), includedData: z .array(z.enum([ 'attributes', 'identifiers', 'images', 'productTypes', 'relationships', 'salesRanks', 'summaries', 'variations', ])) .optional() .describe('Data to include in the response'), locale: z.string().optional().describe('Locale for localized fields'), }), }, async (input) => { try { // Validate input const validatedInput = z .object({ keywords: z.string(), brandNames: z.array(z.string()).optional(), pageSize: z.number().optional(), pageToken: z.string().optional(), includedData: z .array(z.enum([ 'attributes', 'identifiers', 'images', 'productTypes', 'relationships', 'salesRanks', 'summaries', 'variations', ])) .optional(), locale: z.string().optional(), }) .parse(input); const params = { keywords: validatedInput.keywords, brandNames: validatedInput.brandNames, pageSize: validatedInput.pageSize, pageToken: validatedInput.pageToken, includedData: validatedInput.includedData, locale: validatedInput.locale, }; const result = await catalogClient.searchCatalogItems(params); // Format the response let responseText = `Found ${result.numberOfResults} products matching "${validatedInput.keywords}"\n\n`; // Add pagination info if available if (result.pagination) { if (result.pagination.nextToken) { responseText += `Next page token: ${result.pagination.nextToken}\n`; } if (result.pagination.previousToken) { responseText += `Previous page token: ${result.pagination.previousToken}\n`; } responseText += '\n'; } // Add refinements if available if (result.refinements) { if (result.refinements.brands && result.refinements.brands.length > 0) { responseText += 'Available brand filters:\n'; result.refinements.brands.forEach((brand) => { responseText += `- ${brand.name} (${brand.numberOfResults} products)\n`; }); responseText += '\n'; } if (result.refinements.classifications && result.refinements.classifications.length > 0) { responseText += 'Available classification filters:\n'; result.refinements.classifications.forEach((classification) => { responseText += `- ${classification.name} (${classification.numberOfResults} products)\n`; }); responseText += '\n'; } } // Add items responseText += 'Products:\n'; result.items.forEach((item, index) => { const summary = item.summaries && item.summaries.length > 0 ? item.summaries[0] : null; responseText += `${index + 1}. ASIN: ${item.asin}\n`; if (summary) { if (summary.itemName) responseText += ` Title: ${summary.itemName}\n`; if (summary.brandName) responseText += ` Brand: ${summary.brandName}\n`; } responseText += ` Resource URI: amazon-catalog://${item.asin}\n\n`; }); return { content: [ { type: 'text', text: responseText, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error searching catalog: ${error.message}`, }, ], isError: true, }; } }); // Register catalog item retrieval tool toolManager.registerTool('get-catalog-item', { title: 'Get Amazon Catalog Item', description: 'Retrieve detailed information about a product in the Amazon catalog', inputSchema: z.object({ asin: z.string().describe('Amazon Standard Identification Number (ASIN)'), includedData: z .array(z.enum([ 'attributes', 'identifiers', 'images', 'productTypes', 'relationships', 'salesRanks', 'summaries', 'variations', ])) .optional() .describe('Data to include in the response'), locale: z.string().optional().describe('Locale for localized fields'), }), }, async (input) => { try { // Validate input const validatedInput = z .object({ asin: z.string(), includedData: z .array(z.enum([ 'attributes', 'identifiers', 'images', 'productTypes', 'relationships', 'salesRanks', 'summaries', 'variations', ])) .optional(), locale: z.string().optional(), }) .parse(input); const params = { asin: validatedInput.asin, includedData: validatedInput.includedData, locale: validatedInput.locale, }; const item = await catalogClient.getCatalogItem(params); // Format the response let responseText = `Catalog Item: ${validatedInput.asin}\n\n`; // Add summary information const summary = item.summaries && item.summaries.length > 0 ? item.summaries[0] : null; if (summary) { if (summary.itemName) responseText += `Title: ${summary.itemName}\n`; if (summary.brandName) responseText += `Brand: ${summary.brandName}\n`; if (summary.manufacturer) responseText += `Manufacturer: ${summary.manufacturer}\n`; if (summary.modelNumber) responseText += `Model: ${summary.modelNumber}\n`; if (summary.colorName) responseText += `Color: ${summary.colorName}\n`; responseText += '\n'; } // Add product types if (item.productTypes) { responseText += 'Product Types:\n'; Object.entries(item.productTypes).forEach(([marketplace, type]) => { responseText += `- ${marketplace}: ${type}\n`; }); responseText += '\n'; } // Add sales ranks if available if (item.salesRanks) { responseText += 'Sales Ranks:\n'; Object.entries(item.salesRanks).forEach(([category, ranks]) => { responseText += `- ${category}:\n`; ranks.forEach((rank) => { responseText += ` - #${rank.rank} in ${rank.title}\n`; }); }); responseText += '\n'; } // Add images if available if (item.images) { responseText += 'Images:\n'; Object.entries(item.images).forEach(([marketplace, images]) => { responseText += `- ${marketplace}:\n`; images.forEach((image, index) => { responseText += ` - Image ${index + 1}: ${image.width}x${image.height} - ${image.link}\n`; }); }); responseText += '\n'; } // Add link to resource responseText += `Resource URI: amazon-catalog://${item.asin}\n`; // Add full JSON data responseText += '\nFull Item Data:\n```json\n'; responseText += JSON.stringify(item, null, 2); responseText += '\n```\n'; return { content: [ { type: 'text', text: responseText, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error retrieving catalog item: ${error.message}`, }, ], isError: true, }; } }); } //# sourceMappingURL=catalog-tools.js.map