amazon-personal-shopping-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/index.js +2671 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/env.ts","../src/index.ts","../src/server.ts","../src/tools/search.ts","../src/errors.ts","../src/tools/product.ts","../src/tools/reviews.ts","../src/tools/cart.ts","../src/tools/orders.ts","../src/tools/purchase.ts","../src/tools/auth.ts","../src/providers/playwright/browser.ts","../src/utils/paths.ts","../src/providers/playwright/stealth.ts","../src/utils/logger.ts","../src/providers/playwright/auth.ts","../src/providers/playwright/scraper.ts","../src/providers/types.ts","../src/providers/serpapi.ts","../src/cache/index.ts","../src/providers/playwright/captcha.ts","../src/utils/retry.ts","../src/providers/playwright/index.ts","../src/providers/factory.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { dirname, resolve } from \"node:path\";\nimport { config } from \"dotenv\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconfig({ path: resolve(__dirname, \"..\", \".env\") });\n","import \"./env.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\nimport { createProvider } from \"./providers/factory.js\";\nimport { ensureBrowser, closeBrowser } from \"./providers/playwright/browser.js\";\n\nconst provider = createProvider();\nconst server = createServer(provider);\nconst transport = new StdioServerTransport();\n\n// Auto-install Chromium if needed before accepting tool calls\ntry {\n await ensureBrowser();\n} catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`[startup] Browser setup warning: ${message}`);\n // Don't exit — login tool will retry when called\n}\n\nawait server.connect(transport);\nconsole.error(\"amazon-shopping-mcp server started on stdio\");\n\n// Graceful shutdown\nasync function shutdown(): Promise<void> {\n console.error(\"[shutdown] Shutting down...\");\n await closeBrowser();\n await server.close();\n process.exit(0);\n}\n\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"./providers/types.js\";\nimport { registerSearchTools } from \"./tools/search.js\";\nimport { registerProductTools } from \"./tools/product.js\";\nimport { registerReviewTools } from \"./tools/reviews.js\";\nimport { registerCartTools } from \"./tools/cart.js\";\nimport { registerOrderTools } from \"./tools/orders.js\";\nimport { registerPurchaseTools } from \"./tools/purchase.js\";\nimport { registerAuthTools } from \"./tools/auth.js\";\n\nexport function createServer(provider: AmazonProvider): McpServer {\n const server = new McpServer({\n name: \"amazon-shopping-mcp\",\n version: \"0.1.0\",\n });\n\n registerAuthTools(server);\n registerSearchTools(server, provider);\n registerProductTools(server, provider);\n registerReviewTools(server, provider);\n registerCartTools(server, provider);\n registerOrderTools(server, provider);\n registerPurchaseTools(server, provider);\n\n return server;\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"../providers/types.js\";\nimport { AuthRequiredError, SessionExpiredError } from \"../errors.js\";\n\nexport function registerSearchTools(server: McpServer, provider: AmazonProvider): void {\n server.tool(\n \"search-products\",\n \"Search for products on Amazon. Returns structured product data including ASIN, title, price, rating, brand, and Prime eligibility. Requires an active Amazon session (call amazon-login first).\",\n {\n query: z.string().describe(\"Search query for Amazon products\"),\n category: z\n .string()\n .optional()\n .describe(\"Product category to filter by (e.g., 'electronics')\"),\n maxResults: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(\"Maximum number of results to return (default: 20)\"),\n },\n async ({ query, category, maxResults }) => {\n try {\n const products = await provider.searchProducts(query, category, maxResults);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(products, null, 2) }],\n isError: false,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Search failed: ${message}` }],\n isError: true,\n };\n }\n },\n );\n}\n","export class BrowserError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"BrowserError\";\n }\n}\n\nexport class BrowserNotInstalledError extends BrowserError {\n constructor(message = \"Chromium is not installed. Run: npx playwright install chromium\") {\n super(message);\n this.name = \"BrowserNotInstalledError\";\n }\n}\n\nexport class BrowserLaunchError extends BrowserError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"BrowserLaunchError\";\n }\n}\n\nexport class SessionExpiredError extends BrowserError {\n constructor(message = \"Session expired. Please call amazon-login to re-authenticate.\") {\n super(message);\n this.name = \"SessionExpiredError\";\n }\n}\n\nexport class AuthRequiredError extends BrowserError {\n constructor(message = \"Not logged in. Please call amazon-login to authenticate.\") {\n super(message);\n this.name = \"AuthRequiredError\";\n }\n}\n\nexport class ContextInUseError extends BrowserError {\n constructor(\n message = \"Browser context is already in use by another process. Close other instances first.\",\n ) {\n super(message);\n this.name = \"ContextInUseError\";\n }\n}\n\nexport class ScrapingError extends BrowserError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"ScrapingError\";\n }\n}\n\nexport class NotImplementedError extends Error {\n constructor(method: string) {\n super(`${method} is not yet implemented.`);\n this.name = \"NotImplementedError\";\n }\n}\n\nexport class CaptchaRequiredError extends BrowserError {\n constructor(\n message = \"CAPTCHA required - please solve in browser window\",\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = \"CaptchaRequiredError\";\n }\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"../providers/types.js\";\nimport { AuthRequiredError, SessionExpiredError } from \"../errors.js\";\n\nexport function registerProductTools(server: McpServer, provider: AmazonProvider): void {\n server.tool(\n \"get-product-details\",\n \"Get detailed product information for an Amazon product by ASIN. Returns title, description, features, price, rating, availability, images, and more. Requires an active Amazon session (call amazon-login first).\",\n {\n asin: z.string().describe(\"Amazon Standard Identification Number (ASIN) of the product\"),\n },\n async ({ asin }) => {\n try {\n const { details, primaryImageBase64 } = await provider.getProductDetails(asin);\n\n const content: Array<\n { type: \"text\"; text: string } | { type: \"image\"; data: string; mimeType: string }\n > = [{ type: \"text\" as const, text: JSON.stringify(details, null, 2) }];\n\n if (primaryImageBase64) {\n content.push({\n type: \"image\" as const,\n data: primaryImageBase64,\n mimeType: \"image/jpeg\",\n });\n }\n\n return { content, isError: false };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to get product details: ${message}` }],\n isError: true,\n };\n }\n },\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"../providers/types.js\";\nimport { AuthRequiredError, SessionExpiredError } from \"../errors.js\";\n\nexport function registerReviewTools(server: McpServer, provider: AmazonProvider): void {\n server.tool(\n \"get-reviews\",\n \"Get customer reviews for an Amazon product by ASIN. Returns individual reviews with author, rating, title, body, date, and verified purchase status, plus summary statistics with average rating and star distribution. Supports sorting by relevance or recency, and filtering by star rating. Requires an active Amazon session (call amazon-login first).\",\n {\n asin: z.string().describe(\"ASIN of the product to get reviews for\"),\n maxReviews: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(\"Maximum number of reviews to return (default: all from first page)\"),\n sortBy: z\n .enum([\"relevant\", \"recent\"])\n .optional()\n .describe(\"Sort reviews by relevance or most recent\"),\n filterByStars: z\n .number()\n .int()\n .min(1)\n .max(5)\n .optional()\n .describe(\"Filter reviews by star rating (1-5)\"),\n },\n async ({ asin, maxReviews, sortBy, filterByStars }) => {\n try {\n const result = await provider.getReviews(asin, maxReviews, sortBy, filterByStars);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n isError: false,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to get reviews: ${message}` }],\n isError: true,\n };\n }\n },\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"../providers/types.js\";\nimport { AuthRequiredError, SessionExpiredError } from \"../errors.js\";\n\nexport function registerCartTools(server: McpServer, provider: AmazonProvider): void {\n server.tool(\n \"add-to-cart\",\n \"Add a product to your Amazon cart. Before using this tool, confirm with the user which product and quantity they want to add. Requires an active Amazon session (call amazon-login first).\",\n {\n asin: z.string().describe(\"ASIN of the product to add to cart\"),\n quantity: z.number().int().positive().optional().describe(\"Quantity to add (default: 1)\"),\n },\n async ({ asin, quantity }) => {\n try {\n const result = await provider.addToCart(asin, quantity);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n isError: !result.success,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to add to cart: ${message}` }],\n isError: true,\n };\n }\n },\n );\n\n server.tool(\n \"view-cart\",\n \"View the contents of your Amazon cart including items, quantities, prices, and subtotal. Requires an active Amazon session (call amazon-login first).\",\n {},\n async () => {\n try {\n const cart = await provider.getCart();\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(cart, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to view cart: ${message}` }],\n isError: true,\n };\n }\n },\n );\n\n server.tool(\n \"remove-from-cart\",\n \"Remove a specific item from your Amazon cart. Before using this tool, confirm with the user which item they want to remove. Requires an active Amazon session (call amazon-login first).\",\n {\n asin: z.string().describe(\"ASIN of the product to remove from cart\"),\n },\n async ({ asin }) => {\n try {\n const result = await provider.removeFromCart(asin);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n isError: !result.success,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to remove from cart: ${message}` }],\n isError: true,\n };\n }\n },\n );\n\n server.tool(\n \"clear-cart\",\n \"Remove all items from your Amazon cart. Before using this tool, confirm with the user that they want to clear their entire cart. This action cannot be undone. Requires an active Amazon session (call amazon-login first).\",\n {},\n async () => {\n try {\n await provider.clearCart();\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Cart cleared successfully\",\n },\n ],\n isError: false,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to clear cart: ${message}` }],\n isError: true,\n };\n }\n },\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"../providers/types.js\";\nimport { AuthRequiredError, SessionExpiredError } from \"../errors.js\";\n\nexport function registerOrderTools(server: McpServer, provider: AmazonProvider): void {\n server.tool(\n \"get-order-history\",\n \"View your Amazon order history. Returns a list of past orders with order ID, date, total, status, and item count. Supports pagination and optional date filtering. Requires an active Amazon session (call amazon-login first).\",\n {\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(\"Maximum number of orders to return (1-50, default: 10)\"),\n page: z.number().int().min(1).optional().describe(\"Page number for pagination (default: 1)\"),\n startDate: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n .optional()\n .describe(\"Filter orders from this date (YYYY-MM-DD format)\"),\n endDate: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n .optional()\n .describe(\"Filter orders until this date (YYYY-MM-DD format)\"),\n },\n async ({ limit, page, startDate, endDate }) => {\n try {\n const result = await provider.getOrderHistory({\n limit,\n page,\n startDate,\n endDate,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to get order history: ${message}` }],\n isError: true,\n };\n }\n },\n );\n\n server.tool(\n \"get-order-details\",\n \"View detailed information about a specific Amazon order including all items, prices, quantities, and delivery status. Requires an active Amazon session (call amazon-login first).\",\n {\n orderId: z.string().describe(\"The Amazon order ID (e.g., 112-3456789-0123456)\"),\n },\n async ({ orderId }) => {\n try {\n const order = await provider.getOrderDetails(orderId);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(order, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to get order details: ${message}` }],\n isError: true,\n };\n }\n },\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { AmazonProvider } from \"../providers/types.js\";\nimport { AuthRequiredError, SessionExpiredError } from \"../errors.js\";\n\nexport function registerPurchaseTools(server: McpServer, provider: AmazonProvider): void {\n server.tool(\n \"perform-purchase\",\n `Complete the checkout process and place an order for all items currently in your Amazon cart.\n\n**IMPORTANT - AI SAFETY REQUIREMENT**: Before calling this tool, you MUST:\n1. Call view-cart to show the user exactly what items are in their cart\n2. Display the items, quantities, and total price to the user\n3. Ask the user to explicitly confirm they want to purchase these items\n4. Only call this tool after receiving clear confirmation (e.g., \"yes\", \"confirm\", \"proceed\")\n\nThis tool will:\n- Navigate to Amazon checkout\n- Use the default shipping address and payment method\n- Log all items and totals before placing the order\n- Complete the purchase and return the order ID\n\nRequires an active Amazon session with a valid payment method on file (call amazon-login first).`,\n {\n confirmationToken: z\n .string()\n .min(1)\n .describe(\n \"A non-empty string confirming the user has approved this purchase. Can be any confirmation like 'yes', 'confirmed', or the user's explicit approval text.\",\n ),\n },\n async ({ confirmationToken }) => {\n try {\n const result = await provider.purchase(confirmationToken);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n isError: !result.success,\n };\n } catch (error) {\n if (error instanceof SessionExpiredError || error instanceof AuthRequiredError) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Not logged in or session expired. Please call amazon-login first.\",\n },\n ],\n isError: true,\n };\n }\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: \"text\" as const, text: `Failed to complete purchase: ${message}` }],\n isError: true,\n };\n }\n },\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { login, checkSession } from \"../providers/playwright/auth.js\";\n\nexport function registerAuthTools(server: McpServer): void {\n server.tool(\n \"amazon-login\",\n \"Log in to Amazon. Opens a headed browser window for you to enter your credentials. Supports 2FA. Call this before using any other Amazon tools.\",\n {\n force: z.boolean().optional().describe(\"Force re-login even if a session already exists\"),\n },\n async ({ force }) => {\n const result = await login(force);\n return {\n content: [{ type: \"text\" as const, text: result.message }],\n isError: !result.success,\n };\n },\n );\n\n server.tool(\n \"amazon-session-status\",\n \"Check if you are currently logged in to Amazon and whether the session is valid.\",\n {},\n async () => {\n const status = await checkSession();\n return {\n content: [\n {\n type: \"text\" as const,\n text: status.message,\n },\n ],\n };\n },\n );\n}\n","import { chromium } from \"playwright\";\nimport type { BrowserContext, Page } from \"playwright\";\nimport { ensureDataDir, getDataDir } from \"../../utils/paths.js\";\nimport { BrowserLaunchError, BrowserNotInstalledError, ContextInUseError } from \"../../errors.js\";\nimport {\n STEALTH_ARGS,\n REALISTIC_USER_AGENT,\n randomViewport,\n applyStealthToContext,\n} from \"./stealth.js\";\nimport { createLogger } from \"../../utils/logger.js\";\n\nexport const AMAZON_BASE_URL = \"https://www.amazon.com\";\n\nlet browserContext: BrowserContext | null = null;\nlet activePage: Page | null = null;\n\nconst logger = createLogger(\"browser\");\n\nfunction log(message: string): void {\n logger.info(message);\n}\n\nfunction getHeadlessMode(): boolean {\n const env = process.env.AMAZON_MCP_HEADLESS;\n if (env === undefined || env === \"\") {\n return true;\n }\n if (env === \"true\") {\n return true;\n }\n if (env === \"false\") {\n return false;\n }\n log(`Warning: Invalid AMAZON_MCP_HEADLESS value \"${env}\", defaulting to true`);\n return true;\n}\n\nasync function installBrowserIfNeeded(): Promise<void> {\n try {\n const browsers = chromium.executablePath();\n if (browsers) {\n return;\n }\n } catch {\n // executablePath throws if not installed — proceed to install\n }\n\n log(\"Chromium not found. Installing...\");\n try {\n const { execSync } = await import(\"node:child_process\");\n execSync(\"npx playwright install chromium\", {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 300_000,\n });\n log(\"Chromium installed successfully\");\n } catch {\n throw new BrowserNotInstalledError(\n \"Failed to auto-install Chromium. Run manually: npx playwright install chromium\",\n );\n }\n}\n\nexport async function ensureBrowser(): Promise<void> {\n if (browserContext) {\n return;\n }\n await installBrowserIfNeeded();\n log(\"Browser ready\");\n}\n\nexport async function getBrowserContext(options?: { headless?: boolean }): Promise<BrowserContext> {\n if (browserContext) {\n return browserContext;\n }\n\n await installBrowserIfNeeded();\n\n const dataDir = ensureDataDir();\n const headless = options?.headless ?? getHeadlessMode();\n\n log(`Launching browser (headless: ${headless}, data: ${dataDir})`);\n\n try {\n browserContext = await chromium.launchPersistentContext(dataDir, {\n headless,\n args: [...STEALTH_ARGS],\n userAgent: REALISTIC_USER_AGENT,\n viewport: randomViewport(),\n locale: \"en-US\",\n timezoneId: \"America/New_York\",\n });\n\n await applyStealthToContext(browserContext);\n\n browserContext.on(\"close\", () => {\n log(\"Browser context closed\");\n browserContext = null;\n activePage = null;\n });\n\n log(\"Browser context launched\");\n return browserContext;\n } catch (error) {\n browserContext = null;\n const message = error instanceof Error ? error.message : String(error);\n\n if (message.includes(\"lock\") || message.includes(\"already\")) {\n throw new ContextInUseError();\n }\n\n throw new BrowserLaunchError(`Failed to launch browser: ${message}`, {\n cause: error,\n });\n }\n}\n\nexport async function getPage(options?: { headless?: boolean }): Promise<Page> {\n if (activePage && !activePage.isClosed()) {\n return activePage;\n }\n\n const context = await getBrowserContext(options);\n const pages = context.pages();\n activePage = pages.length > 0 ? pages[0] : await context.newPage();\n return activePage;\n}\n\nexport async function closeBrowser(): Promise<void> {\n if (browserContext) {\n log(\"Closing browser context...\");\n try {\n await browserContext.close();\n } catch {\n log(\"Browser context already closed\");\n }\n browserContext = null;\n activePage = null;\n log(\"Browser closed\");\n }\n}\n\nexport { getDataDir };\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdirSync, accessSync, constants } from \"node:fs\";\n\nconst APP_NAME = \"amazon-shopping-mcp\";\n\nexport function getDataDir(): string {\n const envOverride = process.env.AMAZON_MCP_DATA_DIR;\n if (envOverride) {\n return join(envOverride, APP_NAME);\n }\n\n const os = platform();\n const home = homedir();\n\n if (os === \"darwin\") {\n return join(home, \"Library\", \"Application Support\", APP_NAME);\n }\n\n if (os === \"linux\") {\n const xdgDataHome = process.env.XDG_DATA_HOME;\n if (xdgDataHome) {\n return join(xdgDataHome, APP_NAME);\n }\n return join(home, \".local\", \"share\", APP_NAME);\n }\n\n throw new Error(`Unsupported platform: ${os}. Only macOS and Linux are supported.`);\n}\n\nexport function ensureDataDir(): string {\n const dir = getDataDir();\n mkdirSync(dir, { recursive: true });\n validateDirWritable(dir);\n return dir;\n}\n\nexport function getCacheDir(): string {\n return join(getDataDir(), \"cache\");\n}\n\nexport function ensureCacheDir(): string {\n const dir = getCacheDir();\n mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nfunction validateDirWritable(dir: string): void {\n try {\n accessSync(dir, constants.W_OK);\n } catch {\n throw new Error(`Data directory is not writable: ${dir}. Check file permissions.`);\n }\n}\n","import type { BrowserContext, Page } from \"playwright\";\n\n// --- Fingerprint Patches (applied once at context creation) ---\n\nexport const STEALTH_ARGS = [\n \"--disable-blink-features=AutomationControlled\",\n \"--disable-features=AutomationControlled\",\n \"--disable-dev-shm-usage\",\n \"--disable-infobars\",\n \"--disable-background-networking\",\n \"--disable-default-apps\",\n \"--disable-extensions\",\n \"--disable-sync\",\n \"--no-first-run\",\n \"--no-default-browser-check\",\n \"--disable-component-update\",\n \"--disable-hang-monitor\",\n];\n\nexport const REALISTIC_USER_AGENT =\n \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) \" +\n \"AppleWebKit/537.36 (KHTML, like Gecko) \" +\n \"Chrome/131.0.0.0 Safari/537.36\";\n\nconst VIEWPORT_PRESETS = [\n { width: 1920, height: 1080 },\n { width: 1536, height: 864 },\n { width: 1440, height: 900 },\n { width: 1366, height: 768 },\n { width: 1280, height: 800 },\n] as const;\n\nexport function randomViewport(): { width: number; height: number } {\n const preset = VIEWPORT_PRESETS[Math.floor(Math.random() * VIEWPORT_PRESETS.length)];\n return { width: preset.width, height: preset.height };\n}\n\nexport const STEALTH_INIT_SCRIPT = `\n // Hide navigator.webdriver\n Object.defineProperty(navigator, 'webdriver', {\n get: () => false,\n configurable: true,\n });\n\n // Mock window.chrome.runtime (missing in headless automation)\n if (!window.chrome) {\n window.chrome = {};\n }\n if (!window.chrome.runtime) {\n window.chrome.runtime = {\n connect: function() {},\n sendMessage: function() {},\n };\n }\n\n // Realistic navigator.plugins (Chrome PDF plugins)\n Object.defineProperty(navigator, 'plugins', {\n get: () => {\n const plugins = [\n { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format' },\n { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '' },\n { name: 'Native Client', filename: 'internal-nacl-plugin', description: '' },\n ];\n plugins.length = 3;\n return plugins;\n },\n configurable: true,\n });\n\n // Set realistic languages\n Object.defineProperty(navigator, 'languages', {\n get: () => ['en-US', 'en'],\n configurable: true,\n });\n\n // Mask automation artifacts in permissions API\n const originalQuery = navigator.permissions.query.bind(navigator.permissions);\n navigator.permissions.query = async (params) => {\n if (params.name === 'notifications') {\n return { state: 'prompt', onchange: null };\n }\n return originalQuery(params);\n };\n`;\n\nexport async function applyStealthToContext(context: BrowserContext): Promise<void> {\n await context.addInitScript(STEALTH_INIT_SCRIPT);\n}\n\n// --- Human Simulation (called around each navigation) ---\n\nexport function randomDelay(min: number, max: number): Promise<void> {\n const ms = Math.floor(Math.random() * (max - min + 1)) + min;\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function simulateMouseMovement(page: Page): Promise<void> {\n const viewport = page.viewportSize();\n if (!viewport) return;\n\n const steps = 8 + Math.floor(Math.random() * 8); // 8-15 steps\n let x = Math.random() * viewport.width * 0.8;\n let y = Math.random() * viewport.height * 0.8;\n\n for (let i = 0; i < steps; i++) {\n // Bezier-ish curve: small random offsets to simulate natural hand movement\n x += (Math.random() - 0.5) * 120;\n y += (Math.random() - 0.5) * 80;\n\n // Clamp to viewport\n x = Math.max(10, Math.min(viewport.width - 10, x));\n y = Math.max(10, Math.min(viewport.height - 10, y));\n\n await page.mouse.move(x, y, { steps: 3 });\n\n // Micro-pause between movements (10-50ms)\n await randomDelay(10, 50);\n }\n}\n\nexport async function simulateScroll(page: Page): Promise<void> {\n const scrollCount = 2 + Math.floor(Math.random() * 3); // 2-4 scrolls\n\n for (let i = 0; i < scrollCount; i++) {\n const deltaY = 100 + Math.floor(Math.random() * 200); // 100-300px\n await page.mouse.wheel(0, deltaY);\n await randomDelay(200, 600);\n }\n}\n\n// --- Rate Limiting ---\n\nlet lastNavigationTime = 0;\n\nexport async function throttleNavigation(): Promise<void> {\n const now = Date.now();\n const elapsed = now - lastNavigationTime;\n const minGap = 2000 + Math.floor(Math.random() * 3000); // 2-5s\n\n if (lastNavigationTime > 0 && elapsed < minGap) {\n await new Promise((resolve) => setTimeout(resolve, minGap - elapsed));\n }\n\n lastNavigationTime = Date.now();\n}\n\nexport function resetThrottleState(): void {\n lastNavigationTime = 0;\n}\n","export enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n}\n\nconst LOG_LEVEL_NAMES: Record<LogLevel, string> = {\n [LogLevel.DEBUG]: \"DEBUG\",\n [LogLevel.INFO]: \"INFO\",\n [LogLevel.WARN]: \"WARN\",\n [LogLevel.ERROR]: \"ERROR\",\n};\n\n// Global log level - can be changed at runtime\nlet globalLogLevel: LogLevel = LogLevel.INFO;\n\n// Initialize from environment\nif (process.env.AMAZON_MCP_DEBUG === \"true\" || process.env.AMAZON_MCP_DEBUG === \"1\") {\n globalLogLevel = LogLevel.DEBUG;\n}\n\nexport interface Logger {\n debug(message: string, data?: Record<string, unknown>): void;\n info(message: string, data?: Record<string, unknown>): void;\n warn(message: string, data?: Record<string, unknown>): void;\n error(message: string, data?: Record<string, unknown>): void;\n}\n\n/**\n * Set the global log level.\n */\nexport function setGlobalLogLevel(level: LogLevel): void {\n globalLogLevel = level;\n}\n\n/**\n * Get the current global log level.\n */\nexport function getGlobalLogLevel(): LogLevel {\n return globalLogLevel;\n}\n\n/**\n * Check if debug logging is enabled.\n */\nexport function isDebugEnabled(): boolean {\n return globalLogLevel <= LogLevel.DEBUG;\n}\n\n/**\n * Format a log message with timestamp, level, module, and optional data.\n */\nfunction formatLogMessage(\n level: LogLevel,\n module: string,\n message: string,\n data?: Record<string, unknown>,\n): string {\n const timestamp = new Date().toISOString();\n const levelName = LOG_LEVEL_NAMES[level];\n\n let logLine = `${timestamp} [${levelName}] [${module}] ${message}`;\n\n if (data && Object.keys(data).length > 0) {\n logLine += ` ${JSON.stringify(data)}`;\n }\n\n return logLine;\n}\n\n/**\n * Log a message at a specific level.\n */\nfunction log(\n level: LogLevel,\n module: string,\n message: string,\n data?: Record<string, unknown>,\n): void {\n if (level < globalLogLevel) {\n return;\n }\n\n const formattedMessage = formatLogMessage(level, module, message, data);\n\n // Always output to stderr (stdout reserved for MCP transport)\n console.error(formattedMessage);\n}\n\n/**\n * Create a logger instance for a specific module.\n *\n * @param module - The module name to include in log messages\n * @returns A Logger instance with debug, info, warn, and error methods\n */\nexport function createLogger(module: string): Logger {\n return {\n debug(message: string, data?: Record<string, unknown>): void {\n log(LogLevel.DEBUG, module, message, data);\n },\n info(message: string, data?: Record<string, unknown>): void {\n log(LogLevel.INFO, module, message, data);\n },\n warn(message: string, data?: Record<string, unknown>): void {\n log(LogLevel.WARN, module, message, data);\n },\n error(message: string, data?: Record<string, unknown>): void {\n log(LogLevel.ERROR, module, message, data);\n },\n };\n}\n","import type { Page } from \"playwright\";\nimport { closeBrowser, getBrowserContext, getPage, AMAZON_BASE_URL } from \"./browser.js\";\nimport { SessionExpiredError } from \"../../errors.js\";\nimport { createLogger } from \"../../utils/logger.js\";\n\nexport interface LoginResult {\n readonly success: boolean;\n readonly message: string;\n}\n\nexport interface SessionStatus {\n readonly loggedIn: boolean;\n readonly message: string;\n}\n\nconst LOGIN_URL = `${AMAZON_BASE_URL}/ap/signin`;\nconst ACCOUNT_URL = `${AMAZON_BASE_URL}/gp/css/homepage.html`;\nconst LOGIN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes for 2FA\nconst LOGIN_POLL_INTERVAL_MS = 1000;\n\nconst logger = createLogger(\"auth\");\n\nfunction log(message: string): void {\n logger.info(message);\n}\n\nexport function isLoginPage(page: Page): boolean {\n const url = page.url();\n return (\n url.includes(\"/ap/signin\") || url.includes(\"/ap/mfa\") || url.includes(\"/ap/forgotpassword\")\n );\n}\n\nexport async function assertSessionValid(page: Page): Promise<void> {\n if (isLoginPage(page)) {\n throw new SessionExpiredError();\n }\n}\n\nexport async function login(force?: boolean): Promise<LoginResult> {\n if (!force) {\n const status = await checkSession();\n if (status.loggedIn) {\n return {\n success: true,\n message: \"Already logged in. Use force: true to re-login.\",\n };\n }\n }\n\n log(\"Opening headed browser for Amazon login...\");\n\n // Close any existing headless context so we can re-launch in headed mode\n await closeBrowser();\n\n // Always use headed mode for login — user needs to see the browser\n const context = await getBrowserContext({ headless: false });\n const pages = context.pages();\n const page = pages.length > 0 ? pages[0] : await context.newPage();\n\n try {\n await page.goto(LOGIN_URL, { waitUntil: \"domcontentloaded\" });\n log(\"Navigated to Amazon sign-in page. Waiting for user to complete login...\");\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < LOGIN_TIMEOUT_MS) {\n await new Promise((resolve) => setTimeout(resolve, LOGIN_POLL_INTERVAL_MS));\n\n if (page.isClosed()) {\n return {\n success: false,\n message: \"Browser was closed before login was completed.\",\n };\n }\n\n if (!isLoginPage(page)) {\n log(\"Login detected — user navigated away from sign-in page\");\n return {\n success: true,\n message: \"Successfully logged in to Amazon.\",\n };\n }\n }\n\n return {\n success: false,\n message: \"Login timed out after 5 minutes. Please try again.\",\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n log(`Login error: ${message}`);\n return {\n success: false,\n message: `Login failed: ${message}`,\n };\n }\n}\n\nexport async function checkSession(): Promise<SessionStatus> {\n try {\n const page = await getPage();\n await page.goto(ACCOUNT_URL, { waitUntil: \"domcontentloaded\", timeout: 15_000 });\n\n if (isLoginPage(page)) {\n return {\n loggedIn: false,\n message: \"Not logged in. Please call amazon-login to authenticate.\",\n };\n }\n\n return {\n loggedIn: true,\n message: \"Logged in to Amazon.\",\n };\n } catch {\n return {\n loggedIn: false,\n message: \"Unable to verify session. Please call amazon-login to authenticate.\",\n };\n }\n}\n","import * as cheerio from \"cheerio\";\nimport type {\n Cart,\n CartItem,\n Order,\n OrderItem,\n Product,\n ProductDetails,\n PurchaseResult,\n Review,\n ReviewSummary,\n} from \"../types.js\";\nimport {\n CartItemSchema,\n CartSchema,\n OrderItemSchema,\n OrderSchema,\n ProductSchema,\n ProductDetailsSchema,\n PurchaseResultSchema,\n ReviewSchema,\n} from \"../types.js\";\nimport { createLogger } from \"../../utils/logger.js\";\n\nconst logger = createLogger(\"scraper\");\n\nfunction log(message: string): void {\n logger.info(message);\n}\n\nfunction parsePrice(priceText: string): number | null {\n const cleaned = priceText.replace(/[^0-9.]/g, \"\");\n const value = parseFloat(cleaned);\n return Number.isNaN(value) ? null : value;\n}\n\nfunction parseRating(ratingText: string): number | null {\n const match = ratingText.match(/([\\d.]+)\\s*out of\\s*5/);\n if (!match) return null;\n const value = parseFloat(match[1]);\n return Number.isNaN(value) ? null : value;\n}\n\nfunction parseReviewCount(countText: string): number {\n const cleaned = countText.replace(/[^0-9]/g, \"\");\n const value = parseInt(cleaned, 10);\n return Number.isNaN(value) ? 0 : value;\n}\n\nexport function parseSearchResults(html: string): Product[] {\n const $ = cheerio.load(html);\n const products: Product[] = [];\n\n // Amazon search results use data-component-type=\"s-search-result\" on each product card\n const resultCards = $('[data-component-type=\"s-search-result\"]');\n\n if (resultCards.length === 0) {\n log(\"No search result cards found in HTML\");\n return [];\n }\n\n resultCards.each((_index, element) => {\n try {\n const card = $(element);\n const asin = card.attr(\"data-asin\");\n\n if (!asin || asin.trim() === \"\") return;\n\n // Title: try h2>a>span (fixture) then h2 span (live Amazon)\n const title = card.find(\"h2 a span\").text().trim() || card.find(\"h2 span\").text().trim();\n if (!title) return;\n\n // URL: try h2>a (fixture) then title-recipe a or h2's parent a (live Amazon)\n const href =\n card.find(\"h2 a\").attr(\"href\") ??\n card.find('[data-cy=\"title-recipe\"] a').attr(\"href\") ??\n card.find(\"h2\").closest(\"a\").attr(\"href\") ??\n \"\";\n const url = href.startsWith(\"http\") ? href : `https://www.amazon.com${href}`;\n\n // Price: .a-price .a-offscreen (the first one is the current price)\n const priceText = card.find(\".a-price .a-offscreen\").first().text().trim();\n const price = priceText ? parsePrice(priceText) : null;\n\n // Currency: always USD for amazon.com\n const currency = \"USD\";\n\n // Rating: try star-small (fixture) then star-mini (live Amazon)\n const ratingText =\n card.find(\"i.a-icon-star-small span.a-icon-alt\").first().text().trim() ||\n card.find(\"i.a-icon-star-mini span\").first().text().trim() ||\n card.find('[data-cy=\"reviews-ratings-slot\"]').text().trim();\n const rating = ratingText ? parseRating(ratingText) : null;\n\n // Review count: try dedicated element (fixture) then reviews-block spans (live Amazon)\n let reviewCountText =\n card.find('[data-cy=\"reviews-ratings-count\"]').text().trim() ||\n card.find(\"a.s-underline-link-text span.s-underline-text\").text().trim();\n if (!reviewCountText) {\n // Live Amazon wraps count in parentheses like \"(65.4K)\"\n card.find('[data-cy=\"reviews-block\"] span').each((_i, el) => {\n const t = $(el).text().trim();\n if (t.match(/^\\([\\d.,]+[KkMm]?\\)$/)) {\n reviewCountText = t;\n return false; // break\n }\n });\n }\n const reviewCount = reviewCountText ? parseReviewCount(reviewCountText) : 0;\n\n // Brand: span.a-size-base-plus or from \"by Brand\" text\n const brandText =\n card.find(\".a-row .a-size-base-plus\").first().text().trim() ||\n card.find(\".a-row .a-size-base.s-underline-text\").first().text().trim();\n const brand = brandText || null;\n\n // Prime: check for icon (fixture) or FREE delivery text (live Amazon)\n const isPrime =\n card.find(\"i.a-icon-prime\").length > 0 ||\n card.find('[data-cy=\"delivery-recipe\"]').text().includes(\"FREE delivery\");\n\n // Image: img.s-image\n const imageUrl = card.find(\"img.s-image\").attr(\"src\") ?? null;\n\n const rawProduct = {\n asin,\n title,\n price,\n currency,\n rating,\n reviewCount,\n brand,\n isPrime,\n imageUrl,\n url,\n };\n\n const parsed = ProductSchema.safeParse(rawProduct);\n\n if (parsed.success) {\n products.push(parsed.data as Product);\n } else {\n log(`Skipping product ${asin}: validation failed — ${parsed.error.message}`);\n }\n } catch {\n // Skip individual products that fail to parse\n }\n });\n\n log(`Parsed ${products.length} products from ${resultCards.length} cards`);\n return products;\n}\n\nfunction extractBrand($: cheerio.CheerioAPI): string | null {\n const bylineText = $(\"#bylineInfo\").text().trim();\n if (bylineText) {\n // \"Visit the Sony Store\" → \"Sony\"\n const visitMatch = bylineText.match(/Visit the (.+?) Store/);\n if (visitMatch) return visitMatch[1];\n // \"Brand: Sony\" → \"Sony\"\n const brandMatch = bylineText.match(/Brand:\\s*(.+)/);\n if (brandMatch) return brandMatch[1].trim();\n return bylineText;\n }\n const brandLink = $(\"a#brand\").text().trim();\n return brandLink || null;\n}\n\nexport function parseProductDetails(html: string): ProductDetails | null {\n const $ = cheerio.load(html);\n\n // ASIN: from hidden input or canonical URL\n const asin =\n $('input[name=\"ASIN\"]').val()?.toString() ??\n $('link[rel=\"canonical\"]')\n .attr(\"href\")\n ?.match(/\\/dp\\/([A-Z0-9]+)/)?.[1] ??\n \"\";\n\n if (!asin) {\n log(\"No ASIN found in product page HTML\");\n return null;\n }\n\n // Title\n const title = $(\"#productTitle\").text().trim();\n if (!title) {\n log(\"No product title found in HTML\");\n return null;\n }\n\n // Price\n const priceText = $(\".a-price .a-offscreen\").first().text().trim();\n const price = priceText ? parsePrice(priceText) : null;\n const currency = \"USD\";\n\n // Rating\n const ratingText = $(\"#acrPopover span.a-icon-alt\").first().text().trim();\n const rating = ratingText ? parseRating(ratingText) : null;\n\n // Review count\n const reviewCountText = $(\"#acrCustomerReviewText\").text().trim();\n const reviewCount = reviewCountText ? parseReviewCount(reviewCountText) : 0;\n\n // Brand\n const brand = extractBrand($);\n\n // Prime: check for icon (fixture) or FREE delivery text (live Amazon)\n const isPrime =\n $(\"i.a-icon-prime\").length > 0 ||\n $(\"#mir-layout-DELIVERY_BLOCK, #deliveryBlockMessage\").text().includes(\"FREE delivery\");\n\n // Description\n const description = $(\"#productDescription p\").text().trim() || \"\";\n\n // Features\n const features: string[] = [];\n $(\"#feature-bullets ul li span.a-list-item\").each((_i, el) => {\n const text = $(el).text().trim();\n if (text) features.push(text);\n });\n\n // Images: primary + alt images\n const imageUrls: string[] = [];\n const primaryImage = $(\"#landingImage\").attr(\"src\") ?? $(\"#imgTagWrapperId img\").attr(\"src\");\n if (primaryImage) imageUrls.push(primaryImage);\n\n $(\"#altImages ul li img\").each((_i, el) => {\n const src = $(el).attr(\"src\");\n // Skip tiny thumbnails and non-product images (360-view icons, video thumbnails)\n if (src && !imageUrls.includes(src) && src.includes(\"/images/I/\")) {\n imageUrls.push(src);\n }\n });\n\n // Availability\n const availability = $(\"#availability span\").first().text().trim() || \"Unknown\";\n\n // URL\n const url = $('link[rel=\"canonical\"]').attr(\"href\") ?? `https://www.amazon.com/dp/${asin}`;\n\n const raw = {\n asin,\n title,\n price,\n currency,\n rating,\n reviewCount,\n brand,\n isPrime,\n description,\n features,\n imageUrls,\n availability,\n url,\n };\n\n const parsed = ProductDetailsSchema.safeParse(raw);\n if (!parsed.success) {\n log(`Product details validation failed: ${parsed.error.message}`);\n return null;\n }\n\n log(`Parsed product details for ${asin}`);\n return parsed.data as ProductDetails;\n}\n\nexport function parseReviews(html: string): { reviews: Review[]; summary: ReviewSummary } {\n const $ = cheerio.load(html);\n\n // Parse summary\n const ratingOutOfText = $('span[data-hook=\"rating-out-of-text\"]').text().trim();\n const averageRating = ratingOutOfText ? (parseRating(ratingOutOfText) ?? 0) : 0;\n\n const totalCountText = $('div[data-hook=\"total-review-count\"] span').text().trim();\n const totalCount = totalCountText ? parseReviewCount(totalCountText) : 0;\n\n // Parse star distribution from histogram\n const starDistribution: Record<1 | 2 | 3 | 4 | 5, number> = {\n 1: 0,\n 2: 0,\n 3: 0,\n 4: 0,\n 5: 0,\n };\n\n // Try new format first: aria-label=\"5 stars represent 94% of rating\"\n $(\"#histogramTable a[aria-label]\").each((_i, el) => {\n const label = $(el).attr(\"aria-label\") ?? \"\";\n const match = label.match(/(\\d)\\s*stars?\\s*represent\\s*(\\d+)%/);\n if (match) {\n const star = parseInt(match[1], 10) as 1 | 2 | 3 | 4 | 5;\n if (star >= 1 && star <= 5) {\n starDistribution[star] = parseInt(match[2], 10);\n }\n }\n });\n\n // Fallback to old format for test fixtures: tbody tr with td elements\n if (starDistribution[1] === 0 && starDistribution[5] === 0) {\n $(\"#histogramTable tbody tr\").each((_i, el) => {\n const row = $(el);\n const starText = row.find(\"td.a-text-right a\").text().trim();\n const percentText = row.find(\"td.a-text-right span.a-size-base\").text().trim();\n const starMatch = starText.match(/(\\d)\\s*star/);\n const percentMatch = percentText.match(/(\\d+)%/);\n if (starMatch && percentMatch) {\n const star = parseInt(starMatch[1], 10) as 1 | 2 | 3 | 4 | 5;\n if (star >= 1 && star <= 5) {\n starDistribution[star] = parseInt(percentMatch[1], 10);\n }\n }\n });\n }\n\n const summary: ReviewSummary = { averageRating, totalCount, starDistribution };\n\n // Parse individual reviews\n // Note: Amazon sometimes uses <li> instead of <div> for review containers\n const reviews: Review[] = [];\n $('[data-hook=\"review\"]').each((_i, el) => {\n try {\n const reviewEl = $(el);\n\n const id = reviewEl.attr(\"id\") ?? \"\";\n if (!id) return;\n\n const author = reviewEl.find(\"span.a-profile-name\").first().text().trim();\n const ratingAlt = reviewEl\n .find('i[data-hook=\"review-star-rating\"] span.a-icon-alt')\n .text()\n .trim();\n const rating = ratingAlt ? (parseRating(ratingAlt) ?? 0) : 0;\n // Live Amazon nests rating icon inside title anchor; get only the direct child span\n // that's not the letter spacer (which has class a-letter-space)\n const titleAnchor = reviewEl.find('a[data-hook=\"review-title\"]');\n let title = titleAnchor.find(\"> span:not(.a-letter-space)\").text().trim();\n // Fallback for test fixtures and older layouts where span is the only child\n if (!title) {\n title = titleAnchor.find(\"span\").first().text().trim();\n }\n const body = reviewEl.find('span[data-hook=\"review-body\"] span').text().trim();\n const date = reviewEl.find('span[data-hook=\"review-date\"]').text().trim();\n const verified = reviewEl.find('span[data-hook=\"avp-badge\"]').length > 0;\n\n const raw = { id, author, rating, title, body, date, verified };\n const parsed = ReviewSchema.safeParse(raw);\n\n if (parsed.success) {\n reviews.push(parsed.data as Review);\n } else {\n log(`Skipping review ${id}: validation failed — ${parsed.error.message}`);\n }\n } catch {\n // Skip individual reviews that fail to parse\n }\n });\n\n log(`Parsed ${reviews.length} reviews, summary: ${averageRating}/5 (${totalCount} total)`);\n return { reviews, summary };\n}\n\nexport function parseCart(html: string): Cart {\n const $ = cheerio.load(html);\n const items: CartItem[] = [];\n\n // Find all cart items with data-asin attribute\n $(\".sc-list-item[data-asin]\").each((_index, element) => {\n try {\n const item = $(element);\n const asin = item.attr(\"data-asin\");\n\n if (!asin || asin.trim() === \"\") return;\n\n // Title: .sc-product-title or fallback to product link text\n const title =\n item.find(\".sc-product-title\").text().trim() || item.find(\".sc-product-link\").text().trim();\n\n if (!title) {\n log(`Skipping cart item ${asin}: no title found`);\n return;\n }\n\n // Price: .sc-product-price .a-offscreen\n const priceText = item.find(\".sc-product-price .a-offscreen\").first().text().trim();\n const price = priceText ? parsePrice(priceText) : null;\n\n // Quantity: selected option in quantity dropdown or input value\n let quantity = 1;\n const selectedOption = item.find('select[name=\"quantity\"] option[selected]');\n if (selectedOption.length > 0) {\n quantity = parseInt(selectedOption.attr(\"value\") ?? selectedOption.text().trim(), 10);\n } else {\n // Fallback to input field for larger quantities\n const quantityInput = item.find('input[name=\"quantity\"]');\n if (quantityInput.length > 0) {\n quantity = parseInt(quantityInput.attr(\"value\") ?? \"1\", 10);\n }\n }\n if (Number.isNaN(quantity) || quantity < 1) quantity = 1;\n\n const rawItem = { asin, title, price, quantity };\n const parsed = CartItemSchema.safeParse(rawItem);\n\n if (parsed.success) {\n items.push(parsed.data as CartItem);\n } else {\n log(`Skipping cart item ${asin}: validation failed — ${parsed.error.message}`);\n }\n } catch {\n // Skip individual items that fail to parse\n }\n });\n\n // Subtotal: #sc-subtotal-amount-activecart\n const subtotalText = $(\"#sc-subtotal-amount-activecart\").text().trim();\n const subtotal = subtotalText ? parsePrice(subtotalText) : null;\n\n // Currency: always USD for amazon.com\n const currency = \"USD\";\n\n const rawCart = { items, subtotal, currency };\n const parsed = CartSchema.safeParse(rawCart);\n\n if (!parsed.success) {\n log(`Cart validation failed: ${parsed.error.message}`);\n return { items: [], subtotal: null, currency: \"USD\" };\n }\n\n log(`Parsed ${items.length} cart items, subtotal: ${subtotal ?? \"N/A\"}`);\n return parsed.data as Cart;\n}\n\nfunction parseOrderDate(dateText: string): string {\n // Convert \"January 15, 2026\" to \"2026-01-15\" (ISO 8601)\n const months: Record<string, string> = {\n January: \"01\",\n February: \"02\",\n March: \"03\",\n April: \"04\",\n May: \"05\",\n June: \"06\",\n July: \"07\",\n August: \"08\",\n September: \"09\",\n October: \"10\",\n November: \"11\",\n December: \"12\",\n };\n\n const match = dateText.match(/(\\w+)\\s+(\\d+),?\\s+(\\d{4})/);\n if (match) {\n const month = months[match[1]] ?? \"01\";\n const day = match[2].padStart(2, \"0\");\n const year = match[3];\n return `${year}-${month}-${day}`;\n }\n return dateText; // Return as-is if parsing fails\n}\n\nexport function parseOrderHistory(html: string): Order[] {\n const $ = cheerio.load(html);\n const orders: Order[] = [];\n\n // Find all order containers - Amazon uses .order-card.js-order-card\n $(\".order-card.js-order-card\").each((_index, element) => {\n try {\n const orderEl = $(element);\n\n // Order ID: inside .yohtmlc-order-id span[dir=\"ltr\"]\n const orderId = orderEl.find('.yohtmlc-order-id span[dir=\"ltr\"]').text().trim();\n if (!orderId || orderId.trim() === \"\") return;\n\n // Date: first .a-size-base.a-color-secondary.aok-break-word in header\n const dateText = orderEl\n .find(\".order-header .a-size-base.a-color-secondary.aok-break-word\")\n .first()\n .text()\n .trim();\n const date = parseOrderDate(dateText);\n\n // Total: look for \"Order Total\" label, then get the value\n // Total: Find \"Total\" label, then get price from next row\n // Structure: <span>Total</span> in one div, then <span>$XX.XX</span> in sibling div\n let total = 0;\n orderEl.find(\".order-header__header-list-item\").each((_i, item) => {\n const $item = $(item);\n const text = $item.text();\n if (text.includes(\"Total\")) {\n const priceMatch = text.match(/\\$[\\d,]+\\.?\\d*/);\n if (priceMatch) {\n total = parsePrice(priceMatch[0]) ?? 0;\n }\n }\n });\n\n // Currency: always USD for amazon.com\n const currency = \"USD\";\n\n // Status: .delivery-box__primary-text (e.g., \"Delivered January 19\")\n const status = orderEl.find(\".delivery-box__primary-text\").first().text().trim() || \"Unknown\";\n\n // In order history list view, items are not fully detailed\n // We just get basic info from product links, deduped by ASIN\n const items: OrderItem[] = [];\n const seenAsins = new Set<string>();\n const itemLinks = orderEl.find('a[href*=\"/gp/product/\"], a[href*=\"/dp/\"]');\n\n itemLinks.each((_i, link) => {\n try {\n const $link = $(link);\n const href = $link.attr(\"href\") || \"\";\n\n // Extract ASIN from URL\n const asinMatch = href.match(/\\/(?:dp|gp\\/product)\\/([A-Z0-9]{10})/);\n if (!asinMatch) return;\n const asin = asinMatch[1];\n\n // Skip if we've already seen this ASIN\n if (seenAsins.has(asin)) return;\n seenAsins.add(asin);\n\n // Title is usually in the link text or nearby\n let title = $link.text().trim();\n if (!title || title.length < 3) {\n title = $link.find(\"img\").attr(\"alt\") || \"\";\n }\n if (!title || title.length < 3) return;\n\n // Price not typically shown in list view\n const price = null;\n const quantity = 1;\n\n const rawItem = { asin, title, price, quantity };\n const parsed = OrderItemSchema.safeParse(rawItem);\n\n if (parsed.success) {\n items.push(parsed.data as OrderItem);\n }\n } catch {\n // Skip individual items that fail to parse\n }\n });\n\n // Item count is the number of unique items\n const itemCount = items.length || undefined;\n\n const rawOrder = {\n orderId,\n date,\n total,\n currency,\n status,\n itemCount,\n items,\n };\n\n const parsed = OrderSchema.safeParse(rawOrder);\n\n if (parsed.success) {\n orders.push(parsed.data as Order);\n } else {\n log(`Skipping order ${orderId}: validation failed — ${parsed.error.message}`);\n }\n } catch {\n // Skip individual orders that fail to parse\n }\n });\n\n log(`Parsed ${orders.length} orders from order history`);\n return orders;\n}\n\nexport function parseOrderDetails(html: string): Order | null {\n const $ = cheerio.load(html);\n\n // Order ID: Find span containing order ID pattern (XXX-XXXXXXX-XXXXXXX)\n let orderId = \"\";\n $(\"span\").each((_i, el) => {\n const text = $(el).text().trim();\n if (/^\\d{3}-\\d{7}-\\d{7}$/.test(text)) {\n orderId = text;\n return false; // break\n }\n });\n\n if (!orderId) {\n log(\"No order ID found in order details HTML\");\n return null;\n }\n\n // Date: Find \"Order placed\" label, then get the next span with date\n let date = \"\";\n $(\"span\").each((_i, el) => {\n const text = $(el).text().trim();\n if (text === \"Order placed\") {\n // Look for date in sibling/nearby spans\n const parent = $(el).parent();\n const dateSpan = parent\n .find(\"span\")\n .filter((_j, s) => {\n const t = $(s).text().trim();\n return /\\w+\\s+\\d+,\\s+\\d{4}/.test(t);\n })\n .first();\n if (dateSpan.length) {\n date = parseOrderDate(dateSpan.text().trim());\n return false;\n }\n }\n });\n\n // Fallback: look for date pattern anywhere\n if (!date) {\n const bodyText = $(\"body\").text();\n const dateMatch = bodyText.match(\n /(January|February|March|April|May|June|July|August|September|October|November|December)\\s+\\d{1,2},\\s+\\d{4}/,\n );\n if (dateMatch) {\n date = parseOrderDate(dateMatch[0]);\n }\n }\n\n // Total: Find the grand total (usually last large dollar amount)\n let total = 0;\n const allText = $(\"body\").text();\n const grandTotalMatch = allText.match(/Grand Total[:\\s]*\\$?([\\d,]+\\.?\\d*)/i);\n if (grandTotalMatch) {\n total = parsePrice(`$${grandTotalMatch[1]}`) ?? 0;\n } else {\n // Fallback: find Order Total pattern\n const orderTotalMatch = allText.match(/Order Total[:\\s]*\\$?([\\d,]+\\.?\\d*)/i);\n if (orderTotalMatch) {\n total = parsePrice(`$${orderTotalMatch[1]}`) ?? 0;\n }\n }\n\n // Currency: always USD for amazon.com\n const currency = \"USD\";\n\n // Status: Look for \"Delivered\" or shipment status\n let status = \"Unknown\";\n const deliveredEl = $(\".a-text-bold\")\n .filter((_i, el) => {\n return $(el).text().trim().toLowerCase().includes(\"delivered\");\n })\n .first();\n if (deliveredEl.length) {\n const nextSpan = deliveredEl.next(\"span\");\n status = `Delivered ${nextSpan.text().trim()}`.trim();\n }\n\n // Parse items: Find all product links with /dp/ASIN pattern\n const items: OrderItem[] = [];\n const seenAsins = new Set<string>();\n\n $('a[href*=\"/dp/\"]').each((_index, element) => {\n try {\n const link = $(element);\n const href = link.attr(\"href\") || \"\";\n const asinMatch = href.match(/\\/dp\\/([A-Z0-9]{10})/);\n if (!asinMatch) return;\n\n const asin = asinMatch[1];\n if (seenAsins.has(asin)) return; // Skip duplicates\n seenAsins.add(asin);\n\n // Title from link text or img alt\n let title = link.text().trim();\n if (!title || title.length < 3) {\n title = link.find(\"img\").attr(\"alt\") || \"\";\n }\n if (!title || title.length < 3) return;\n\n // Price: Look for .a-offscreen price near this item\n // Find the parent container and look for price\n let price: number | null = null;\n const container = link.closest(\".a-row, .a-section, div\").parent();\n const priceEl = container.find(\".a-offscreen\").first();\n if (priceEl.length) {\n const priceText = priceEl.text().trim();\n if (priceText.startsWith(\"$\")) {\n price = parsePrice(priceText);\n }\n }\n\n const quantity = 1; // Details page shows individual items\n\n const rawItem = { asin, title, price, quantity };\n const parsed = OrderItemSchema.safeParse(rawItem);\n\n if (parsed.success) {\n items.push(parsed.data as OrderItem);\n } else {\n log(`Skipping order item ${asin}: validation failed — ${parsed.error.message}`);\n }\n } catch {\n // Skip individual items that fail to parse\n }\n });\n\n const itemCount = items.length;\n\n const rawOrder = {\n orderId,\n date,\n total,\n currency,\n status,\n itemCount,\n items,\n };\n\n const parsed = OrderSchema.safeParse(rawOrder);\n\n if (!parsed.success) {\n log(`Order details validation failed: ${parsed.error.message}`);\n return null;\n }\n\n log(`Parsed order details for ${orderId} with ${items.length} items`);\n return parsed.data as Order;\n}\n\nexport interface CheckoutSummary {\n readonly items: ReadonlyArray<{\n readonly asin: string;\n readonly title: string;\n readonly price: string;\n readonly quantity: number;\n }>;\n readonly subtotal: string;\n readonly shipping: string;\n readonly tax: string;\n readonly total: string;\n}\n\nexport interface CheckoutError {\n readonly type: \"payment_declined\" | \"out_of_stock\" | \"address_invalid\" | \"unknown\";\n readonly message: string;\n readonly affectedItems?: readonly string[];\n}\n\nexport function parseCartForCheckout(html: string): { isEmpty: boolean; itemCount: number } {\n const $ = cheerio.load(html);\n\n // Check for empty cart message\n const emptyCartText = $(\"h1, h2, .a-section\").text().toLowerCase();\n if (\n emptyCartText.includes(\"your cart is empty\") ||\n emptyCartText.includes(\"your amazon cart is empty\") ||\n emptyCartText.includes(\"your shopping cart is empty\")\n ) {\n log(\"Cart is empty\");\n return { isEmpty: true, itemCount: 0 };\n }\n\n // Count items with data-asin attribute\n const itemCount = $(\".sc-list-item[data-asin]\").length;\n log(`Cart has ${itemCount} items`);\n return { isEmpty: itemCount === 0, itemCount };\n}\n\nexport function parseCheckoutPage(html: string): {\n summary: CheckoutSummary | null;\n error: CheckoutError | null;\n hasPlaceOrderButton: boolean;\n} {\n const $ = cheerio.load(html);\n\n // Check for error states\n const errorAlert = $(\".a-alert-error, .a-box.a-alert-error\").text().toLowerCase();\n const warningAlert = $(\".a-alert-warning, .a-box.a-alert-warning\").text().toLowerCase();\n const pageText = $(\"body\").text().toLowerCase();\n\n // Payment declined\n if (\n errorAlert.includes(\"payment\") ||\n errorAlert.includes(\"declined\") ||\n pageText.includes(\"payment method was declined\") ||\n pageText.includes(\"payment was declined\")\n ) {\n log(\"Checkout error: payment declined\");\n return {\n summary: null,\n error: {\n type: \"payment_declined\",\n message:\n \"Your payment method was declined. Please update your payment method or use a different one.\",\n },\n hasPlaceOrderButton: false,\n };\n }\n\n // Out of stock\n if (\n warningAlert.includes(\"out of stock\") ||\n warningAlert.includes(\"no longer available\") ||\n pageText.includes(\"no longer available\") ||\n pageText.includes(\"currently unavailable\")\n ) {\n // Try to find affected items\n const affectedItems: string[] = [];\n $(\".unavailable-item, [data-asin]\")\n .filter((_i, el) => {\n const text = $(el).text().toLowerCase();\n return text.includes(\"unavailable\") || text.includes(\"out of stock\");\n })\n .each((_i, el) => {\n const title = $(el).find(\".item-title, .item-name\").text().trim();\n if (title) affectedItems.push(title);\n });\n\n log(`Checkout error: out of stock (${affectedItems.length} items)`);\n return {\n summary: null,\n error: {\n type: \"out_of_stock\",\n message: \"Some items in your cart are no longer available.\",\n affectedItems: affectedItems.length > 0 ? affectedItems : undefined,\n },\n hasPlaceOrderButton: false,\n };\n }\n\n // Address invalid\n if (\n errorAlert.includes(\"address\") ||\n pageText.includes(\"address is not valid\") ||\n pageText.includes(\"unable to ship\")\n ) {\n log(\"Checkout error: address invalid\");\n return {\n summary: null,\n error: {\n type: \"address_invalid\",\n message: \"The shipping address is not valid or we cannot ship to this location.\",\n },\n hasPlaceOrderButton: false,\n };\n }\n\n // Parse order summary\n const items: CheckoutSummary[\"items\"][number][] = [];\n $(\".checkout-item, .order-summary-content .checkout-item, [data-asin]\").each((_i, el) => {\n const $item = $(el);\n const asin = $item.attr(\"data-asin\") ?? \"\";\n if (!asin) return;\n\n const title =\n $item.find(\".item-title, .item-name, .sc-product-title\").text().trim() ||\n $item.find(\"a\").first().text().trim();\n const price = $item.find(\".item-price, .a-price .a-offscreen\").first().text().trim();\n const qtyText = $item.find(\".item-quantity, [name='quantity']\").text().trim();\n const qtyMatch = qtyText.match(/\\d+/);\n const quantity = qtyMatch ? parseInt(qtyMatch[0], 10) : 1;\n\n if (title) {\n items.push({ asin, title, price, quantity });\n }\n });\n\n // Parse totals\n const getText = (selector: string): string => $(selector).text().trim();\n const findTotal = (label: string): string => {\n let value = \"\";\n $(\".order-totals div, .a-row\").each((_i, el) => {\n const text = $(el).text();\n if (text.toLowerCase().includes(label.toLowerCase())) {\n const priceMatch = text.match(/\\$[\\d,]+\\.?\\d*/);\n if (priceMatch) {\n value = priceMatch[0];\n return false; // break\n }\n }\n });\n return value;\n };\n\n const subtotal = findTotal(\"items\") || findTotal(\"subtotal\") || \"\";\n const shipping = findTotal(\"shipping\") || \"$0.00\";\n const tax = findTotal(\"tax\") || \"$0.00\";\n const total =\n getText(\".grand-total-price\") ||\n getText(\".order-total-value\") ||\n findTotal(\"order total\") ||\n findTotal(\"grand total\") ||\n \"\";\n\n // Check for place order button\n const hasPlaceOrderButton =\n $('input[name=\"placeYourOrder1\"], #submitOrderButtonId, [name*=\"placeOrder\"]').length > 0;\n\n if (items.length === 0 && !total) {\n log(\"Could not parse checkout summary\");\n return {\n summary: null,\n error: { type: \"unknown\", message: \"Could not parse checkout page\" },\n hasPlaceOrderButton,\n };\n }\n\n const summary: CheckoutSummary = {\n items,\n subtotal,\n shipping,\n tax,\n total,\n };\n\n log(`Parsed checkout: ${items.length} items, total ${total}`);\n return { summary, error: null, hasPlaceOrderButton };\n}\n\nexport function parseOrderConfirmation(html: string): PurchaseResult {\n const $ = cheerio.load(html);\n\n // Look for success indicators\n const successAlert = $(\".a-alert-success, .a-box.a-alert-success\").length > 0;\n const thankYouText = $(\"body\").text().toLowerCase();\n const hasThankYou =\n thankYouText.includes(\"thanks\") ||\n thankYouText.includes(\"order placed\") ||\n thankYouText.includes(\"order confirmed\");\n\n if (!successAlert && !hasThankYou) {\n log(\"Order confirmation page does not show success\");\n const raw = {\n success: false,\n orderId: null,\n message: \"Order placement failed - confirmation not found\",\n orderTotal: null,\n };\n const parsed = PurchaseResultSchema.safeParse(raw);\n return parsed.success ? (parsed.data as PurchaseResult) : raw;\n }\n\n // Extract order ID\n let orderId: string | null = null;\n\n // Try .order-id class first\n const orderIdEl = $(\".order-id, #orderDetails .order-id, bdi.order-id\").first();\n if (orderIdEl.length) {\n orderId = orderIdEl.text().trim();\n }\n\n // Try bdi containing \"Order #\" nearby\n if (!orderId) {\n $(\"bdi\").each((_i, el) => {\n const text = $(el).text().trim();\n if (/^\\d{3}-\\d{7}-\\d{7}$/.test(text)) {\n orderId = text;\n return false; // break\n }\n });\n }\n\n // Try \"Order #\" pattern in text\n if (!orderId) {\n const orderMatch = $(\"body\")\n .text()\n .match(/Order\\s*#?\\s*(\\d{3}-\\d{7}-\\d{7})/i);\n if (orderMatch) {\n orderId = orderMatch[1];\n }\n }\n\n // Extract order total\n let orderTotal: string | null = null;\n const totalEl = $(\".order-total-value, .order-total\").first();\n if (totalEl.length) {\n orderTotal = totalEl.text().trim();\n }\n if (!orderTotal) {\n const totalMatch = $(\"body\")\n .text()\n .match(/Order total[:\\s]*(\\$[\\d,]+\\.?\\d*)/i);\n if (totalMatch) {\n orderTotal = totalMatch[1];\n }\n }\n\n const message = orderId\n ? `Order placed successfully. Order ID: ${orderId}`\n : \"Order placed successfully, but order ID could not be extracted.\";\n\n const raw = {\n success: true,\n orderId,\n message,\n orderTotal,\n };\n\n const parsed = PurchaseResultSchema.safeParse(raw);\n if (!parsed.success) {\n log(`Order confirmation validation failed: ${parsed.error.message}`);\n return raw;\n }\n\n log(`Parsed order confirmation: ${orderId}, total ${orderTotal}`);\n return parsed.data as PurchaseResult;\n}\n","import { z } from \"zod\";\n\nexport interface Product {\n readonly asin: string;\n readonly title: string;\n readonly price: number | null;\n readonly currency: string;\n readonly rating: number | null;\n readonly reviewCount: number;\n readonly brand: string | null;\n readonly isPrime: boolean;\n readonly imageUrl: string | null;\n readonly url: string;\n}\n\nexport const ProductSchema = z.object({\n asin: z.string().min(1),\n title: z.string().min(1),\n price: z.number().positive().nullable(),\n currency: z.string().min(1),\n rating: z.number().min(0).max(5).nullable(),\n reviewCount: z.number().int().nonnegative(),\n brand: z.string().nullable(),\n isPrime: z.boolean(),\n imageUrl: z.string().url().nullable(),\n url: z.string().url(),\n});\n\nexport interface ProductDetails {\n readonly asin: string;\n readonly title: string;\n readonly price: number | null;\n readonly currency: string;\n readonly rating: number | null;\n readonly reviewCount: number;\n readonly brand: string | null;\n readonly isPrime: boolean;\n readonly description: string;\n readonly features: readonly string[];\n readonly imageUrls: readonly string[];\n readonly availability: string;\n readonly url: string;\n}\n\nexport const ProductDetailsSchema = z.object({\n asin: z.string().min(1),\n title: z.string().min(1),\n price: z.number().positive().nullable(),\n currency: z.string().min(1),\n rating: z.number().min(0).max(5).nullable(),\n reviewCount: z.number().int().nonnegative(),\n brand: z.string().nullable(),\n isPrime: z.boolean(),\n description: z.string(),\n features: z.array(z.string()),\n imageUrls: z.array(z.string().url()),\n availability: z.string(),\n url: z.string().url(),\n});\n\nexport interface Review {\n readonly id: string;\n readonly author: string;\n readonly rating: number;\n readonly title: string;\n readonly body: string;\n readonly date: string;\n readonly verified: boolean;\n}\n\nexport const ReviewSchema = z.object({\n id: z.string().min(1),\n author: z.string().min(1),\n rating: z.number().int().min(1).max(5),\n title: z.string(),\n body: z.string(),\n date: z.string().min(1),\n verified: z.boolean(),\n});\n\nexport interface ReviewSummary {\n readonly averageRating: number;\n readonly totalCount: number;\n readonly starDistribution: Readonly<Record<1 | 2 | 3 | 4 | 5, number>>;\n}\n\nexport const ReviewSummarySchema = z.object({\n averageRating: z.number().min(0).max(5),\n totalCount: z.number().int().nonnegative(),\n starDistribution: z.object({\n 1: z.number().int().nonnegative(),\n 2: z.number().int().nonnegative(),\n 3: z.number().int().nonnegative(),\n 4: z.number().int().nonnegative(),\n 5: z.number().int().nonnegative(),\n }),\n});\n\nexport interface CartItem {\n readonly asin: string;\n readonly title: string;\n readonly price: number | null;\n readonly quantity: number;\n}\n\nexport const CartItemSchema = z.object({\n asin: z.string().min(1),\n title: z.string().min(1),\n price: z.number().positive().nullable(),\n quantity: z.number().int().positive(),\n});\n\nexport interface Cart {\n readonly items: readonly CartItem[];\n readonly subtotal: number | null;\n readonly currency: string;\n}\n\nexport const CartSchema = z.object({\n items: z.array(CartItemSchema),\n subtotal: z.number().nonnegative().nullable(),\n currency: z.string().min(1),\n});\n\nexport interface CartResult {\n readonly success: boolean;\n readonly message: string;\n readonly cart: Cart;\n}\n\nexport interface Order {\n readonly orderId: string;\n readonly date: string;\n readonly total: number;\n readonly currency: string;\n readonly status: string;\n readonly itemCount?: number;\n readonly items: readonly OrderItem[];\n}\n\nexport interface OrderItem {\n readonly asin: string;\n readonly title: string;\n readonly price: number | null;\n readonly quantity: number;\n readonly deliveryStatus?: string;\n}\n\nexport const OrderItemSchema = z.object({\n asin: z.string().min(1),\n title: z.string().min(1),\n price: z.number().positive().nullable(),\n quantity: z.number().int().positive(),\n deliveryStatus: z.string().optional(),\n});\n\nexport const OrderSchema = z.object({\n orderId: z.string().min(1),\n date: z.string().min(1),\n total: z.number().nonnegative(),\n currency: z.string().min(1),\n status: z.string().min(1),\n itemCount: z.number().int().nonnegative().optional(),\n items: z.array(OrderItemSchema),\n});\n\nexport interface OrderHistoryParams {\n readonly limit?: number;\n readonly page?: number;\n readonly startDate?: string;\n readonly endDate?: string;\n}\n\nexport const OrderHistoryParamsSchema = z.object({\n limit: z.number().int().min(1).max(50).optional().default(10),\n page: z.number().int().min(1).optional().default(1),\n startDate: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n .optional(),\n endDate: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n .optional(),\n});\n\nexport interface OrderHistoryResponse {\n readonly orders: readonly Order[];\n readonly hasMore: boolean;\n readonly nextPage: number | null;\n}\n\nexport const OrderHistoryResponseSchema = z.object({\n orders: z.array(OrderSchema),\n hasMore: z.boolean(),\n nextPage: z.number().int().positive().nullable(),\n});\n\nexport interface PurchaseResult {\n readonly success: boolean;\n readonly orderId: string | null;\n readonly message: string;\n readonly orderTotal: string | null;\n}\n\nexport const PurchaseResultSchema = z.object({\n success: z.boolean(),\n orderId: z.string().min(1).nullable(),\n message: z.string(),\n orderTotal: z.string().nullable(),\n});\n\nexport interface AmazonProvider {\n searchProducts(query: string, category?: string, maxResults?: number): Promise<Product[]>;\n getProductDetails(\n asin: string,\n ): Promise<{ details: ProductDetails; primaryImageBase64: string | null }>;\n getReviews(\n asin: string,\n maxReviews?: number,\n sortBy?: string,\n filterByStars?: number,\n ): Promise<{ reviews: Review[]; summary: ReviewSummary }>;\n addToCart(asin: string, quantity?: number): Promise<CartResult>;\n removeFromCart(asin: string): Promise<CartResult>;\n getCart(): Promise<Cart>;\n clearCart(): Promise<void>;\n getOrderHistory(params?: OrderHistoryParams): Promise<OrderHistoryResponse>;\n getOrderDetails(orderId: string): Promise<Order>;\n purchase(confirmationToken: string): Promise<PurchaseResult>;\n}\n","import { getJson } from \"serpapi\";\nimport type { Product, ProductDetails, Review, ReviewSummary } from \"./types.js\";\n\nexport interface SerpApiClient {\n searchProducts(query: string, category?: string, maxResults?: number): Promise<Product[]>;\n getProductDetails(asin: string): Promise<ProductDetails | null>;\n getReviews(\n asin: string,\n maxReviews?: number,\n sortBy?: string,\n filterByStars?: number,\n ): Promise<{ reviews: Review[]; summary: ReviewSummary } | null>;\n}\n\nfunction log(message: string): void {\n console.error(`[serpapi] ${message}`);\n}\n\nfunction parsePrice(raw: string | undefined | null): { price: number | null; currency: string } {\n if (!raw) return { price: null, currency: \"USD\" };\n const match = raw.match(/([£€$])?([\\d,]+\\.?\\d*)/);\n if (!match) return { price: null, currency: \"USD\" };\n\n const currencyMap: Record<string, string> = { $: \"USD\", \"£\": \"GBP\", \"€\": \"EUR\" };\n return {\n price: parseFloat(match[2].replace(/,/g, \"\")),\n currency: currencyMap[match[1]] ?? \"USD\",\n };\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport function createSerpApiClient(apiKey: string): SerpApiClient {\n return {\n async searchProducts(query, category, maxResults = 20) {\n log(`Searching for \"${query}\"${category ? ` in ${category}` : \"\"}`);\n\n try {\n const params: Record<string, any> = {\n engine: \"amazon\",\n amazon_domain: \"amazon.com\",\n search_term: query,\n api_key: apiKey,\n };\n if (category) {\n params.amazon_url = `https://www.amazon.com/s?k=${encodeURIComponent(query)}&i=${encodeURIComponent(category)}`;\n }\n\n const json = await getJson(params);\n const results: any[] = json.organic_results ?? [];\n\n const products: Product[] = results.slice(0, maxResults).map((r: any) => {\n const { price, currency } = parsePrice(r.price?.raw ?? r.price?.value?.toString());\n return {\n asin: r.asin ?? \"\",\n title: r.title ?? \"\",\n price,\n currency,\n rating: r.rating ?? null,\n reviewCount: r.reviews ?? 0,\n brand: r.brand ?? null,\n isPrime: r.is_prime ?? false,\n imageUrl: r.thumbnail ?? null,\n url: r.link ?? `https://www.amazon.com/dp/${r.asin}`,\n };\n });\n\n log(`Found ${products.length} products`);\n return products;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n log(`Search error: ${message}`);\n return [];\n }\n },\n\n async getProductDetails(asin) {\n log(`Fetching product details for ${asin}`);\n\n try {\n const json = await getJson({\n engine: \"amazon_product\",\n asin,\n amazon_domain: \"amazon.com\",\n api_key: apiKey,\n });\n\n const p: any = json.product_results ?? json.product_result;\n if (!p) {\n log(`No product result for ${asin}`);\n return null;\n }\n\n const { price, currency } = parsePrice(p.price?.raw ?? p.price?.value?.toString());\n\n const details: ProductDetails = {\n asin: p.asin ?? asin,\n title: p.title ?? \"\",\n price,\n currency,\n rating: p.rating ?? null,\n reviewCount: p.reviews_total ?? p.reviews ?? 0,\n brand: p.brand ?? null,\n isPrime: p.is_prime ?? false,\n description: json.product_description?.text ?? p.description ?? \"\",\n features:\n json.about_item?.map((item: any) => item.text ?? item) ?? p.feature_bullets ?? [],\n imageUrls: p.images?.map((img: any) => img.link ?? img) ?? [],\n availability: p.availability?.raw ?? p.availability ?? \"Unknown\",\n url: p.link ?? `https://www.amazon.com/dp/${asin}`,\n };\n\n log(`Got details for \"${details.title}\"`);\n return details;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n log(`Product details error: ${message}`);\n return null;\n }\n },\n\n async getReviews(asin, maxReviews, _sortBy, _filterByStars) {\n log(`Fetching reviews for ${asin}`);\n\n try {\n // SerpAPI returns reviews via the amazon_product engine\n // (there is no separate amazon_product_reviews engine)\n const json = await getJson({\n engine: \"amazon_product\",\n asin,\n amazon_domain: \"amazon.com\",\n api_key: apiKey,\n });\n\n const reviewsInfo: any = json.reviews_information ?? {};\n const rawReviews: any[] = reviewsInfo.authors_reviews ?? [];\n\n if (rawReviews.length === 0) {\n log(`No reviews found for ${asin}`);\n return null;\n }\n\n const reviews: Review[] = rawReviews\n .slice(0, maxReviews ?? rawReviews.length)\n .map((r: any, i: number) => ({\n id: r.id ?? `serpapi-${asin}-${i}`,\n author: r.author ?? \"Unknown\",\n rating: r.rating ?? 0,\n title: r.title ?? \"\",\n body: r.text ?? r.body ?? \"\",\n date: r.date ?? \"\",\n verified: r.verified_purchase ?? false,\n }));\n\n const customerReviews: any = reviewsInfo.summary?.customer_reviews ?? {};\n const product: any = json.product_results ?? {};\n\n const starDist = {\n 1: customerReviews[\"1 star\"] ?? 0,\n 2: customerReviews[\"2 star\"] ?? 0,\n 3: customerReviews[\"3 star\"] ?? 0,\n 4: customerReviews[\"4 star\"] ?? 0,\n 5: customerReviews[\"5 star\"] ?? 0,\n };\n\n // totalCount: prefer product.reviews_total, fall back to sum of star distribution\n const totalFromStars = starDist[1] + starDist[2] + starDist[3] + starDist[4] + starDist[5];\n const totalCount = product.reviews_total ?? (totalFromStars > 0 ? totalFromStars : 0);\n\n const summary: ReviewSummary = {\n averageRating: product.rating ?? 0,\n totalCount,\n starDistribution: starDist,\n };\n\n log(`Got ${reviews.length} reviews (avg ${summary.averageRating}/5)`);\n return { reviews, summary };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n log(`Reviews error: ${message}`);\n return null;\n }\n },\n };\n}\n","import { createHash } from \"node:crypto\";\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n unlinkSync,\n mkdirSync,\n readdirSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getDataDir } from \"../utils/paths.js\";\n\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n metadata: CacheMetadata;\n}\n\ninterface CacheMetadata {\n namespace?: string;\n createdAt?: number;\n}\n\nexport interface CacheOptions {\n ttlSeconds?: number;\n namespace?: string;\n}\n\nconst DEFAULT_TTL_SECONDS = 600; // 10 minutes\n\nfunction getCacheDir(): string {\n return join(getDataDir(), \"cache\");\n}\n\nfunction getCacheFilePath(key: string): string {\n const hash = createHash(\"sha256\").update(key).digest(\"hex\");\n return join(getCacheDir(), `${hash}.json`);\n}\n\nexport function getCached<T>(key: string, _options?: CacheOptions): T | null {\n const filePath = getCacheFilePath(key);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const entry: CacheEntry<T> = JSON.parse(content);\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n try {\n unlinkSync(filePath);\n } catch {\n // Ignore deletion errors\n }\n return null;\n }\n\n return entry.value;\n } catch {\n // Corrupted cache file - delete it\n try {\n unlinkSync(filePath);\n } catch {\n // Ignore deletion errors\n }\n return null;\n }\n}\n\nexport function setCache<T>(key: string, value: T, options?: CacheOptions): void {\n const cacheDir = getCacheDir();\n mkdirSync(cacheDir, { recursive: true });\n\n const ttlSeconds = options?.ttlSeconds ?? getDefaultTTL();\n const filePath = getCacheFilePath(key);\n\n const entry: CacheEntry<T> = {\n value,\n expiresAt: Date.now() + ttlSeconds * 1000,\n metadata: {\n namespace: options?.namespace,\n createdAt: Date.now(),\n },\n };\n\n writeFileSync(filePath, JSON.stringify(entry), \"utf-8\");\n}\n\nexport function invalidateCache(key: string): void {\n const filePath = getCacheFilePath(key);\n\n if (existsSync(filePath)) {\n try {\n unlinkSync(filePath);\n } catch {\n // Ignore deletion errors\n }\n }\n}\n\nexport function clearCacheNamespace(namespace: string): void {\n const cacheDir = getCacheDir();\n\n if (!existsSync(cacheDir)) {\n return;\n }\n\n const files = readdirSync(cacheDir);\n\n for (const file of files) {\n if (!file.endsWith(\".json\")) {\n continue;\n }\n\n const filePath = join(cacheDir, file);\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const entry: CacheEntry<unknown> = JSON.parse(content);\n\n if (entry.metadata?.namespace === namespace) {\n unlinkSync(filePath);\n }\n } catch {\n // Ignore read/parse errors\n }\n }\n}\n\nfunction getDefaultTTL(): number {\n const envTTL = process.env.AMAZON_MCP_CACHE_TTL;\n if (envTTL) {\n const parsed = parseInt(envTTL, 10);\n if (!isNaN(parsed) && parsed > 0) {\n return parsed;\n }\n }\n return DEFAULT_TTL_SECONDS;\n}\n","import type { Page } from \"playwright\";\nimport { CaptchaRequiredError } from \"../../errors.js\";\nimport { closeBrowser, getPage } from \"./browser.js\";\nimport { createLogger } from \"../../utils/logger.js\";\n\nconst logger = createLogger(\"captcha\");\n\n// CAPTCHA detection patterns - must be specific to avoid false positives\nconst CAPTCHA_PATTERNS = [\n // Amazon text CAPTCHA prompts (visible text)\n /enter the characters you see/i,\n /type the characters/i,\n /sorry,?\\s*we just need to make sure you'?re not a robot/i,\n /to continue, please type the characters/i,\n\n // Amazon CAPTCHA form elements (specific IDs/classes)\n /id=\"auth-captcha-image\"/i,\n /id=\"auth-captcha-guess\"/i,\n /id=\"captchacharacters\"/i,\n\n // reCAPTCHA iframe/div (specific attributes)\n /class=\"g-recaptcha\"/i,\n /data-sitekey=/i,\n];\n\n// Specific HTML element patterns - these are checked via substring matching\n// Keep them specific to avoid false positives\nconst ELEMENT_PATTERNS = [\n \"#auth-captcha-image\",\n \"#auth-captcha-guess\",\n \"#captchacharacters\",\n];\n\n/**\n * Detect if HTML content contains a CAPTCHA challenge.\n * Uses pattern matching on common Amazon CAPTCHA indicators.\n */\nexport function detectCaptcha(html: string): boolean {\n if (!html || html.length < 50) {\n return false;\n }\n\n const lowerHtml = html.toLowerCase();\n\n // Check text patterns\n for (const pattern of CAPTCHA_PATTERNS) {\n if (pattern.test(lowerHtml)) {\n return true;\n }\n }\n\n // Check for specific element patterns\n for (const selector of ELEMENT_PATTERNS) {\n // Simple check - look for key parts of the selector in HTML\n const selectorParts = selector\n .replace(/[[\\]#.]/g, \" \")\n .split(/\\s+/)\n .filter((p) => p.length > 3);\n\n const matchCount = selectorParts.filter((part) =>\n lowerHtml.includes(part.toLowerCase()),\n ).length;\n\n // If most parts match, likely a CAPTCHA element\n if (matchCount >= Math.ceil(selectorParts.length * 0.5)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Detect CAPTCHA on a Playwright page by checking page content.\n */\nexport async function detectCaptchaOnPage(page: Page): Promise<boolean> {\n const html = await page.content();\n return detectCaptcha(html);\n}\n\n/**\n * Handle CAPTCHA by switching to headed browser mode and waiting for user resolution.\n *\n * This function:\n * 1. Closes the current headless browser context\n * 2. Opens a headed browser so the user can see the CAPTCHA\n * 3. Navigates to the same URL\n * 4. Waits for the user to solve the CAPTCHA (up to 5 minutes)\n * 5. Returns true if resolved, throws if timeout\n */\nexport async function handleCaptcha(currentUrl: string): Promise<Page> {\n logger.info(\"CAPTCHA detected - switching to headed browser mode\");\n\n // Close current headless browser\n await closeBrowser();\n\n // Open headed browser\n const page = await getPage({ headless: false });\n\n logger.info(\"Headed browser opened - please solve the CAPTCHA in the browser window\");\n\n // Navigate to the URL that had the CAPTCHA\n await page.goto(currentUrl, { waitUntil: \"domcontentloaded\" });\n\n // Wait for user to solve CAPTCHA\n const resolved = await waitForCaptchaResolution(page);\n\n if (!resolved) {\n throw new CaptchaRequiredError(\"CAPTCHA timeout. The CAPTCHA was not solved within 5 minutes.\");\n }\n\n logger.info(\"CAPTCHA resolved - continuing operation\");\n\n return page;\n}\n\n/**\n * Wait for user to solve CAPTCHA.\n * Polls the page until CAPTCHA is no longer detected or timeout is reached.\n */\nexport async function waitForCaptchaResolution(\n page: Page,\n timeoutMs: number = 300000, // 5 minutes\n): Promise<boolean> {\n const startTime = Date.now();\n const pollIntervalMs = 2000;\n\n while (Date.now() - startTime < timeoutMs) {\n const hasCaptcha = await detectCaptchaOnPage(page);\n if (!hasCaptcha) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n\n return false;\n}\n","export interface RetryOptions {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffFactor?: number;\n jitter?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<RetryOptions> = {\n maxRetries: 3,\n initialDelayMs: 1000,\n maxDelayMs: 16000,\n backoffFactor: 2,\n jitter: true,\n};\n\n// Transient error patterns that should trigger retry\nconst TRANSIENT_ERROR_PATTERNS = [\n /timeout/i,\n /ECONNRESET/i,\n /ENOTFOUND/i,\n /ETIMEDOUT/i,\n /ECONNREFUSED/i,\n /EPIPE/i,\n /ENETUNREACH/i,\n /EHOSTUNREACH/i,\n /socket hang up/i,\n /network/i,\n];\n\n/**\n * Check if an error is transient and should be retried.\n */\nexport function isTransientError(error: Error): boolean {\n const message = error.message || \"\";\n\n for (const pattern of TRANSIENT_ERROR_PATTERNS) {\n if (pattern.test(message)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Execute a function with exponential backoff retry on transient errors.\n *\n * @param fn - The async function to execute\n * @param options - Retry configuration options\n * @returns The result of the function\n * @throws The last error if all retries are exhausted\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options?: RetryOptions,\n): Promise<T> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry non-transient errors\n if (!isTransientError(lastError)) {\n throw lastError;\n }\n\n // Don't wait after the last attempt\n if (attempt < opts.maxRetries - 1) {\n const delay = calculateDelay(attempt, opts);\n await sleep(delay);\n }\n }\n }\n\n // All retries exhausted\n throw lastError;\n}\n\n/**\n * Calculate delay for a given retry attempt with exponential backoff and optional jitter.\n */\nfunction calculateDelay(attempt: number, opts: Required<RetryOptions>): number {\n // Exponential backoff: initialDelay * (factor ^ attempt)\n let delay = opts.initialDelayMs * Math.pow(opts.backoffFactor, attempt);\n\n // Cap at maxDelay\n delay = Math.min(delay, opts.maxDelayMs);\n\n // Add jitter if enabled (+/- 20%)\n if (opts.jitter) {\n const jitterRange = delay * 0.2;\n delay = delay - jitterRange + Math.random() * jitterRange * 2;\n }\n\n return Math.round(delay);\n}\n\n/**\n * Sleep for specified milliseconds.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type {\n AmazonProvider,\n Product,\n ProductDetails,\n Review,\n ReviewSummary,\n CartResult,\n Cart,\n Order,\n OrderHistoryParams,\n OrderHistoryResponse,\n PurchaseResult,\n} from \"../types.js\";\nimport type { Page } from \"playwright\";\nimport { getPage, AMAZON_BASE_URL } from \"./browser.js\";\nimport { assertSessionValid } from \"./auth.js\";\nimport {\n parseSearchResults,\n parseProductDetails,\n parseReviews,\n parseCart,\n parseOrderHistory,\n parseOrderDetails,\n parseCartForCheckout,\n parseCheckoutPage,\n parseOrderConfirmation,\n} from \"./scraper.js\";\nimport { ScrapingError, CaptchaRequiredError } from \"../../errors.js\";\nimport {\n throttleNavigation,\n simulateMouseMovement,\n simulateScroll,\n randomDelay,\n} from \"./stealth.js\";\nimport { createSerpApiClient, type SerpApiClient } from \"../serpapi.js\";\nimport { getCached, setCache } from \"../../cache/index.js\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport { detectCaptcha, handleCaptcha } from \"./captcha.js\";\nimport { retryWithBackoff } from \"../../utils/retry.js\";\n\nconst SCRAPE_TIMEOUT_MS = 30_000;\nconst SEARCH_CACHE_TTL_SECONDS = 600; // 10 minutes\nconst PRODUCT_CACHE_TTL_SECONDS = 1800; // 30 minutes\nconst REVIEWS_CACHE_TTL_SECONDS = 1800; // 30 minutes\n\nconst logger = createLogger(\"provider\");\n\nfunction log(message: string): void {\n logger.info(message);\n}\n\nasync function downloadImageAsBase64(page: Page, imageUrl: string): Promise<string | null> {\n try {\n const response = await page.request.get(imageUrl, { timeout: 10_000 });\n if (!response.ok()) {\n log(`Image download failed: ${response.status()} for ${imageUrl}`);\n return null;\n }\n const buffer = await response.body();\n return buffer.toString(\"base64\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n log(`Image download error: ${message}`);\n return null;\n }\n}\n\nexport class PlaywrightProvider implements AmazonProvider {\n private serpapi: SerpApiClient | null;\n\n constructor(serpApiKey?: string) {\n this.serpapi = serpApiKey ? createSerpApiClient(serpApiKey) : null;\n log(`SerpAPI fallback: ${this.serpapi ? \"configured\" : \"not configured\"}`);\n }\n\n async searchProducts(query: string, category?: string, maxResults?: number): Promise<Product[]> {\n // Check cache first\n const cacheKey = `search:${query}:${category ?? \"all\"}`;\n const cached = getCached<Product[]>(cacheKey, { namespace: \"search\" });\n if (cached) {\n log(`Cache hit for search: ${query}`);\n const limit = maxResults ?? 20;\n return cached.slice(0, limit);\n }\n\n const page = await getPage();\n await assertSessionValid(page);\n\n const searchUrl = new URL(\"/s\", AMAZON_BASE_URL);\n searchUrl.searchParams.set(\"k\", query);\n if (category) {\n searchUrl.searchParams.set(\"i\", category);\n }\n\n log(`Searching: ${searchUrl.toString()}`);\n\n await throttleNavigation();\n\n try {\n await retryWithBackoff(async () => {\n await page.goto(searchUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n });\n\n await simulateMouseMovement(page);\n await simulateScroll(page);\n await randomDelay(500, 1500);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load search results: ${message}`, {\n cause: error,\n });\n }\n\n await assertSessionValid(page);\n\n const html = await page.content();\n\n // Check for CAPTCHA and handle interactively\n if (detectCaptcha(html)) {\n logger.warn(\"CAPTCHA detected on search page - switching to headed browser\");\n const resolvedPage = await handleCaptcha(page.url());\n // After CAPTCHA resolved, get fresh content\n const freshHtml = await resolvedPage.content();\n if (detectCaptcha(freshHtml)) {\n throw new CaptchaRequiredError(\"CAPTCHA could not be resolved\");\n }\n // Use fresh page and continue with resolved content\n const products = parseSearchResults(freshHtml);\n const limit = maxResults ?? 20;\n const result = products.slice(0, limit);\n if (products.length > 0) {\n setCache(cacheKey, products, { ttlSeconds: SEARCH_CACHE_TTL_SECONDS, namespace: \"search\" });\n }\n return result;\n }\n\n const products = parseSearchResults(html);\n\n const limit = maxResults ?? 20;\n const result = products.slice(0, limit);\n\n if (result.length === 0 && this.serpapi) {\n log(`Empty search results from scraper, trying SerpAPI fallback`);\n const serpResult = await this.serpapi.searchProducts(query, category, maxResults);\n if (serpResult.length > 0) {\n log(`SerpAPI fallback returned ${serpResult.length} products`);\n // Cache SerpAPI results too\n setCache(cacheKey, serpResult, {\n ttlSeconds: SEARCH_CACHE_TTL_SECONDS,\n namespace: \"search\",\n });\n return serpResult;\n }\n }\n\n // Cache successful results\n if (products.length > 0) {\n setCache(cacheKey, products, { ttlSeconds: SEARCH_CACHE_TTL_SECONDS, namespace: \"search\" });\n }\n\n return result;\n }\n\n async getProductDetails(\n asin: string,\n ): Promise<{ details: ProductDetails; primaryImageBase64: string | null }> {\n // Check cache first\n const cacheKey = `product:${asin}`;\n const cached = getCached<{ details: ProductDetails; primaryImageBase64: string | null }>(\n cacheKey,\n { namespace: \"product\" },\n );\n if (cached) {\n log(`Cache hit for product: ${asin}`);\n return cached;\n }\n\n const page = await getPage();\n await assertSessionValid(page);\n\n const productUrl = new URL(`/dp/${asin}`, AMAZON_BASE_URL);\n log(`Fetching product details: ${productUrl.toString()}`);\n\n await throttleNavigation();\n\n try {\n await retryWithBackoff(async () => {\n await page.goto(productUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n });\n\n await simulateMouseMovement(page);\n await simulateScroll(page);\n await randomDelay(500, 1500);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load product page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n\n const html = await page.content();\n\n // Check for CAPTCHA and handle interactively\n let contentHtml = html;\n if (detectCaptcha(html)) {\n logger.warn(\"CAPTCHA detected on product page - switching to headed browser\");\n const resolvedPage = await handleCaptcha(page.url());\n contentHtml = await resolvedPage.content();\n if (detectCaptcha(contentHtml)) {\n throw new CaptchaRequiredError(\"CAPTCHA could not be resolved\");\n }\n }\n\n const details = parseProductDetails(contentHtml);\n\n if (!details) {\n if (this.serpapi) {\n log(`Could not parse product details, trying SerpAPI fallback for ${asin}`);\n const serpDetails = await this.serpapi.getProductDetails(asin);\n if (serpDetails) {\n log(`SerpAPI fallback returned details for \"${serpDetails.title}\"`);\n const result = { details: serpDetails, primaryImageBase64: null };\n // Cache SerpAPI results\n setCache(cacheKey, result, {\n ttlSeconds: PRODUCT_CACHE_TTL_SECONDS,\n namespace: \"product\",\n });\n return result;\n }\n }\n throw new ScrapingError(`Could not parse product details for ASIN ${asin}`);\n }\n\n // Download primary image as base64\n let primaryImageBase64: string | null = null;\n if (details.imageUrls.length > 0) {\n primaryImageBase64 = await downloadImageAsBase64(page, details.imageUrls[0]);\n }\n\n const result = { details, primaryImageBase64 };\n\n // Cache successful results\n setCache(cacheKey, result, { ttlSeconds: PRODUCT_CACHE_TTL_SECONDS, namespace: \"product\" });\n\n return result;\n }\n\n async getReviews(\n asin: string,\n maxReviews?: number,\n sortBy?: string,\n filterByStars?: number,\n ): Promise<{ reviews: Review[]; summary: ReviewSummary }> {\n // Check cache first\n const cacheKey = `reviews:${asin}:${sortBy ?? \"default\"}:${filterByStars ?? \"all\"}`;\n const cached = getCached<{ reviews: Review[]; summary: ReviewSummary }>(cacheKey, {\n namespace: \"reviews\",\n });\n if (cached) {\n log(`Cache hit for reviews: ${asin}`);\n const limit = maxReviews ?? cached.reviews.length;\n return { reviews: cached.reviews.slice(0, limit), summary: cached.summary };\n }\n\n const page = await getPage();\n await assertSessionValid(page);\n\n const reviewsUrl = new URL(`/product-reviews/${asin}`, AMAZON_BASE_URL);\n if (sortBy) {\n reviewsUrl.searchParams.set(\"sortBy\", sortBy);\n }\n if (filterByStars !== undefined) {\n const starMap: Record<number, string> = {\n 1: \"one_star\",\n 2: \"two_star\",\n 3: \"three_star\",\n 4: \"four_star\",\n 5: \"five_star\",\n };\n const filterValue = starMap[filterByStars];\n if (filterValue) {\n reviewsUrl.searchParams.set(\"filterByStar\", filterValue);\n }\n }\n\n log(`Fetching reviews: ${reviewsUrl.toString()}`);\n\n await throttleNavigation();\n\n try {\n await retryWithBackoff(async () => {\n await page.goto(reviewsUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n });\n\n await simulateMouseMovement(page);\n await simulateScroll(page);\n await randomDelay(500, 1500);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load reviews page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n\n try {\n // Amazon sometimes uses <li> instead of <div> for review containers\n await page.waitForSelector('[data-hook=\"review\"]', { timeout: 10_000 });\n } catch {\n log(\"Warning: review elements did not appear within timeout\");\n }\n\n const html = await page.content();\n\n // Check for CAPTCHA and handle interactively\n let contentHtml = html;\n if (detectCaptcha(html)) {\n logger.warn(\"CAPTCHA detected on reviews page - switching to headed browser\");\n const resolvedPage = await handleCaptcha(page.url());\n contentHtml = await resolvedPage.content();\n if (detectCaptcha(contentHtml)) {\n throw new CaptchaRequiredError(\"CAPTCHA could not be resolved\");\n }\n }\n\n const { reviews, summary } = parseReviews(contentHtml);\n\n const limit = maxReviews ?? reviews.length;\n const result = { reviews: reviews.slice(0, limit), summary };\n\n if (result.reviews.length === 0 && this.serpapi) {\n log(`Empty reviews from scraper, trying SerpAPI fallback for ${asin}`);\n const serpResult = await this.serpapi.getReviews(asin, maxReviews, sortBy, filterByStars);\n if (serpResult && serpResult.reviews.length > 0) {\n log(`SerpAPI fallback returned ${serpResult.reviews.length} reviews`);\n // Cache SerpAPI results\n setCache(cacheKey, serpResult, {\n ttlSeconds: REVIEWS_CACHE_TTL_SECONDS,\n namespace: \"reviews\",\n });\n return serpResult;\n }\n }\n\n // Cache successful results\n if (reviews.length > 0) {\n setCache(\n cacheKey,\n { reviews, summary },\n { ttlSeconds: REVIEWS_CACHE_TTL_SECONDS, namespace: \"reviews\" },\n );\n }\n\n return result;\n }\n\n private async dismissSubscribeAndSave(page: Page): Promise<void> {\n try {\n // Look for \"No thanks\" or one-time purchase option\n const noThanks = page.locator('text=\"No thanks\"');\n if (await noThanks.isVisible({ timeout: 2000 })) {\n await noThanks.click();\n log(\"Dismissed subscribe-and-save dialog\");\n }\n } catch {\n // Dialog didn't appear, continue\n }\n\n try {\n // Alternative: \"Buy once\" option on subscribe-and-save\n const buyOnce = page.locator('input[data-action=\"sos-one-time-purchase\"]');\n if (await buyOnce.isVisible({ timeout: 500 })) {\n await buyOnce.click();\n log(\"Selected one-time purchase option\");\n }\n } catch {\n // Option not present, continue\n }\n }\n\n private async dismissInsurancePrompt(page: Page): Promise<void> {\n try {\n // Look for \"No thanks\" or decline button\n const decline = page.locator(\n '[data-action=\"decline-warranty\"], button:has-text(\"No Thanks\")',\n );\n if (await decline.first().isVisible({ timeout: 2000 })) {\n await decline.first().click();\n log(\"Dismissed insurance/warranty prompt\");\n }\n } catch {\n // Prompt didn't appear, continue\n }\n }\n\n async addToCart(asin: string, _quantity?: number): Promise<CartResult> {\n const page = await getPage();\n await assertSessionValid(page);\n\n // Navigate to product page\n const productUrl = new URL(`/dp/${asin}`, AMAZON_BASE_URL);\n log(`Adding to cart: ${productUrl.toString()}`);\n\n await throttleNavigation();\n\n try {\n await page.goto(productUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n\n await simulateMouseMovement(page);\n await randomDelay(300, 800);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load product page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n\n // Click Add to Cart button\n try {\n const addToCartBtn = page.locator(\"#add-to-cart-button, #add-to-cart-button-ubb\");\n await addToCartBtn.first().click({ timeout: 5000 });\n log(\"Clicked Add to Cart button\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Could not find or click Add to Cart button: ${message}`, {\n cause: error,\n });\n }\n\n // Wait for navigation or modal\n await randomDelay(1000, 2000);\n\n // Handle subscribe-and-save dialog\n await this.dismissSubscribeAndSave(page);\n\n // Handle insurance prompt\n await this.dismissInsurancePrompt(page);\n\n // Get updated cart\n const cart = await this.getCart();\n return {\n success: true,\n message: `Added ${asin} to cart`,\n cart,\n };\n }\n\n async removeFromCart(asin: string): Promise<CartResult> {\n const page = await getPage();\n await assertSessionValid(page);\n\n // Navigate to cart page\n const cartUrl = new URL(\"/gp/cart/view.html\", AMAZON_BASE_URL);\n log(`Removing from cart: ${asin}`);\n\n await throttleNavigation();\n\n try {\n await page.goto(cartUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n\n await simulateMouseMovement(page);\n await randomDelay(300, 800);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load cart page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n\n // Find the cart item by ASIN and click delete\n try {\n const cartItem = page.locator(`.sc-list-item[data-asin=\"${asin}\"]`);\n if (!(await cartItem.isVisible({ timeout: 2000 }))) {\n const cart = await this.getCart();\n return {\n success: false,\n message: `Item ${asin} not in cart`,\n cart,\n };\n }\n\n const deleteBtn = cartItem.locator(\n 'input[value=\"Delete\"], [data-feature-id=\"item-delete-button\"]',\n );\n await deleteBtn.first().click({ timeout: 5000 });\n log(`Deleted item ${asin} from cart`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Could not remove item from cart: ${message}`, { cause: error });\n }\n\n // Wait for removal to process\n await randomDelay(1000, 2000);\n\n // Get updated cart\n const cart = await this.getCart();\n return {\n success: true,\n message: `Removed ${asin} from cart`,\n cart,\n };\n }\n\n async getCart(): Promise<Cart> {\n const page = await getPage();\n await assertSessionValid(page);\n\n const cartUrl = new URL(\"/gp/cart/view.html\", AMAZON_BASE_URL);\n log(`Fetching cart: ${cartUrl.toString()}`);\n\n await throttleNavigation();\n\n try {\n await page.goto(cartUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n\n await simulateMouseMovement(page);\n await simulateScroll(page);\n await randomDelay(500, 1500);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load cart page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n\n const html = await page.content();\n return parseCart(html);\n }\n\n async clearCart(): Promise<void> {\n const page = await getPage();\n await assertSessionValid(page);\n\n log(\"Clearing cart\");\n\n // Get current cart\n let cart = await this.getCart();\n\n // Iteratively remove each item\n while (cart.items.length > 0) {\n const asin = cart.items[0].asin;\n log(`Removing item ${asin} (${cart.items.length} items remaining)`);\n await this.removeFromCart(asin);\n cart = await this.getCart();\n }\n\n log(\"Cart cleared\");\n }\n\n async getOrderHistory(params?: OrderHistoryParams): Promise<OrderHistoryResponse> {\n const page = await getPage();\n\n log(\"Loading order history page\");\n\n // Build URL with optional parameters\n const limit = params?.limit ?? 10;\n const currentPage = params?.page ?? 1;\n const startIndex = (currentPage - 1) * limit;\n\n let url = `${AMAZON_BASE_URL}/gp/your-account/order-history`;\n const urlParams: string[] = [];\n\n if (startIndex > 0) {\n urlParams.push(`startIndex=${startIndex}`);\n }\n\n // Date filtering via timeFilter parameter\n if (params?.startDate || params?.endDate) {\n // Amazon uses timeFilter for date ranges, we'll pass startDate/endDate via URL\n if (params.startDate && params.endDate) {\n urlParams.push(`startDate=${params.startDate}`);\n urlParams.push(`endDate=${params.endDate}`);\n } else if (params.startDate) {\n // Just start date - filter from that date\n urlParams.push(`startDate=${params.startDate}`);\n } else if (params.endDate) {\n // Just end date - filter until that date\n urlParams.push(`endDate=${params.endDate}`);\n }\n }\n\n if (urlParams.length > 0) {\n url += `?${urlParams.join(\"&\")}`;\n }\n\n await throttleNavigation();\n\n try {\n await page.goto(url, {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load order history page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n await simulateMouseMovement(page);\n await randomDelay(500, 1500);\n await simulateScroll(page);\n\n const html = await page.content();\n const allOrders = parseOrderHistory(html);\n\n // Apply limit and determine pagination\n const orders = allOrders.slice(0, limit);\n const hasMore = allOrders.length > limit;\n const nextPage = hasMore ? currentPage + 1 : null;\n\n log(`Retrieved ${orders.length} orders (page ${currentPage})`);\n\n return {\n orders,\n hasMore,\n nextPage,\n };\n }\n\n async getOrderDetails(orderId: string): Promise<Order> {\n const page = await getPage();\n\n log(`Loading order details for ${orderId}`);\n\n const url = `${AMAZON_BASE_URL}/gp/your-account/order-details?orderID=${orderId}`;\n\n await throttleNavigation();\n\n try {\n await page.goto(url, {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load order details page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n await simulateMouseMovement(page);\n await randomDelay(500, 1500);\n\n const html = await page.content();\n const order = parseOrderDetails(html);\n\n if (!order) {\n throw new ScrapingError(`Order ${orderId} not found or could not be parsed`);\n }\n\n log(`Retrieved order details for ${orderId}`);\n\n return order;\n }\n\n async purchase(confirmationToken: string): Promise<PurchaseResult> {\n // Validate confirmation token\n if (!confirmationToken || confirmationToken.trim() === \"\") {\n return {\n success: false,\n orderId: null,\n message:\n \"Confirmation token is required. The AI assistant must confirm with the user before calling this tool.\",\n orderTotal: null,\n };\n }\n\n const page = await getPage();\n await assertSessionValid(page);\n\n // Step 1: Navigate to cart and verify items\n const cartUrl = new URL(\"/gp/cart/view.html\", AMAZON_BASE_URL);\n log(\"Starting purchase flow - checking cart\");\n\n await throttleNavigation();\n\n try {\n await page.goto(cartUrl.toString(), {\n waitUntil: \"domcontentloaded\",\n timeout: SCRAPE_TIMEOUT_MS,\n });\n await simulateMouseMovement(page);\n await randomDelay(500, 1000);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Failed to load cart page: ${message}`, { cause: error });\n }\n\n await assertSessionValid(page);\n\n // Check if cart is empty\n const cartHtml = await page.content();\n const { isEmpty, itemCount } = parseCartForCheckout(cartHtml);\n if (isEmpty) {\n return {\n success: false,\n orderId: null,\n message: \"Your cart is empty. Add items before attempting to purchase.\",\n orderTotal: null,\n };\n }\n\n // Log cart contents before purchase\n const cart = parseCart(cartHtml);\n log(`=== PRE-PURCHASE SUMMARY ===`);\n log(`Items in cart: ${itemCount}`);\n for (const item of cart.items) {\n log(` - ${item.title} (ASIN: ${item.asin}) x${item.quantity} @ $${item.price ?? \"N/A\"}`);\n }\n log(`Subtotal: $${cart.subtotal ?? \"N/A\"}`);\n log(`=============================`);\n\n // Step 2: Click \"Proceed to checkout\"\n log(\"Proceeding to checkout\");\n await throttleNavigation();\n\n try {\n // Multiple selectors for checkout button\n const checkoutBtn = page.locator(\n '#sc-buy-box-ptc-button, input[name=\"proceedToRetailCheckout\"], [data-feature-id=\"proceed-to-checkout-action\"]',\n );\n await checkoutBtn.first().click({ timeout: 5000 });\n await randomDelay(1500, 3000);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Could not find or click checkout button: ${message}`, {\n cause: error,\n });\n }\n\n // Wait for checkout page to load\n await page.waitForLoadState(\"domcontentloaded\", { timeout: SCRAPE_TIMEOUT_MS });\n await assertSessionValid(page);\n\n // Step 3: Handle any prompts on checkout page\n await this.dismissSubscribeAndSave(page);\n await this.dismissInsurancePrompt(page);\n\n // Step 4: Parse checkout page for errors\n const checkoutHtml = await page.content();\n const checkoutResult = parseCheckoutPage(checkoutHtml);\n\n if (checkoutResult.error) {\n const err = checkoutResult.error;\n let errorMessage = err.message;\n if (err.type === \"out_of_stock\" && err.affectedItems && err.affectedItems.length > 0) {\n errorMessage += ` Affected items: ${err.affectedItems.join(\", \")}`;\n }\n return {\n success: false,\n orderId: null,\n message: errorMessage,\n orderTotal: null,\n };\n }\n\n if (!checkoutResult.hasPlaceOrderButton) {\n log(\"No place order button found - checkout may require additional action\");\n return {\n success: false,\n orderId: null,\n message:\n \"Checkout page is not ready. You may need to select an address or payment method on Amazon directly.\",\n orderTotal: null,\n };\n }\n\n // Log order summary\n if (checkoutResult.summary) {\n log(\n `Order summary: ${checkoutResult.summary.items.length} items, total ${checkoutResult.summary.total}`,\n );\n }\n\n // Step 5: Click \"Place your order\"\n log(\"Placing order\");\n await throttleNavigation();\n\n try {\n const placeOrderBtn = page.locator(\n 'input[name=\"placeYourOrder1\"], #submitOrderButtonId input, [name*=\"placeOrder\"]',\n );\n await placeOrderBtn.first().click({ timeout: 5000 });\n await randomDelay(2000, 4000);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ScrapingError(`Could not find or click place order button: ${message}`, {\n cause: error,\n });\n }\n\n // Wait for confirmation page\n await page.waitForLoadState(\"domcontentloaded\", { timeout: SCRAPE_TIMEOUT_MS });\n\n // Step 6: Parse order confirmation\n const confirmationHtml = await page.content();\n const result = parseOrderConfirmation(confirmationHtml);\n\n if (result.success) {\n log(`Order placed successfully! Order ID: ${result.orderId}`);\n } else {\n log(`Order placement failed: ${result.message}`);\n }\n\n return result;\n }\n}\n","import type { AmazonProvider } from \"./types.js\";\nimport { PlaywrightProvider } from \"./playwright/index.js\";\n\nconst SUPPORTED_PROVIDERS = [\"playwright\"] as const;\ntype ProviderName = (typeof SUPPORTED_PROVIDERS)[number];\n\nfunction log(message: string): void {\n console.error(`[provider] ${message}`);\n}\n\nexport function createProvider(): AmazonProvider {\n const providerName = (process.env.AMAZON_MCP_PROVIDER ?? \"playwright\") as string;\n\n if (!SUPPORTED_PROVIDERS.includes(providerName as ProviderName)) {\n throw new Error(\n `Unsupported provider: \"${providerName}\". Supported providers: ${SUPPORTED_PROVIDERS.join(\", \")}`,\n );\n }\n\n const serpApiKey = process.env.SERPAPI_API_KEY;\n log(`Creating provider: ${providerName}`);\n log(`SerpAPI fallback: ${serpApiKey ? \"configured\" : \"not configured\"}`);\n\n switch (providerName as ProviderName) {\n case \"playwright\":\n return new PlaywrightProvider(serpApiKey);\n }\n}\n"],"mappings":"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","names":["server","provider","z","server","provider","z","z","server","provider","z","z","server","provider","z","z","server","provider","z","z","server","provider","z","z","resolve","log","logger","log","resolve","server","z","provider","server","z","logger","log","parsed","raw","log","parsePrice","mkdirSync","join","join","mkdirSync","logger","resolve","resolve","logger","log","limit","products","result","cart","log"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "amazon-personal-shopping-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for Amazon shopping via AI assistants",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"amazon-personal-shopping-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=20"
|
|
12
|
+
},
|
|
13
|
+
"author": "Phil Patterson",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/wiseyoda/amazon-shopping-mcp.git"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/wiseyoda/amazon-shopping-mcp#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/wiseyoda/amazon-shopping-mcp/issues"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "eslint src/",
|
|
31
|
+
"format": "prettier --write .",
|
|
32
|
+
"format:check": "prettier --check .",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"dev": "tsx src/index.ts"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"mcp",
|
|
38
|
+
"amazon",
|
|
39
|
+
"shopping",
|
|
40
|
+
"ai",
|
|
41
|
+
"model-context-protocol"
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
46
|
+
"cheerio": "^1.2.0",
|
|
47
|
+
"dotenv": "^17.2.3",
|
|
48
|
+
"playwright": "^1.58.1",
|
|
49
|
+
"serpapi": "^2.2.1",
|
|
50
|
+
"zod": "^3.24.2"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@eslint/js": "^9.18.0",
|
|
54
|
+
"@types/node": "^22.12.0",
|
|
55
|
+
"eslint": "^9.18.0",
|
|
56
|
+
"eslint-config-prettier": "^10.0.1",
|
|
57
|
+
"prettier": "^3.4.2",
|
|
58
|
+
"tsup": "^8.3.6",
|
|
59
|
+
"tsx": "^4.19.2",
|
|
60
|
+
"typescript": "~5.7.3",
|
|
61
|
+
"typescript-eslint": "^8.21.0",
|
|
62
|
+
"vitest": "^3.0.4"
|
|
63
|
+
}
|
|
64
|
+
}
|