Findcheap MCP server
The Findcheap MCP server lets an AI assistant find where a product is sold for less. It offers the capabilities of the Findcheap API as three tools that any MCP client (Claude, Claude Code, Cursor and others) can call in a conversation:
- find_cheaper - takes a product page URL as input and searches the internet to find where the product is available for a lower price.
- read_product_page - takes a product page URL as input and returns structured product data from the page.
- resolve_listing - a utility tool that turns a result’s
resolve_idinto the merchant’s link and name.
https://mcp.findcheap.ai/mcpEach tool answers exactly what the corresponding API endpoint answers. This page covers how to connect and what each tool takes; every field of the answers is documented in the API reference.
Connect
Add the server to your client with your Findcheap API key (the same key the API uses; request one on the developers page). The key travels in the Authorization header of every request.
claude mcp add --transport http findcheap https://mcp.findcheap.ai/mcp \
--header "Authorization: Bearer fc_live_..."Any other MCP client connects the same way: the server URL above, Streamable HTTP, and the Authorization header.
Authentication
Every request carries your API key:
Authorization: Bearer fc_live_...A request without a valid key is answered 401 before anything else happens, which a client reports as a failed connection. A key is valid for the API and the MCP server alike, and both draw on the same rate limits.
In Claude.ai, add the server as a custom connector (Customize, then Connectors, add by URL) with Authentication set to “No sign-in” and one request header, authorization with the value Bearer fc_live_.... The request-headers option is in beta, so not every organization has it yet. OAuth sign-in is not yet supported.
find_cheaper
Takes a product page URL as input and searches the internet for where the product is available for a lower price. It is the Search endpoint as a tool: the agent reads the product page, then searches the marketplaces of the shopper’s market. Results are sorted into two arrays, each containing up to 10 results:
same_product- the same brand and model as the original product. Sorted by cheapest first.similar_products- products that don’t match the same brand and model of the original product, but would be considered acceptable equivalents. Sorted by cheapest first.
It has a maximum budget of 90 seconds, but usually completes much sooner. While it runs, the server sends progress notifications (reading the page, searching, comparing) to clients that display them.
Two ways it gets used:
- User-initiated. A shopper pastes a product link into their assistant and asks for it cheaper; the assistant calls
find_cheaperand answers with the retailers, prices and links. - Agent-initiated. An agent working on a task the user gave it, “buy me a soccer ball”, finds a candidate ball on Amazon and calls
find_cheaperon that page to see whether the same ball, or an equivalent, is sold for less elsewhere before recommending or buying it.
In both, there is nothing to build: the assistant decides when to call the tool from its description.
Parameters
The product page’s address (https), as the shopper sees it.
The shopper’s market, the country they are buying in (see Markets). If omitted, the market is inferred from the URL; otherwise, it defaults to US.
Which marketplaces to search. Only marketplaces available in the shopper’s market count. If omitted, the agent chooses for the product. Accepted values: "amazon", "walmart", "ebay", "aliexpress", "shein", "flipkart", "other_sites".
Defaults to "new". If set to "used", the agent searches for where the product can be bought secondhand. This search mode is not available in India, and is refused for grocery and consumable products.
Result
The Search endpoint’s answer, as JSON: product, same_product, similar_products, page_is_cheapest and product_name. Every field, and the structure of a card, is documented under Search in the API reference. A card whose url is null carries a resolve_id for resolve_listing.
Example
The call the assistant makes, and the answer trimmed to one card per list:
find_cheaper({ "url": "https://www.jlab.com/products/jbuds-lux-anc-headphones" }){
"product": {
"title": "JBuds Lux ANC Headphones",
"price": 79.99,
"currency": "USD",
"brand": "JLab",
"url": "https://www.jlab.com/products/jbuds-lux-anc-headphones",
"market": "US",
"image": "https://www.jlab.com/cdn/shop/files/jbuds-lux-anc.jpg",
"in_stock": true
},
"product_name": "JLab JBuds Lux ANC",
"page_is_cheapest": false,
"same_product": [
{
"title": "JLab JBuds Lux ANC Wireless Headphones",
"price": 67.50,
"currency": "USD",
"retailer": "Amazon",
"url": "https://www.amazon.com/dp/B0FWTKRMFV",
"resolve_id": null,
"image": "https://m.media-amazon.com/images/I/61a.jpg",
"over_page_price": false,
"rating": 4.4,
"coupon": null,
"promo_code": null,
"price_before_discount": null,
"discount_type": null,
"discount_value": null
}
],
"similar_products": [
{
"title": "Soundcore Q20i Hybrid ANC Headphones",
"price": 49.99,
"currency": "USD",
"retailer": "Walmart",
"url": null,
"resolve_id": "7c1f0e2b4d9a4f3e8b6a2c5d9e1f0a3b",
"image": "https://i5.walmartimages.com/seo/q20i.jpg",
"rating": 4.5,
"coupon": null,
"promo_code": null,
"price_before_discount": null,
"discount_type": null,
"discount_value": null
}
]
}read_product_page
Takes a product page URL as input and returns structured product data from the page, without searching. It is the Extract endpoint as a tool. It answers within 30 seconds, and has a median response time of 4 seconds.
Two ways it gets used:
- User-initiated. A shopper pastes a product link into their assistant and asks what it sells, what it costs or whether it is in stock; the assistant calls
read_product_pageand answers from the page’s data. - Agent-initiated. An agent working on a task the user gave it, “compare these three monitors”, calls
read_product_pageon each page to get the title, price, brand and stock it needs before comparing them.
In both, it answers what the page says and nothing more; find_cheaper is the tool that searches.
Parameters
The product page’s address (https).
The market to read the page from (see Markets). If omitted, the market is inferred from the URL; otherwise, it defaults to US.
Result
The Extract endpoint’s answer: is_product_page, title, image, price, currency, brand, in_stock, url, market and reason. Every field is documented under Extract in the API reference.
Example
read_product_page({ "url": "https://www.jlab.com/products/jbuds-lux-anc-headphones" }){
"is_product_page": true,
"url": "https://www.jlab.com/products/jbuds-lux-anc-headphones",
"market": "US",
"title": "JBuds Lux ANC Headphones",
"image": "https://www.jlab.com/cdn/shop/files/jbuds-lux-anc.jpg",
"price": 79.99,
"currency": "USD",
"brand": "JLab",
"in_stock": true,
"reason": null
}resolve_listing
For some results, find_cheaper only returns top-level data, to maximize search efficiency. These results carry a resolve_id instead of a url. Calling resolve_listing with a resolve_id returns a direct link to the corresponding product on the merchant’s website and the merchant’s name. It is the Resolve endpoint as a tool.
An id is valid for up to two hours after the search that produced it. In rare cases, it may expire sooner, so it is advised to resolve any desired ids shortly after the search has completed.
Parameters
The card’s resolve_id.
Result
| Field | Type | Meaning |
|---|---|---|
| resolved | boolean | true when url holds the retailer's link. |
| url | string | null | The product's direct link on the merchant's website, tracking parameters stripped. null when not resolved. |
| retailer | string | null | The merchant's name, e.g. "B&H Photo". null when not resolved. |
An id that is unknown, expired, or could not be resolved answers { "resolved": false, "url": null, "retailer": null }; it is never an error.
Example
resolve_listing({ "resolve_id": "7c1f0e2b4d9a4f3e8b6a2c5d9e1f0a3b" }){ "resolved": true, "url": "https://www.walmart.com/ip/Soundcore-Q20i/...", "retailer": "Walmart" }Errors
A tool call that cannot be served returns a tool error the assistant can read: the error’s type, a colon, and a sentence saying what happened, e.g. not_searchable: The address is not a readable product page (not_a_product_page). The types are the API’s (see Errors in the API reference):
| Type | Tool | When |
|---|---|---|
| invalid_url | all | The url is not one https product page address. |
| unknown_market | all | The market is not one the agent serves. |
| invalid_request | all | A parameter has the wrong shape, e.g. an unknown marketplace name. |
| not_searchable | find_cheaper | The page is not a readable product page; the message says why. |
| refused | find_cheaper | A used-condition search for a grocery or consumable product, or for a product with no determinable brand. |
| unreachable | find_cheaper, read_product_page | The page could not be fetched right now; try again later. |
| timeout | find_cheaper, read_product_page | The page was reached but could not be read within 30 seconds, or the search did not finish within 90 seconds; try again. |
| rate_limited | all | The key is over one of its windows; the message says how long to wait. |
| unauthorized | all | The key is missing or wrong (also a 401 when the client connects). |
Rate limits
The rate limits for each plan are listed on the developers page. A key has one budget: a find_cheaper call counts as a Search request, read_product_page as an Extract request and resolve_listing as a Resolve request, whether made through the MCP server or the API.