returncheck-mcp
Can this specific product actually be returned?
An MCP server that answers that question with a verified verdict and the merchant's
exact policy clause, quoted verbatim — plus the source URL, the return window and a
confidence score.
It answers the version of the question that a per-domain rating cannot: the same product
page can be 90 days or 30 depending on who the seller is, a year or 90 days depending on
whether you are a member, 365 days or 180 depending on whether the box is open.
It never invents. If it cannot verify a clause on the page, it returns UNKNOWN, and
UNKNOWN is free.
npx returncheck-mcp
Coverage, measured — including where it fails
On 28 August 2026 we took 50 real US retailers, one live product page each, chosen
before the run and frozen. We reached the policy for 17 of 50.
That number is on the tin because you should know it before you build on this. The 33
that failed are not hard pages: they are stores that serve no policy text to anything
that isn't a real browser — no JavaScript, no cookies, program-shaped fingerprint.
We also tested the obvious idea — that fetching from a developer's own machine, on a
residential IP, would get past that. It doesn't. Same 50 stores, same code, run from
a residential connection: 9 reached instead of 17, and 20 blocked instead of 15. One of
the 15 blocks broke; six new ones appeared. We are publishing the result that contradicts
us because the alternative is selling you a story.
(Honest caveat: that run was from Europe against US stores, so some of it may be
geography rather than fingerprinting. That doesn't rescue the idea — it just means the
idea is still unmeasured in its favour, so we don't claim it.)
So the one thing that reliably fixes coverage is you. If you already have the page —
from a browser session, a headless browser, a crawler, an extension, anything — pass it
as page_text and the store's wall is irrelevant. Every question that arrives with the
page attached gets answered.
When you don't pass one, this package tries a local fetch and sends it only if the text
actually talks about returns. A JavaScript shell is not sent, and neither is a long
product page with nothing about returning in it. Both cases would take away something
the service does better on its own: find and read the store's returns page.
You pass page_text | Best results. No fetch happens |
| Local fetch finds real policy text | Sent, saves the service a round trip |
| Shell, or text with no policy in it | Not sent — the service's own discovery wins |
Install
Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"returncheck": {
"command": "npx",
"args": ["-y", "returncheck-mcp"]
}
}
}
Anything else that speaks MCP over stdio — run npx -y returncheck-mcp.
No API key needed to start: there is a keyless free trial. For more, sign up:
curl -X POST https://returncheck.m-angelmartinez-fer.workers.dev/v1/signup \
-H 'content-type: application/json' -d '{"email":"you@example.com"}'
Then set RETURNCHECK_API_KEY. It travels in an Authorization header and is never
written to disk or logged.
The tool
check_return
product_url | required | the product page URL |
buyer_country | required | ISO 3166-1 alpha-2, e.g. US |
page_text / page_html | optional | the page, if you already have it — otherwise we fetch it |
item_condition | optional | unopened · opened · used · defective |
reason | optional | changed_mind · defective · wrong_size_or_model · arrived_late · other |
purchase_date, delivery_date | optional | YYYY-MM-DD. Delivery date gives you a deadline |
merchant, seller_name | optional | seller_name matters on marketplaces |
membership, purchase_channel | optional | some policies differ by tier or channel |
What comes back
{
"verdict": "YES",
"returnable": true,
"confidence": 0.95,
"policy": {
"return_category": "FiniteReturnWindow",
"merchant_return_days": 30,
"window_basis": "delivery_date",
"refund_type": "FullRefund"
},
"evidence": {
"source_url": "https://store.example/p/shoe",
"exact_clause": "Eligible items may be returned within 30 days of delivery for a full refund to the original payment method.",
"verified_on": "2026-08-28"
},
"missing_input": ["delivery_date"],
"missing_input_hint": "The policy counts its window from the delivery date. Send delivery_date (YYYY-MM-DD) to get a deadline."
}
Four verdicts, and the fourth is the point:
YES — returnable, and every condition the clause names is covered by what you told us.
YES_WITH_CONDITIONS — returnable, but at least one condition we cannot assume is met.
NO — the policy excludes it, and the clause proving that is quoted.
UNKNOWN — we could not verify it. Free. No guess is offered in its place.
When something is missing that would change the answer, missing_input says what, and
missing_input_hint says why it matters.
Configuration
RETURNCHECK_API_KEY | — | optional; without it you get the free trial |
RETURNCHECK_URL | the hosted service | point it elsewhere if you self-host |
RETURNCHECK_FETCH_LOCALLY | true | false to let the service fetch instead |
RETURNCHECK_TIMEOUT_MS | 8000 | the local fetch budget |
Pricing
$0.02 per verified answer. UNKNOWN is free. Keyless free trial, no signup.
That last part is a rule, not a promotion: we do not charge for not knowing.
No dependencies
Not one. Node 18+ already has fetch, and a package that installs on your machine and
talks to a paid API has no business dragging in a tree nobody will audit. The whole
thing reads in ten minutes.
Why you would use this at all
You can already read a web page. What you cannot do is prove later what it said.
Every answer carries the clause verbatim, the URL it came from, and the date it was
verified. That turns an opinion into a receipt — which matters on the day a buyer says
the policy said something else.
MIT · returncheck.m-angelmartinez-fer.workers.dev
· source