amazon-seller-mcp
Version:
Model Context Protocol (MCP) client for Amazon Selling Partner API
350 lines • 13.3 kB
JavaScript
/**
* 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