diff --git a/packages/api-server/src/routes/helpers.ts b/packages/api-server/src/routes/helpers.ts index 3b13092..19b9d95 100644 --- a/packages/api-server/src/routes/helpers.ts +++ b/packages/api-server/src/routes/helpers.ts @@ -31,9 +31,9 @@ export function parseNonNegativeIntegerParam( return value; } -export function emptySearchResponse(): Response { - return Response.json( - { message: "Search didn't return any results!" }, - { status: 404 }, - ); +export function emptySearchResponse(hint?: string): Response { + const message = hint + ? `Search didn't return any results! ${hint}` + : "Search didn't return any results!"; + return Response.json({ message }, { status: 404 }); } diff --git a/packages/api-server/src/routes/kijiji.ts b/packages/api-server/src/routes/kijiji.ts index 0ccfede..ad6affb 100644 --- a/packages/api-server/src/routes/kijiji.ts +++ b/packages/api-server/src/routes/kijiji.ts @@ -73,7 +73,10 @@ export async function kijijiRoute(req: Request): Promise { { hideUnstableResults: true }, ); if (items.results.length === 0 && items.unstableResults.length === 0) { - return emptySearchResponse(); + return emptySearchResponse( + `Kijiji matches ALL words in the query against listing titles. ` + + `Try a shorter or more common query (e.g. "macbook air m1" instead of "macbook air m1 apple silicon").`, + ); } return Response.json(items, { status: 200 }); } @@ -86,7 +89,10 @@ export async function kijijiRoute(req: Request): Promise { {}, ); if (!items || items.length === 0) { - return emptySearchResponse(); + return emptySearchResponse( + `Kijiji matches ALL words in the query against listing titles. ` + + `Try a shorter or more common query (e.g. "macbook air m1" instead of "macbook air m1 apple silicon").`, + ); } return Response.json(items, { status: 200 }); } catch (error) { diff --git a/packages/api-server/test/routes.test.ts b/packages/api-server/test/routes.test.ts index 64909ad..a20ab43 100644 --- a/packages/api-server/test/routes.test.ts +++ b/packages/api-server/test/routes.test.ts @@ -394,7 +394,8 @@ describe("API routes", () => { expect(response.status).toBe(404); const body = await response.json(); - expect(body.message).toBe("Search didn't return any results!"); + expect(body.message).toStartWith("Search didn't return any results!"); + expect(body.message).toContain("Kijiji matches ALL words"); }); test("ebayRoute forwards maxItems to core in default mode", async () => { diff --git a/packages/core/src/scrapers/kijiji.ts b/packages/core/src/scrapers/kijiji.ts index 54015db..8677b18 100644 --- a/packages/core/src/scrapers/kijiji.ts +++ b/packages/core/src/scrapers/kijiji.ts @@ -893,7 +893,17 @@ export default async function fetchKijijiItems( const searchResults = parseSearch(searchHtml, BASE_URL); if (searchResults.length === 0) { - logger.log(`No more results found on page ${page}. Stopping pagination.`); + if (page === 1) { + logger.log( + `No results found on page 1. The search URL was: ${searchUrl}\n` + + `Tip: Kijiji matches ALL words in the query against listing titles. ` + + `Try a shorter or more common query (e.g. "macbook air m1" instead of "macbook air m1 apple silicon").`, + ); + } else { + logger.log( + `No more results found on page ${page}. Stopping pagination.`, + ); + } break; } diff --git a/packages/mcp-server/src/protocol/handler.ts b/packages/mcp-server/src/protocol/handler.ts index 80150e4..24a212c 100644 --- a/packages/mcp-server/src/protocol/handler.ts +++ b/packages/mcp-server/src/protocol/handler.ts @@ -138,7 +138,14 @@ export async function handleMcpRequest(req: Request): Promise { logger.error( `[MCP] Kijiji API error ${response.status}: ${errorText}`, ); - throw new Error(`API returned ${response.status}: ${errorText}`); + let errorMessage = `API returned ${response.status}: ${errorText}`; + try { + const errorJson = JSON.parse(errorText) as { message?: string }; + if (errorJson.message) errorMessage = errorJson.message; + } catch { + // not JSON — use raw text + } + throw new Error(errorMessage); } result = await response.json(); logger.log( diff --git a/packages/mcp-server/src/protocol/tools.ts b/packages/mcp-server/src/protocol/tools.ts index ababca4..701a67e 100644 --- a/packages/mcp-server/src/protocol/tools.ts +++ b/packages/mcp-server/src/protocol/tools.ts @@ -11,7 +11,11 @@ export const tools = [ properties: { query: { type: "string", - description: "Search query for Kijiji listings", + description: + "Search query for Kijiji listings. " + + "Kijiji requires ALL words to appear in the listing title — keep queries short and use terms sellers actually write. " + + "Avoid marketing/brand phrases sellers don't use (e.g. use 'macbook air m1' not 'macbook air m1 apple silicon'). " + + "If the search returns no results, try a shorter or more common query.", }, location: { type: "string",