diff --git a/packages/api-server/src/routes/ebay.ts b/packages/api-server/src/routes/ebay.ts index 7723308..720d9b6 100644 --- a/packages/api-server/src/routes/ebay.ts +++ b/packages/api-server/src/routes/ebay.ts @@ -1,8 +1,8 @@ import { fetchEbayItems } from "@marketplace-scrapers/core"; /** - * GET /api/ebay?q={query}&minPrice={minPrice}&maxPrice={maxPrice}&strictMode={strictMode}&exclusions={exclusions}&keywords={keywords} - * Search eBay for listings + * GET /api/ebay?q={query}&minPrice={minPrice}&maxPrice={maxPrice}&strictMode={strictMode}&exclusions={exclusions}&keywords={keywords}&buyItNowOnly={buyItNowOnly}&canadaOnly={canadaOnly} + * Search eBay for listings (default: Buy It Now only, Canada only) */ export async function ebayRoute(req: Request): Promise { const reqUrl = new URL(req.url); @@ -26,6 +26,8 @@ export async function ebayRoute(req: Request): Promise { ? parseInt(reqUrl.searchParams.get("maxPrice")!) : undefined; const strictMode = reqUrl.searchParams.get("strictMode") === "true"; + const buyItNowOnly = reqUrl.searchParams.get("buyItNowOnly") !== "false"; + const canadaOnly = reqUrl.searchParams.get("canadaOnly") !== "false"; const exclusionsParam = reqUrl.searchParams.get("exclusions"); const exclusions = exclusionsParam ? exclusionsParam.split(",").map(s => s.trim()) : []; const keywordsParam = reqUrl.searchParams.get("keywords"); @@ -38,6 +40,8 @@ export async function ebayRoute(req: Request): Promise { strictMode, exclusions, keywords, + buyItNowOnly, + canadaOnly, }); if (!items || items.length === 0) return Response.json( diff --git a/packages/core/src/scrapers/ebay.ts b/packages/core/src/scrapers/ebay.ts index 9eb8e9e..fc0c252 100644 --- a/packages/core/src/scrapers/ebay.ts +++ b/packages/core/src/scrapers/ebay.ts @@ -270,6 +270,8 @@ export default async function fetchEbayItems( strictMode?: boolean; exclusions?: string[]; keywords?: string[]; + buyItNowOnly?: boolean; + canadaOnly?: boolean; } = {}, ) { const { @@ -277,11 +279,27 @@ export default async function fetchEbayItems( maxPrice = Number.MAX_SAFE_INTEGER, strictMode = false, exclusions = [], - keywords = [SEARCH_QUERY] // Default to search query if no keywords provided + keywords = [SEARCH_QUERY], // Default to search query if no keywords provided + buyItNowOnly = true, + canadaOnly = true, } = opts; - // Build eBay search URL - use Canadian site and tracking parameters like real browser - const searchUrl = `https://www.ebay.ca/sch/i.html?_nkw=${encodeURIComponent(SEARCH_QUERY)}^&_sacat=0^&_from=R40^&_trksid=p4432023.m570.l1313`; + // Build eBay search URL - use Canadian site, Buy It Now filter, and Canada-only preference + const urlParams = new URLSearchParams({ + _nkw: SEARCH_QUERY, + _sacat: "0", + _from: "R40", + }); + + if (buyItNowOnly) { + urlParams.set("LH_BIN", "1"); + } + + if (canadaOnly) { + urlParams.set("LH_PrefLoc", "1"); + } + + const searchUrl = `https://www.ebay.ca/sch/i.html?${urlParams.toString()}`; const DELAY_MS = Math.max(1, Math.floor(1000 / REQUESTS_PER_SECOND)); diff --git a/packages/mcp-server/src/protocol/handler.ts b/packages/mcp-server/src/protocol/handler.ts index 910f818..38e60f7 100644 --- a/packages/mcp-server/src/protocol/handler.ts +++ b/packages/mcp-server/src/protocol/handler.ts @@ -131,6 +131,8 @@ export async function handleMcpRequest(req: Request): Promise { strictMode: args.strictMode || false, exclusions: args.exclusions || [], keywords: args.keywords || [query], + buyItNowOnly: args.buyItNowOnly !== false, + canadaOnly: args.canadaOnly !== false, }); result = items || []; } else { diff --git a/packages/mcp-server/src/protocol/tools.ts b/packages/mcp-server/src/protocol/tools.ts index b0fc96e..0e2947c 100644 --- a/packages/mcp-server/src/protocol/tools.ts +++ b/packages/mcp-server/src/protocol/tools.ts @@ -52,7 +52,7 @@ export const tools = [ }, { name: "search_ebay", - description: "Search eBay for listings matching a query", + description: "Search eBay for listings matching a query (default: Buy It Now only, Canada only)", inputSchema: { type: "object", properties: { @@ -83,6 +83,16 @@ export const tools = [ items: { type: "string" }, description: "Keywords to include in search", }, + buyItNowOnly: { + type: "boolean", + description: "Include only Buy It Now listings (exclude auctions)", + default: true, + }, + canadaOnly: { + type: "boolean", + description: "Include only Canadian sellers/listings", + default: true, + }, maxItems: { type: "number", description: "Maximum number of items to return",