Recall Kitchen's MCP server lets AI agents look up government-published product, food, vehicle and drug recalls. Most lookups are free; past the free quota (and for photo search) an agent can pay per call with x402 in USDC on Base. Here's exactly how.
(Disclosure: I build Recall Kitchen.)
Docs: https://recallkitchen.com/docs?utm_source=devto&utm_campaign=x402_howto
You don't need an account to keep using the server. A few anonymous searches per IP are free (5 an hour, 15 a day), and photo search is never in that free quota. After the quota, an x402-capable client can pay per call: $0.025 in USDC on Base. When a call needs payment, the server returns a normal JSON-RPC result whose content is an x402 "Payment Required" challenge (HTTP 200, isError: true), not a bare HTTP 402. Your client pays it and retries. The price and pay-to address are published at https://app.recallkitchen.com/.well-known/x402. x402 covers search and photo search only. Account tools like watches and inventory need a free API key instead. The full rules are in the docs and the API Terms.
POST https://app.recallkitchen.com/mcp
https://app.recallkitchen.com/.well-known/x402
| Tool | Free anonymous quota | x402 / API key |
|---|---|---|
search_product_recalls (and other non-photo search tools) |
Yes — a few calls per IP (docs/API terms: 5/hour, 15/day) | After the IP quota, pay with x402 or send an API key |
search_product_recalls_from_image (photo, beta) |
No — never in the free anonymous quota | Always needs an API key or x402 |
Account tools (watches, inventory, notifications, key management) do not accept x402; use a free API key from signup / Integrations.
For MCP tool calls that require payment, the server answers HTTP 200 with a JSON-RPC tools/call result whose content is an x402 Payment Required payload (isError: true). That HTTP 200 + JSON-RPC payment challenge is correct for this MCP integration — clients should not expect a bare HTTP 402 on the MCP POST for tool payment.
Live example (image search, unpaid), truncated:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"isError": true,
"structuredContent": {
"error": "Payment Required",
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "25000",
"payTo": "0x8E2d8e2850Baf623A8A886DE7c80CDfB83a5cfa3",
"maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" }
}],
"resource": {
"url": "mcp://tool/search_product_recalls_from_image",
"description": "Photo (beta): identify products in an image URL, data URI, or MCP image content",
"mimeType": "application/json"
}
}
}
}
amount is USDC atomic units (6 decimals): "25000" = $0.025. The well-known document publishes the same price as decimal "0.025".
From /.well-known/x402 and the live challenge (they match):
| Field | Value |
|---|---|
| Network | Base mainnet — eip155:8453 |
| Asset | USDC on Base — 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Currency | USDC |
| Price | $0.025 per call (unless a live challenge states otherwise) |
| Pay to | 0x8E2d8e2850Baf623A8A886DE7c80CDfB83a5cfa3 |
| Scheme | exact |
| x402 version | 2 |
Do not invent other prices; always prefer the live accepts[] on the challenge.
https://app.recallkitchen.com/mcp (streamable HTTP / JSON-RPC). Prefer a free API key (X-API-Key: rk_... for Grok, or Authorization: Bearer rk_... for Claude/Cursor) when you have one — that skips x402 for search tools.search_product_recalls after the free IP quota, or search_product_recalls_from_image any time without a key).accepts[0] (network, asset, amount, payTo).X402_EVM_PRIVATE_KEY and registers scheme eip155:8453), sign and settle the payTo for amount atomic units on Base.
export X402_EVM_PRIVATE_KEY=0x... # Base wallet funded with USDC (+ gas)
cd examples/go
go run ./search_product_recalls -query spinach -location Iowa
Or set RK_API_KEY / RECALL_KITCHEN_API_KEY instead of paying per call.
GET https://app.recallkitchen.com/.well-known/x402`` tools/call → /mcp (HTTP 200 + Payment Required JSON-RPC)