UNPKG

amazon-seller-mcp

Version:

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

350 lines 13.3 kB
/** * Orders API client for Amazon Selling Partner API */ // Third-party dependencies import { z } from 'zod'; // Internal imports import { BaseApiClient } from './base-client.js'; /** * Orders API client for Amazon Selling Partner API */ export class OrdersClient extends BaseApiClient { /** * API version */ apiVersion = 'orders/v0'; /** * Create a new OrdersClient instance * * @param authConfig Authentication configuration */ constructor(authConfig) { super(authConfig); } /** * Get orders * * @param params Parameters for retrieving orders * @returns Promise resolving to the orders result */ async getOrders(params = {}) { const { createdAfter, createdBefore, lastUpdatedAfter, lastUpdatedBefore, orderStatuses, fulfillmentChannels, paymentMethods, buyerEmail, sellerOrderId, maxResultsPerPage, nextToken, amazonOrderIds, itemCategories, easyShipShipmentStatuses, } = params; // Build query parameters const query = { MarketplaceIds: this.config.marketplaceId, }; if (createdAfter) { query.CreatedAfter = createdAfter; } if (createdBefore) { query.CreatedBefore = createdBefore; } if (lastUpdatedAfter) { query.LastUpdatedAfter = lastUpdatedAfter; } if (lastUpdatedBefore) { query.LastUpdatedBefore = lastUpdatedBefore; } if (orderStatuses && orderStatuses.length > 0) { query.OrderStatuses = orderStatuses; } if (fulfillmentChannels && fulfillmentChannels.length > 0) { query.FulfillmentChannels = fulfillmentChannels; } if (paymentMethods && paymentMethods.length > 0) { query.PaymentMethods = paymentMethods; } if (buyerEmail) { query.BuyerEmail = buyerEmail; } if (sellerOrderId) { query.SellerOrderId = sellerOrderId; } if (maxResultsPerPage) { query.MaxResultsPerPage = Math.min(100, Math.max(1, maxResultsPerPage)); // Ensure maxResultsPerPage is between 1 and 100 } if (nextToken) { query.NextToken = nextToken; } if (amazonOrderIds && amazonOrderIds.length > 0) { query.AmazonOrderIds = amazonOrderIds; } if (itemCategories && itemCategories.length > 0) { query.ItemCategories = itemCategories; } if (easyShipShipmentStatuses && easyShipShipmentStatuses.length > 0) { query.EasyShipShipmentStatuses = easyShipShipmentStatuses; } // Make API request const requestOptions = { method: 'GET', path: `/${this.apiVersion}/orders`, query: query, }; // Use cache for orders (30 seconds TTL) const cacheKey = `orders:${this.config.marketplaceId}:${JSON.stringify(query)}`; return this.withCache(cacheKey, async () => { const response = await this.request(requestOptions); return response.data.payload; }, 30 // 30 seconds TTL ); } /** * Get a single order by Amazon order ID * * @param params Parameters for retrieving a single order * @returns Promise resolving to the order */ async getOrder(params) { const { amazonOrderId } = params; // Make API request const requestOptions = { method: 'GET', path: `/${this.apiVersion}/orders/${amazonOrderId}`, }; // Use cache for order (30 seconds TTL) const cacheKey = `order:${amazonOrderId}`; return this.withCache(cacheKey, async () => { const response = await this.request(requestOptions); return response.data.payload; }, 30 // 30 seconds TTL ); } /** * Get order items * * @param params Parameters for retrieving order items * @returns Promise resolving to the order items result */ async getOrderItems(params) { const { amazonOrderId, nextToken } = params; // Build query parameters const query = {}; if (nextToken) { query.NextToken = nextToken; } // Make API request const requestOptions = { method: 'GET', path: `/${this.apiVersion}/orders/${amazonOrderId}/orderItems`, query, }; // Use cache for order items (30 seconds TTL) const cacheKey = `orderItems:${amazonOrderId}:${nextToken || 'first'}`; return this.withCache(cacheKey, async () => { const response = await this.request(requestOptions); return response.data.payload; }, 30 // 30 seconds TTL ); } /** * Update order status * * @param params Parameters for updating order status * @returns Promise resolving to the order update result */ async updateOrderStatus(params) { const { amazonOrderId, action, details } = params; // Validate update order status parameters this.validateUpdateOrderStatusParams(params); let path = ''; let requestBody = {}; // Build request based on action switch (action) { case 'CONFIRM': path = `/${this.apiVersion}/orders/${amazonOrderId}/confirmation`; break; case 'SHIP': if (!details?.shippingDetails) { throw new Error('Shipping details are required for SHIP action'); } path = `/${this.apiVersion}/orders/${amazonOrderId}/shipment`; requestBody = { carrierCode: details.shippingDetails.carrierCode, trackingNumber: details.shippingDetails.trackingNumber, shipDate: details.shippingDetails.shipDate, items: details.shippingDetails.items, }; break; case 'CANCEL': if (!details?.cancellationReason) { throw new Error('Cancellation reason is required for CANCEL action'); } path = `/${this.apiVersion}/orders/${amazonOrderId}/cancellation`; requestBody = { cancellationReason: details.cancellationReason, }; break; default: throw new Error(`Unsupported action: ${action}`); } // Make API request const requestOptions = { method: 'POST', path, data: requestBody, }; const response = await this.request(requestOptions); // Clear cache for this order this.clearCache(`order:${amazonOrderId}`); this.clearCache(`orderItems:${amazonOrderId}:*`); return response.data.payload; } /** * Get order buyer info * * @param params Parameters for retrieving order buyer info * @returns Promise resolving to the order buyer info */ async getOrderBuyerInfo(params) { const { amazonOrderId } = params; // Make API request const requestOptions = { method: 'GET', path: `/${this.apiVersion}/orders/${amazonOrderId}/buyerInfo`, }; // Use cache for order buyer info (30 seconds TTL) const cacheKey = `orderBuyerInfo:${amazonOrderId}`; return this.withCache(cacheKey, async () => { const response = await this.request(requestOptions); return response.data.payload; }, 30 // 30 seconds TTL ); } /** * Get order address * * @param params Parameters for retrieving order address * @returns Promise resolving to the order address result */ async getOrderAddress(params) { const { amazonOrderId } = params; // Make API request const requestOptions = { method: 'GET', path: `/${this.apiVersion}/orders/${amazonOrderId}/address`, }; // Use cache for order address (30 seconds TTL) const cacheKey = `orderAddress:${amazonOrderId}`; return this.withCache(cacheKey, async () => { const response = await this.request(requestOptions); return response.data.payload; }, 30 // 30 seconds TTL ); } /** * Get order fulfillment * * @param params Parameters for retrieving order fulfillment * @returns Promise resolving to the order fulfillment result */ async getOrderFulfillment(params) { const { amazonOrderId } = params; // Make API request const requestOptions = { method: 'GET', path: `/${this.apiVersion}/orders/${amazonOrderId}/fulfillment`, }; // Use cache for order fulfillment (30 seconds TTL) const cacheKey = `orderFulfillment:${amazonOrderId}`; return this.withCache(cacheKey, async () => { const response = await this.request(requestOptions); return response.data.payload; }, 30 // 30 seconds TTL ); } /** * Validate update order status parameters * * @param params Parameters to validate * @throws Error if validation fails */ validateUpdateOrderStatusParams(params) { const { action } = params; // Define validation schema using zod const baseSchema = z.object({ amazonOrderId: z.string().min(1, 'Amazon order ID is required'), action: z.enum(['CONFIRM', 'SHIP', 'CANCEL'], { errorMap: () => ({ message: 'Action must be one of: CONFIRM, SHIP, CANCEL' }), }), }); // Additional validation based on action switch (action) { case 'SHIP': { const shipSchema = baseSchema.extend({ details: z .object({ shippingDetails: z .object({ carrierCode: z.string().min(1, 'Carrier code is required'), trackingNumber: z.string().min(1, 'Tracking number is required'), shipDate: z .string() .regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}Z)?$/, 'Ship date must be in ISO 8601 format'), items: z .array(z.object({ orderItemId: z.string().min(1, 'Order item ID is required'), quantity: z.number().int().positive('Quantity must be a positive integer'), })) .min(1, 'At least one item is required'), }) .required(), }) .required(), }); try { shipSchema.parse(params); } catch (error) { if (error instanceof z.ZodError) { const formattedErrors = error.errors .map((err) => `${err.path.join('.')}: ${err.message}`) .join(', '); throw new Error(`Validation failed for SHIP action: ${formattedErrors}`); } throw error; } break; } case 'CANCEL': { const cancelSchema = baseSchema.extend({ details: z .object({ cancellationReason: z.string().min(1, 'Cancellation reason is required'), }) .required(), }); try { cancelSchema.parse(params); } catch (error) { if (error instanceof z.ZodError) { const formattedErrors = error.errors .map((err) => `${err.path.join('.')}: ${err.message}`) .join(', '); throw new Error(`Validation failed for CANCEL action: ${formattedErrors}`); } throw error; } break; } case 'CONFIRM': { // No additional validation needed for CONFIRM try { baseSchema.parse(params); } catch (error) { if (error instanceof z.ZodError) { const formattedErrors = error.errors .map((err) => `${err.path.join('.')}: ${err.message}`) .join(', '); throw new Error(`Validation failed for CONFIRM action: ${formattedErrors}`); } throw error; } break; } } } } //# sourceMappingURL=orders-client.js.map