import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; import { handleMcpRequest } from "../src/protocol/handler"; import { tools } from "../src/protocol/tools"; const originalFetch = global.fetch; describe("MCP protocol cookie inputs", () => { beforeEach(() => { global.fetch = mock(() => Promise.resolve(new Response(JSON.stringify([]), { status: 200 })), ) as unknown as typeof fetch; }); afterEach(() => { global.fetch = originalFetch; }); test("search tools should not expose Facebook or eBay cookie inputs", () => { const searchFacebookTool = tools.find( (tool) => tool.name === "search_facebook", ); const searchEbayTool = tools.find((tool) => tool.name === "search_ebay"); expect(searchFacebookTool?.inputSchema.properties).not.toHaveProperty( "cookiesSource", ); expect(searchEbayTool?.inputSchema.properties).not.toHaveProperty( "cookies", ); }); test("search_facebook should not forward cookies query parameters", async () => { await handleMcpRequest( new Request("http://localhost", { method: "POST", body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "search_facebook", arguments: { query: "laptop", cookiesSource: "c_user=1", }, }, }), }), ); const calledUrl = (global.fetch as unknown as ReturnType).mock .calls[0]?.[0]; expect(String(calledUrl)).toContain("/facebook?q=laptop"); expect(String(calledUrl)).not.toContain("cookies="); }); }); describe("MCP protocol unstableFilter", () => { beforeEach(() => { global.fetch = mock(() => Promise.resolve(new Response(JSON.stringify([]), { status: 200 })), ) as unknown as typeof fetch; }); afterEach(() => { global.fetch = originalFetch; }); test("all search tools should document the unstableFilter property", () => { const toolNames = ["search_kijiji", "search_facebook", "search_ebay"]; for (const toolName of toolNames) { const tool = tools.find((t) => t.name === toolName); expect(tool).toBeDefined(); expect(tool?.inputSchema.properties).toHaveProperty("unstableFilter"); const prop = tool?.inputSchema.properties.unstableFilter as { type: string; description: string; }; expect(prop.type).toBe("boolean"); expect(prop.description).toContain("optional"); expect(prop.description).toContain("20%"); expect(prop.description).toContain("median"); expect(prop.description).toContain("unstableResults"); } }); test("handler should forward unstableFilter=true for search_kijiji", async () => { await handleMcpRequest( new Request("http://localhost", { method: "POST", body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "search_kijiji", arguments: { query: "laptop", unstableFilter: true, }, }, }), }), ); const calledUrl = (global.fetch as unknown as ReturnType).mock .calls[0]?.[0]; expect(String(calledUrl)).toContain("unstableFilter=true"); }); test("handler should forward unstableFilter=true for search_facebook", async () => { await handleMcpRequest( new Request("http://localhost", { method: "POST", body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "search_facebook", arguments: { query: "laptop", unstableFilter: true, }, }, }), }), ); const calledUrl = (global.fetch as unknown as ReturnType).mock .calls[0]?.[0]; expect(String(calledUrl)).toContain("unstableFilter=true"); }); test("handler should forward unstableFilter=true for search_ebay", async () => { await handleMcpRequest( new Request("http://localhost", { method: "POST", body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "search_ebay", arguments: { query: "laptop", unstableFilter: true, }, }, }), }), ); const calledUrl = (global.fetch as unknown as ReturnType).mock .calls[0]?.[0]; expect(String(calledUrl)).toContain("unstableFilter=true"); }); });