amazon-seller-mcp
Version:
Model Context Protocol (MCP) client for Amazon Selling Partner API
296 lines • 13.4 kB
JavaScript
/**
* Inventory tools for Amazon Selling Partner API
*/
// Third-party dependencies
import { z } from 'zod';
import { InventoryClient, } from '../api/inventory-client.js';
/**
* Register inventory tools with the tool manager
*
* @param toolManager Tool registration manager
* @param authConfig Authentication configuration
* @param providedInventoryClient Optional inventory client to use
*/
export function registerInventoryTools(toolManager, authConfig, providedInventoryClient) {
// Use provided inventory client or create a new one
const inventoryClient = providedInventoryClient || new InventoryClient(authConfig);
// Register inventory retrieval tool
toolManager.registerTool('get-inventory', {
title: 'Get Amazon Inventory',
description: 'Retrieve inventory levels for your Amazon products',
inputSchema: z.object({
sellerSkus: z.array(z.string()).optional().describe('List of seller SKUs to filter by'),
asins: z.array(z.string()).optional().describe('List of ASINs to filter by'),
fulfillmentChannels: z
.array(z.enum(['AMAZON', 'SELLER']))
.optional()
.describe('List of fulfillment channels to filter by'),
startDateTime: z
.string()
.optional()
.describe('Filter for items updated after this date-time (ISO format)'),
endDateTime: z
.string()
.optional()
.describe('Filter for items updated before this date-time (ISO format)'),
pageSize: z
.number()
.int()
.min(1)
.max(100)
.optional()
.describe('Number of results per page (1-100)'),
nextToken: z.string().optional().describe('Token for pagination'),
}),
}, async (input) => {
try {
// Validate input
const validatedInput = z
.object({
sellerSkus: z.array(z.string()).optional(),
asins: z.array(z.string()).optional(),
fulfillmentChannels: z.array(z.enum(['AMAZON', 'SELLER'])).optional(),
startDateTime: z.string().optional(),
endDateTime: z.string().optional(),
pageSize: z.number().int().min(1).max(100).optional(),
nextToken: z.string().optional(),
})
.parse(input);
const params = {
sellerSkus: validatedInput.sellerSkus,
asins: validatedInput.asins,
fulfillmentChannels: validatedInput.fulfillmentChannels,
startDateTime: validatedInput.startDateTime
? new Date(validatedInput.startDateTime)
: undefined,
endDateTime: validatedInput.endDateTime
? new Date(validatedInput.endDateTime)
: undefined,
pageSize: validatedInput.pageSize,
nextToken: validatedInput.nextToken,
};
const result = await inventoryClient.getInventory(params);
// Format the response
let responseText = `# Amazon Inventory\n\n`;
if (result.items.length === 0) {
responseText += `No inventory items found matching the criteria.\n`;
}
else {
responseText += `Found ${result.items.length} inventory items\n\n`;
// Add pagination info if available
if (result.nextToken) {
responseText += `Next page token: ${result.nextToken}\n\n`;
}
// Add inventory items
responseText += `## Inventory Items\n\n`;
result.items.forEach((item, index) => {
responseText += `### ${index + 1}. ${item.sku}\n\n`;
if (item.asin) {
responseText += `**ASIN:** ${item.asin}\n\n`;
}
if (item.condition) {
responseText += `**Condition:** ${item.condition}\n\n`;
}
// Add inventory levels by fulfillment channel
responseText += `**Inventory Levels:**\n\n`;
item.inventoryDetails.forEach((detail) => {
responseText += `- **${detail.fulfillmentChannelCode}:** ${detail.quantity} units`;
if (detail.reservedQuantity !== undefined) {
responseText += ` (${detail.reservedQuantity} reserved)`;
}
if (detail.restockDate) {
responseText += `\n **Restock Date:** ${new Date(detail.restockDate).toLocaleDateString()}`;
}
// Add replenishment settings if available
if (detail.replenishmentSettings) {
responseText += `\n **Replenishment Settings:**`;
if (detail.replenishmentSettings.restockLevel !== undefined) {
responseText += `\n - Restock Level: ${detail.replenishmentSettings.restockLevel}`;
}
if (detail.replenishmentSettings.targetLevel !== undefined) {
responseText += `\n - Target Level: ${detail.replenishmentSettings.targetLevel}`;
}
if (detail.replenishmentSettings.maximumLevel !== undefined) {
responseText += `\n - Maximum Level: ${detail.replenishmentSettings.maximumLevel}`;
}
if (detail.replenishmentSettings.leadTimeDays !== undefined) {
responseText += `\n - Lead Time: ${detail.replenishmentSettings.leadTimeDays} days`;
}
}
responseText += '\n\n';
});
responseText += `**Last Updated:** ${new Date(item.lastUpdatedTime).toLocaleString()}\n\n`;
responseText += `Resource URI: amazon-inventory://${item.sku}\n\n`;
responseText += `---\n\n`;
});
}
return {
content: [
{
type: 'text',
text: responseText,
},
],
};
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error retrieving inventory: ${error.message}`,
},
],
isError: true,
};
}
});
// Register inventory update tool
toolManager.registerTool('update-inventory', {
title: 'Update Amazon Inventory',
description: 'Update inventory quantity for a product',
inputSchema: z.object({
sku: z.string().describe('Seller SKU for the product'),
quantity: z.number().int().min(0).describe('New inventory quantity'),
fulfillmentChannel: z.enum(['AMAZON', 'SELLER']).describe('Fulfillment channel'),
restockDate: z
.string()
.optional()
.describe('Restock date for future inventory (ISO format)'),
}),
}, async (input) => {
try {
// Validate input
const validatedInput = z
.object({
sku: z.string(),
quantity: z.number().int().min(0),
fulfillmentChannel: z.enum(['AMAZON', 'SELLER']),
restockDate: z.string().optional(),
})
.parse(input);
const params = {
sku: validatedInput.sku,
quantity: validatedInput.quantity,
fulfillmentChannel: validatedInput.fulfillmentChannel,
restockDate: validatedInput.restockDate
? new Date(validatedInput.restockDate)
: undefined,
};
const result = await inventoryClient.updateInventory(params);
// Format the response
let responseText = `# Inventory Update Result\n\n`;
responseText += `**SKU:** ${result.sku}\n\n`;
responseText += `**Fulfillment Channel:** ${result.fulfillmentChannel}\n\n`;
responseText += `**Status:** ${result.status}\n\n`;
if (result.status === 'FAILED') {
responseText += `**Error Code:** ${result.errorCode || 'Unknown'}\n\n`;
responseText += `**Error Message:** ${result.errorMessage || 'No error message provided'}\n\n`;
}
else {
responseText += `Successfully updated inventory for SKU ${result.sku} to ${validatedInput.quantity} units.\n\n`;
responseText += `Resource URI: amazon-inventory://${result.sku}\n\n`;
}
return {
content: [
{
type: 'text',
text: responseText,
},
],
};
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error updating inventory: ${error.message}`,
},
],
isError: true,
};
}
});
// Register inventory replenishment settings tool
toolManager.registerTool('set-inventory-replenishment', {
title: 'Set Inventory Replenishment Settings',
description: 'Configure inventory replenishment settings for a product',
inputSchema: z.object({
sku: z.string().describe('Seller SKU for the product'),
restockLevel: z
.number()
.int()
.min(0)
.describe('Restock level (minimum quantity before reordering)'),
targetLevel: z
.number()
.int()
.min(0)
.describe('Target level (desired quantity after reordering)'),
maximumLevel: z.number().int().min(0).optional().describe('Maximum inventory level'),
leadTimeDays: z.number().int().min(1).optional().describe('Lead time in days'),
}),
}, async (input) => {
try {
// Validate input
const validatedInput = z
.object({
sku: z.string(),
restockLevel: z.number().int().min(0),
targetLevel: z.number().int().min(0),
maximumLevel: z.number().int().min(0).optional(),
leadTimeDays: z.number().int().min(1).optional(),
})
.parse(input);
const params = {
sku: validatedInput.sku,
restockLevel: validatedInput.restockLevel,
targetLevel: validatedInput.targetLevel,
maximumLevel: validatedInput.maximumLevel,
leadTimeDays: validatedInput.leadTimeDays,
};
const result = await inventoryClient.setInventoryReplenishment(params);
// Format the response
let responseText = `# Inventory Replenishment Settings Result\n\n`;
responseText += `**SKU:** ${result.sku}\n\n`;
responseText += `**Status:** ${result.status}\n\n`;
if (result.status === 'FAILED') {
responseText += `**Error Code:** ${result.errorCode || 'Unknown'}\n\n`;
responseText += `**Error Message:** ${result.errorMessage || 'No error message provided'}\n\n`;
}
else {
responseText += `Successfully updated replenishment settings for SKU ${result.sku}.\n\n`;
responseText += `**Restock Level:** ${validatedInput.restockLevel}\n\n`;
responseText += `**Target Level:** ${validatedInput.targetLevel}\n\n`;
if (validatedInput.maximumLevel !== undefined) {
responseText += `**Maximum Level:** ${validatedInput.maximumLevel}\n\n`;
}
if (validatedInput.leadTimeDays !== undefined) {
responseText += `**Lead Time:** ${validatedInput.leadTimeDays} days\n\n`;
}
responseText += `Resource URI: amazon-inventory://${result.sku}\n\n`;
}
return {
content: [
{
type: 'text',
text: responseText,
},
],
};
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error setting inventory replenishment: ${error.message}`,
},
],
isError: true,
};
}
});
}
//# sourceMappingURL=inventory-tools.js.map