Skip to main content
Glama

Amazon Order History CSV Download MCP

by marcusquinn
index.ts47.5 kB
#!/usr/bin/env node /** * Amazon Order History CSV Download MCP Server * * MCP server for extracting Amazon order history and exporting to CSV. */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, ProgressNotification, } from "@modelcontextprotocol/sdk/types.js"; import { chromium, BrowserContext, Page } from "playwright"; import { join } from "path"; import { homedir } from "os"; import { AmazonPlugin } from "./amazon/adapter"; import { getRegionCodes } from "./amazon/regions"; import { fetchOrders, exportOrdersCSV, exportItemsCSV, exportShipmentsCSV, exportTransactionsCSV, exportGiftCardTransactionsCSV, getOutputPath, estimateExtractionTime, GiftCardTransactionCSVData, } from "./tools"; import { extractTransactionsFromPage } from "./amazon/extractors/transactions-page"; import { extractGiftCardData, GiftCardData, } from "./amazon/extractors/gift-card"; // Initialize the Amazon plugin const amazonPlugin = new AmazonPlugin(); // Browser context instance (lazy initialized) let browserContext: BrowserContext | null = null; let page: Page | null = null; // Browser data directory for session persistence const BROWSER_DATA_DIR = join( homedir(), ".amazon-order-history-mcp", "browser-data", ); /** * Get or create browser context instance. */ async function getBrowserContext(): Promise<BrowserContext> { if (!browserContext) { browserContext = await chromium.launchPersistentContext(BROWSER_DATA_DIR, { headless: false, // Need visible browser for login viewport: { width: 1280, height: 800 }, userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", }); } return browserContext; } /** * Get or create page instance. */ async function getPage(): Promise<Page> { const context = await getBrowserContext(); if (!page || page.isClosed()) { const pages = context.pages(); page = pages[0] || (await context.newPage()); } return page; } /** * Validate region parameter and return error response if invalid. */ function validateRegion( region: string | undefined, args: Record<string, unknown> | undefined, ): { content: Array<{ type: string; text: string }>; isError: true } | null { if (!region) { return { content: [ { type: "text", text: JSON.stringify( { error: "region parameter is required", validRegions: getRegionCodes(), receivedArgs: args, }, null, 2, ), }, ], isError: true, }; } if (!getRegionCodes().includes(region)) { return { content: [ { type: "text", text: JSON.stringify( { error: `Invalid region: "${region}"`, validRegions: getRegionCodes(), receivedArgs: args, }, null, 2, ), }, ], isError: true, }; } return null; // Valid region } // Define MCP tools const tools: Tool[] = [ { name: "get_amazon_orders", description: "Fetch Amazon order history for a specified date range or year. Returns order summaries including: order ID, date, total amount, status, item count, shipping address (7 lines), payment method, and Subscribe & Save frequency. Optionally includes detailed item data (ASIN, name, price, quantity, seller, condition) and shipment tracking. Use for browsing order history or building reports.", inputSchema: { type: "object", properties: { region: { type: "string", description: `Amazon region code. Supported: ${getRegionCodes().join(", ")}`, enum: getRegionCodes(), }, year: { type: "number", description: "Year to fetch orders from (e.g., 2024). If omitted, uses current year.", }, start_date: { type: "string", description: "Start date in ISO format (YYYY-MM-DD). Overrides year if provided.", }, end_date: { type: "string", description: "End date in ISO format (YYYY-MM-DD). Overrides year if provided.", }, include_items: { type: "boolean", description: "Extract item details (ASIN, name, price, quantity, seller, condition) from each order's invoice page. Adds ~2s per order.", default: false, }, include_shipments: { type: "boolean", description: "Extract shipment info (delivery status, tracking link) from each order's detail page. Adds ~2s per order. Note: tracking link URL is captured but not the carrier tracking number - use fetch_tracking_numbers for that.", default: false, }, fetch_tracking_numbers: { type: "boolean", description: "Extract actual carrier tracking numbers (e.g., AZ218181365JE) by visiting each shipment's 'Track package' page. Adds ~2s per shipment. Only works when include_shipments is true.", default: false, }, max_orders: { type: "number", description: "Maximum number of orders to fetch. Use to limit results for large accounts or avoid timeouts.", }, }, required: ["region"], }, }, { name: "get_amazon_order_details", description: "Get comprehensive details for a specific Amazon order by order ID. Returns full order data including: items (ASIN, name, price, quantity, seller, condition), financial breakdown (subtotal, shipping, tax, VAT, promotions, total), shipping address, payment methods, and optionally shipment tracking and transaction history.", inputSchema: { type: "object", properties: { order_id: { type: "string", description: "Amazon order ID in format XXX-XXXXXXX-XXXXXXX (e.g., 123-4567890-1234567)", }, region: { type: "string", description: "Amazon region code where the order was placed", enum: getRegionCodes(), }, include_shipments: { type: "boolean", description: "Extract shipment info from order detail page (default: true)", default: true, }, fetch_tracking_numbers: { type: "boolean", description: "Extract actual carrier tracking number (e.g., AZ218181365JE) by visiting the 'Track package' page. Adds ~2s per shipment.", default: false, }, include_transactions: { type: "boolean", description: "Include payment transaction details (default: false)", default: false, }, }, required: ["order_id", "region"], }, }, { name: "export_amazon_orders_csv", description: "Export Amazon orders summary to CSV file. Fast extraction from order list page (~0.5s per 10 orders). CSV columns: Order ID, Date, Total, Status, Item Count, Address (7 lines), Subscribe & Save, Platform, Region, Order URL. Defaults to ~/Downloads with auto-generated filename. For large accounts (500+ orders), use max_orders to batch exports and avoid timeouts.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, year: { type: "number", description: "Year to export (defaults to current year)", }, start_date: { type: "string", description: "Start date in ISO format (YYYY-MM-DD)", }, end_date: { type: "string", description: "End date in ISO format (YYYY-MM-DD)", }, output_path: { type: "string", description: "Full path to save CSV file. Defaults to ~/Downloads/amazon-{region}-orders-{year}-{date}.csv", }, max_orders: { type: "number", description: "Maximum number of orders to export. Recommended: 100-200 per batch for large accounts.", }, }, required: ["region"], }, }, { name: "export_amazon_items_csv", description: "Export detailed Amazon order items to CSV file. Visits each order's invoice page to extract item-level data (~2s/order). CSV columns: Order ID, Date, ASIN, Product Name, Condition, Quantity, Unit Price, Item Total, Seller, Subscribe & Save, Order financials (Subtotal, Shipping, Tax, VAT, Promotion, Total), Status, Address (7 lines), Payment Method, Product URL, Order URL, Region. Ideal for expense tracking, inventory analysis, or accounting exports.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, year: { type: "number", description: "Year to export (defaults to current year)", }, start_date: { type: "string", description: "Start date in ISO format (YYYY-MM-DD)", }, end_date: { type: "string", description: "End date in ISO format (YYYY-MM-DD)", }, output_path: { type: "string", description: "Full path to save CSV file. Defaults to ~/Downloads/amazon-{region}-items-{year}-{date}.csv", }, max_orders: { type: "number", description: "Maximum number of orders to process. Recommended: 50-100 per batch due to ~2s/order extraction time.", }, }, required: ["region"], }, }, { name: "export_amazon_shipments_csv", description: "Export Amazon shipment tracking data to CSV file. Visits each order's detail page to extract tracking info (~4s/order). CSV columns: Order ID, Date, Shipment ID, Status, Delivered (Yes/No/Unknown), Tracking ID, Tracking URL, Items in Shipment, Item Names, Payment Amount, Refund. Useful for tracking deliveries and reconciling shipments.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, year: { type: "number", description: "Year to export (defaults to current year)", }, start_date: { type: "string", description: "Start date in ISO format (YYYY-MM-DD)", }, end_date: { type: "string", description: "End date in ISO format (YYYY-MM-DD)", }, output_path: { type: "string", description: "Full path to save CSV file. Defaults to ~/Downloads/amazon-{region}-shipments-{year}-{date}.csv", }, max_orders: { type: "number", description: "Maximum number of orders to process. Recommended: 25-50 per batch due to ~4s/order extraction time.", }, fetch_tracking_numbers: { type: "boolean", description: "Extract actual carrier tracking numbers (e.g., AZ218181365JE) by visiting each shipment's 'Track package' page. Adds ~2s per shipment.", default: false, }, }, required: ["region"], }, }, { name: "export_amazon_transactions_csv", description: "Export Amazon payment transactions to CSV file. Extracts transaction data from each order's detail page. CSV columns include: date, order ID, amount, payment method, card info. For faster bulk transaction export, consider get_amazon_transactions which scrapes the dedicated transactions page.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, year: { type: "number", description: "Year to export (defaults to current year)", }, start_date: { type: "string", description: "Start date in ISO format (YYYY-MM-DD)", }, end_date: { type: "string", description: "End date in ISO format (YYYY-MM-DD)", }, output_path: { type: "string", description: "Full path to save CSV file. Defaults to ~/Downloads/amazon-{region}-transactions-{year}-{date}.csv", }, max_orders: { type: "number", description: "Maximum number of orders to process", }, }, required: ["region"], }, }, { name: "get_amazon_transactions", description: "Fetch all Amazon payment transactions from the dedicated transactions page. Faster than per-order extraction as it scrapes the infinite-scroll transactions list. Returns: date, order IDs, amount, payment method, card info (last 4 digits), vendor. Useful for reconciling payments, tracking spending, or exporting for accounting.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, start_date: { type: "string", description: "Start date filter in ISO format (YYYY-MM-DD)", }, end_date: { type: "string", description: "End date filter in ISO format (YYYY-MM-DD)", }, max_scrolls: { type: "number", description: "Maximum scroll attempts to load more transactions. Default: 50. Increase for longer history.", }, }, required: ["region"], }, }, { name: "get_amazon_gift_card_balance", description: "Get current Amazon gift card balance and transaction history. Returns: current balance, last updated timestamp, and paginated transaction history (date, description, amount, closing balance, type, associated order ID, claim code, serial number). Supports fetching complete history across multiple pages.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, max_pages: { type: "number", description: "Maximum pages of transaction history to fetch. Default: 10. Set to 0 for unlimited.", default: 10, }, fetch_all_pages: { type: "boolean", description: "Automatically paginate through all available transaction history. Default: true.", default: true, }, }, required: ["region"], }, }, { name: "export_amazon_gift_cards_csv", description: "Export Amazon gift card transaction history to CSV file. CSV columns: Date, Description, Amount, Closing Balance, Type (credit/debit), Order ID, Claim Code, Serial Number, Region. Useful for tracking gift card usage and reconciling balances.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, output_path: { type: "string", description: "Full path to save CSV file. Defaults to ~/Downloads/amazon-{region}-gift-cards-{date}.csv", }, max_pages: { type: "number", description: "Maximum pages of transaction history to fetch. Default: 10. Set to 0 for unlimited.", default: 10, }, }, required: ["region"], }, }, { name: "get_amazon_gift_card_transactions", description: "Get Amazon gift card transaction history with full details. Returns: current balance, transaction count, and detailed transactions (date, description, amount, closing balance, transaction type, order ID, claim code, serial number). Supports pagination for complete history.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code", enum: getRegionCodes(), }, max_pages: { type: "number", description: "Maximum pages of transaction history to fetch. Default: 10. Set to 0 for unlimited.", default: 10, }, }, required: ["region"], }, }, { name: "check_amazon_auth_status", description: "Check if the browser session is authenticated with Amazon for a specific region. Returns authentication status (authenticated/not authenticated), current URL, and any error messages. Use this to verify login status before running other tools, or to prompt user to log in if session expired.", inputSchema: { type: "object", properties: { region: { type: "string", description: "Amazon region code to check authentication for", enum: getRegionCodes(), }, }, required: ["region"], }, }, ]; // Create server instance const server = new Server( { name: "amazon-order-history-csv-download-mcp", version: "0.3.0", }, { capabilities: { tools: {}, }, }, ); /** * Send progress notification to client. */ async function sendProgress( progressToken: string | number | undefined, progress: number, total: number, message: string, ): Promise<void> { if (!progressToken) return; try { await server.notification({ method: "notifications/progress", params: { progressToken, progress, total, message, }, } as unknown as ProgressNotification); } catch (e) { // Progress notifications are optional, don't fail on errors console.error(`[progress] Failed to send: ${e}`); } } /** * Shared gift card data structure for export. */ interface GiftCardExportData { balance: { amount: number; currency: string; formatted: string; }; lastUpdated: string; region: string; transactionCount: number; transactions: Array<{ date: string; description: string; amount: { amount: number; currency: string; currencySymbol: string; formatted: string; }; closingBalance: { amount: number; currency: string; currencySymbol: string; formatted: string; }; type: string; orderId?: string; claimCode?: string; serialNumber?: string; }>; } /** * Convert GiftCardData to export format (shared by CSV and JSON exports). */ function formatGiftCardDataForExport( giftCardData: GiftCardData, ): GiftCardExportData { return { balance: { amount: giftCardData.balance.balance.amount, currency: giftCardData.balance.balance.currency, formatted: giftCardData.balance.balance.formatted, }, lastUpdated: giftCardData.balance.lastUpdated.toISOString(), region: giftCardData.region, transactionCount: giftCardData.transactions.length, transactions: giftCardData.transactions.map((t) => ({ date: t.date.toISOString(), description: t.description, amount: { amount: t.amount.amount, currency: t.amount.currency, currencySymbol: t.amount.currencySymbol, formatted: t.amount.formatted, }, closingBalance: { amount: t.closingBalance.amount, currency: t.closingBalance.currency, currencySymbol: t.closingBalance.currencySymbol, formatted: t.closingBalance.formatted, }, type: t.type, orderId: t.orderId, claimCode: t.claimCode, serialNumber: t.serialNumber, })), }; } /** * Convert GiftCardData to CSV export format. */ function formatGiftCardDataForCSV( giftCardData: GiftCardData, ): GiftCardTransactionCSVData[] { return giftCardData.transactions.map((t) => ({ date: t.date, description: t.description, amount: t.amount, closingBalance: t.closingBalance, type: t.type, orderId: t.orderId, claimCode: t.claimCode, serialNumber: t.serialNumber, region: giftCardData.region, })); } // Handle list tools request server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case "get_amazon_orders": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; // Validated above // Get progress token from request meta const progressToken = request.params._meta?.progressToken; const currentPage = await getPage(); const result = await fetchOrders(currentPage, amazonPlugin, { region, year: args?.year as number | undefined, startDate: args?.start_date as string | undefined, endDate: args?.end_date as string | undefined, includeItems: args?.include_items as boolean | undefined, includeShipments: args?.include_shipments as boolean | undefined, fetchTrackingNumbers: args?.fetch_tracking_numbers as | boolean | undefined, maxOrders: args?.max_orders as number | undefined, onProgress: async (message, current, total) => { await sendProgress(progressToken, current, total, message); }, }); return { content: [ { type: "text", text: JSON.stringify( { status: "success", // Echo input parameters for debugging params: { region, year: args?.year, startDate: args?.start_date, endDate: args?.end_date, includeItems: args?.include_items, includeShipments: args?.include_shipments, fetchTrackingNumbers: args?.fetch_tracking_numbers, maxOrders: args?.max_orders, }, totalOrders: result.totalFound, orders: result.orders.map((o) => ({ id: o.id, date: o.date?.toISOString(), total: o.total, status: o.status?.label || "Unknown", // Use itemCount from order header (extracted from list page) or fall back to items array length itemCount: o.itemCount ?? o.items?.length ?? 0, shipmentCount: o.shipments?.length || 0, // Enhanced order header data from list page subtotal: o.subtotal, shipping: o.shipping, tax: o.tax, vat: o.vat, promotion: o.promotion, grandTotal: o.grandTotal, // Shipping address shippingAddress: o.shippingAddress, // Payment method from list page paymentMethod: o.paymentMethod, // Recipient (simple name) recipient: typeof o.recipient === "object" ? o.recipient : { name: o.recipient }, // Payments from detail/invoice payments: o.payments, // Include items when extracted items: o.items?.map((i) => ({ name: i.name, asin: i.asin, quantity: i.quantity, unitPrice: i.unitPrice, condition: i.condition, seller: i.seller?.name, subscriptionFrequency: i.subscriptionFrequency, })), // Include shipments when extracted shipments: o.shipments?.map((s) => ({ shipmentId: s.shipmentId, status: s.status, delivered: s.delivered, trackingId: s.trackingId, carrier: s.carrier, trackingLink: s.trackingLink, itemCount: s.items?.length || 0, })), })), itemCount: result.items.length, shipmentCount: result.shipments.length, errors: result.errors, }, null, 2, ), }, ], }; } case "get_amazon_order_details": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const orderId = args?.order_id as string; const includeShipments = args?.include_shipments as boolean | undefined; const fetchTrackingNumbers = args?.fetch_tracking_numbers as | boolean | undefined; const includeTransactions = args?.include_transactions as | boolean | undefined; // Use the same fetchOrders logic that works for get_amazon_orders const result = await fetchOrders(currentPage, amazonPlugin, { region, orderId, // This triggers single-order mode includeItems: true, includeShipments: includeShipments ?? true, fetchTrackingNumbers: fetchTrackingNumbers ?? false, includeTransactions: includeTransactions ?? false, }); const order = result.orders[0]; return { content: [ { type: "text", text: JSON.stringify( { status: result.errors.length > 0 ? "error" : "success", params: { orderId, region, includeShipments, fetchTrackingNumbers, includeTransactions, }, order: order ? { id: order.id, date: order.date?.toISOString(), total: order.total, shipping: order.shipping, tax: order.tax, recipient: order.recipient, payments: order.payments, itemCount: order.items?.length || 0, shipmentCount: order.shipments?.length || 0, } : null, items: result.items.map((i) => ({ name: i.name, asin: i.asin, quantity: i.quantity, unitPrice: i.unitPrice, condition: i.condition, seller: i.seller?.name, subscriptionFrequency: i.subscriptionFrequency, })), shipments: result.shipments.map((s) => ({ shipmentId: s.shipmentId, status: s.status, delivered: s.delivered, trackingId: s.trackingId, carrier: s.carrier, trackingLink: s.trackingLink, itemCount: s.items?.length || 0, })), transactions: result.transactions.map((t) => ({ date: t.date.toISOString(), amount: t.amount, vendor: t.vendor, cardInfo: t.cardInfo, })), errors: result.errors, }, null, 2, ), }, ], }; } case "export_amazon_orders_csv": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const year = args?.year as number | undefined; const startDate = args?.start_date as string | undefined; const endDate = args?.end_date as string | undefined; const maxOrders = args?.max_orders as number | undefined; const outputPath = getOutputPath( args?.output_path as string | undefined, "orders", region, { year, startDate, endDate }, ); const fetchResult = await fetchOrders(currentPage, amazonPlugin, { region, year, startDate, endDate, includeItems: false, includeShipments: false, maxOrders, }); // Calculate time estimate for informational purposes const timeEstimate = estimateExtractionTime(fetchResult.orders.length, { includeItems: false, includeShipments: false, }); const exportResult = await exportOrdersCSV( fetchResult.orders, outputPath, ); return { content: [ { type: "text", text: JSON.stringify( { status: exportResult.success ? "success" : "error", params: { region, year, startDate, endDate, maxOrders, outputPath, }, filePath: exportResult.filePath, rowCount: exportResult.rowCount, error: exportResult.error, fetchErrors: fetchResult.errors, // Include timing info for transparency timing: { orderCount: fetchResult.orders.length, estimate: timeEstimate.formattedEstimate, warnings: timeEstimate.warnings, recommendations: timeEstimate.recommendations, }, }, null, 2, ), }, ], }; } case "export_amazon_items_csv": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const year = args?.year as number | undefined; const startDate = args?.start_date as string | undefined; const endDate = args?.end_date as string | undefined; const maxOrders = args?.max_orders as number | undefined; const outputPath = getOutputPath( args?.output_path as string | undefined, "items", region, { year, startDate, endDate }, ); // Pre-estimate time for items extraction (slower due to invoice/detail page visits) const preEstimate = estimateExtractionTime(maxOrders || 100, { includeItems: true, includeShipments: false, useInvoice: true, }); // Warn if this might take a while if (preEstimate.warnings.length > 0) { console.error( `[export-items] Time estimate: ${preEstimate.formattedEstimate}`, ); console.error( `[export-items] Warnings: ${preEstimate.warnings.join(", ")}`, ); } const fetchResult = await fetchOrders(currentPage, amazonPlugin, { region, year, startDate, endDate, includeItems: true, includeShipments: false, maxOrders, }); // Calculate actual time estimate based on orders found const timeEstimate = estimateExtractionTime(fetchResult.orders.length, { includeItems: true, includeShipments: false, useInvoice: true, }); const exportResult = await exportItemsCSV( fetchResult.items, outputPath, ); return { content: [ { type: "text", text: JSON.stringify( { status: exportResult.success ? "success" : "error", params: { region, year, startDate, endDate, maxOrders, outputPath, }, filePath: exportResult.filePath, rowCount: exportResult.rowCount, error: exportResult.error, fetchErrors: fetchResult.errors, timing: { orderCount: fetchResult.orders.length, itemCount: fetchResult.items.length, estimate: timeEstimate.formattedEstimate, warnings: timeEstimate.warnings, recommendations: timeEstimate.recommendations, }, }, null, 2, ), }, ], }; } case "export_amazon_shipments_csv": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const year = args?.year as number | undefined; const startDate = args?.start_date as string | undefined; const endDate = args?.end_date as string | undefined; const maxOrders = args?.max_orders as number | undefined; const fetchTrackingNumbers = args?.fetch_tracking_numbers as | boolean | undefined; const outputPath = getOutputPath( args?.output_path as string | undefined, "shipments", region, { year, startDate, endDate }, ); const fetchResult = await fetchOrders(currentPage, amazonPlugin, { region, year, startDate, endDate, includeItems: false, includeShipments: true, fetchTrackingNumbers: fetchTrackingNumbers ?? false, maxOrders, }); const timeEstimate = estimateExtractionTime(fetchResult.orders.length, { includeItems: false, includeShipments: true, }); const exportResult = await exportShipmentsCSV( fetchResult.shipments, outputPath, ); return { content: [ { type: "text", text: JSON.stringify( { status: exportResult.success ? "success" : "error", params: { region, year, startDate, endDate, maxOrders, fetchTrackingNumbers, outputPath, }, filePath: exportResult.filePath, rowCount: exportResult.rowCount, error: exportResult.error, fetchErrors: fetchResult.errors, timing: { orderCount: fetchResult.orders.length, shipmentCount: fetchResult.shipments.length, estimate: timeEstimate.formattedEstimate, warnings: timeEstimate.warnings, recommendations: timeEstimate.recommendations, }, }, null, 2, ), }, ], }; } case "export_amazon_transactions_csv": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const year = args?.year as number | undefined; const startDate = args?.start_date as string | undefined; const endDate = args?.end_date as string | undefined; const maxOrders = args?.max_orders as number | undefined; const outputPath = getOutputPath( args?.output_path as string | undefined, "transactions", region, { year, startDate, endDate }, ); const fetchResult = await fetchOrders(currentPage, amazonPlugin, { region, year, startDate, endDate, includeItems: false, includeShipments: false, includeTransactions: true, maxOrders, }); const timeEstimate = estimateExtractionTime(fetchResult.orders.length, { includeItems: false, includeShipments: false, }); const exportResult = await exportTransactionsCSV( fetchResult.transactions, outputPath, ); return { content: [ { type: "text", text: JSON.stringify( { status: exportResult.success ? "success" : "error", params: { region, year, startDate, endDate, maxOrders, outputPath, }, filePath: exportResult.filePath, rowCount: exportResult.rowCount, error: exportResult.error, fetchErrors: fetchResult.errors, timing: { orderCount: fetchResult.orders.length, transactionCount: fetchResult.transactions.length, estimate: timeEstimate.formattedEstimate, warnings: timeEstimate.warnings, recommendations: timeEstimate.recommendations, }, }, null, 2, ), }, ], }; } case "get_amazon_transactions": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const progressToken = request.params._meta?.progressToken; const startDate = args?.start_date as string | undefined; const endDate = args?.end_date as string | undefined; const maxScrolls = args?.max_scrolls as number | undefined; const transactions = await extractTransactionsFromPage( currentPage, region, { startDate: startDate ? new Date(startDate) : undefined, endDate: endDate ? new Date(endDate) : undefined, maxScrolls, onProgress: async (message, count) => { await sendProgress(progressToken, count, 0, message); }, }, ); return { content: [ { type: "text", text: JSON.stringify( { status: "success", params: { region, startDate, endDate, maxScrolls, }, transactionCount: transactions.length, transactions: transactions.map((t) => ({ date: t.date.toISOString(), orderIds: t.orderIds, amount: t.amount, cardInfo: t.cardInfo, vendor: t.vendor, })), }, null, 2, ), }, ], }; } case "get_amazon_gift_card_balance": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const maxPages = (args?.max_pages as number) ?? 10; const fetchAllPages = (args?.fetch_all_pages as boolean) ?? true; const giftCardData = await extractGiftCardData(currentPage, region, { maxPages, fetchAllPages, }); return { content: [ { type: "text", text: JSON.stringify( { status: "success", params: { region, maxPages, fetchAllPages, }, balance: giftCardData.balance.balance, lastUpdated: giftCardData.balance.lastUpdated.toISOString(), transactionCount: giftCardData.transactions.length, transactions: giftCardData.transactions.map((t) => ({ date: t.date.toISOString(), description: t.description, amount: t.amount, closingBalance: t.closingBalance, type: t.type, orderId: t.orderId, claimCode: t.claimCode, serialNumber: t.serialNumber, })), }, null, 2, ), }, ], }; } case "export_amazon_gift_cards_csv": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const outputPath = args?.output_path as string | undefined; const maxPages = (args?.max_pages as number) ?? 10; // Extract gift card transactions const giftCardData = await extractGiftCardData(currentPage, region, { maxPages, fetchAllPages: true, }); // Convert to CSV format using shared helper const csvData = formatGiftCardDataForCSV(giftCardData); // Generate output path const today = new Date().toISOString().split("T")[0]; const finalPath = getOutputPath(outputPath, "gift-cards", region, { endDate: today, }); // Export to CSV const exportResult = await exportGiftCardTransactionsCSV( csvData, finalPath, ); return { content: [ { type: "text", text: JSON.stringify( { status: exportResult.success ? "success" : "error", params: { region, maxPages, }, balance: giftCardData.balance.balance, transactionCount: giftCardData.transactions.length, filePath: exportResult.filePath, rowCount: exportResult.rowCount, error: exportResult.error, }, null, 2, ), }, ], }; } case "get_amazon_gift_card_transactions": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const maxPages = (args?.max_pages as number) ?? 10; // Extract gift card transactions const giftCardData = await extractGiftCardData(currentPage, region, { maxPages, fetchAllPages: true, }); // Convert to export format using shared helper const exportData = formatGiftCardDataForExport(giftCardData); return { content: [ { type: "text", text: JSON.stringify( { status: "success", params: { region, maxPages, }, ...exportData, }, null, 2, ), }, ], }; } case "check_amazon_auth_status": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const authStatus = await amazonPlugin.checkAuthStatus( currentPage, region, ); return { content: [ { type: "text", text: JSON.stringify( { status: authStatus.authenticated ? "success" : "error", params: { region, }, authenticated: authStatus.authenticated, username: authStatus.username, message: authStatus.message, loginUrl: authStatus.authenticated ? undefined : amazonPlugin.getLoginUrl(region), }, null, 2, ), }, ], }; } default: return { content: [ { type: "text", text: JSON.stringify({ error: `Unknown tool: ${name}`, }), }, ], isError: true, }; } } catch (error) { return { content: [ { type: "text", text: JSON.stringify({ error: String(error), }), }, ], isError: true, }; } }); // Cleanup on exit process.on("SIGINT", async () => { if (browserContext) { await browserContext.close(); } process.exit(0); }); process.on("SIGTERM", async () => { if (browserContext) { await browserContext.close(); } process.exit(0); }); // Main entry point async function main(): Promise<void> { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Amazon Order History CSV Download MCP server running"); } main().catch(console.error);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/marcusquinn/amazon-order-history-csv-download-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server