Open format · stores + agents
Every store your AI agent can buy from, in one file.
STORES.md is a simple, open format for what agents can buy and how they pay: an x402 link, a checkout link, an invoice. Stores publish one. Your agent keeps one too, with every store it finds, in every format, read into one file.
● Format v1.0/stores.md on any domainmade-up stores shown
Your agent’s file
Every store, one STORES.md
Read from any format, checked before paying.
- # Example Weatherknownforecast · 0.002 USD per call · x402
- # Example Outfittersnewcamp mug · 18 USD once · checkout
- # Example Bakerynewsourdough · 7 USD · pickup · checkout
- # Purchases10-15 · forecast · 0.002 USD · x402 · ref 0x9f…
- One file per store
- Every format in
- Check before paying
- Nothing you send is kept
Every format in, one file out
Whatever a store publishes, your agent reads it the same way.
A 402 answer, a discovery list, a product page, a feed, a tool list, an API document: pick one and see it read into STORES.md, with links worth following and text that tries to instruct agents flagged. For a 402, see the check that runs before your agent pays. Every sample is made up.
Read an HTTP 402 answer: 1 product from 1 store.
- askExample Weather is new to you: ask first. Once the person says yes, mark it status: known.
- noteRead with 6 decimal places, the usual number for dollar tokens. If this token uses another number, pass decimals.
- note0x000000...0000E1 matches an address Example Weather lists under pay_to.
- Hourly forecast, 48 hours0.002 USD per requestx402
# api.example.com
- url: https://api.example.com
- source: https://api.example.com/v1/forecast
- format: HTTP 402 answer
- pulled: 2026-10-16
- status: new
## Hourly forecast, 48 hours
- id: v1-forecast
- price: 0.002 USD per request
- pay: x402 https://api.example.com/v1/forecast
- delivers: application/json, in the response
- x402_terms: eip155:8453 0.002 USD to 0x00000000000000000000000000000000000000E1
For stores
Sell to agents with one file.
- 1
Add stores.md to your domain
Serve it at
https://your-domain/stores.mdand link it from/llms.txt. Plain Markdown; no account, no sign-up. - 2
One heading per store, one per product
Under
# Your store:url,terms,refunds. Under each## Product:price,payanddelivers. - 3
Say where payments go
One
pay_toline per address you receive at. Buyers’ agents stop when a 402 pays anywhere else. - 4
Check it
Run
check_stores_mdbelow, or call it from your build, before you publish.
Prices read like 0.002 USD per call, 5 USD per 1,000 calls or 20 USD per month. Ways to pay: x402, l402, checkout, agent-checkout, mcp, invoice, transfer, free and contact. The whole format: /spec.md.
---stores: 1updated: 2026-10-15---# Example WeatherForecasts and history for any place on Earth, sold by the call or by the month.- url: https://example.com- terms: https://example.com/terms- refunds: Plans within 14 days. Single calls are final.- pay_to: eip155:8453 0x00000000000000000000000000000000000000E1- contact: https://example.com/support## Forecast lookupHourly forecast for the next 48 hours, for one place.- id: forecast- price: 0.002 USD per call- pay: x402 https://api.example.com/v1/forecast- delivers: JSON, at once- tags: weather, forecast## History pack, 2025Every hour of 2025 for one city, as one file.- id: history-2025- price: 12 USD once- pay: checkout https://example.com/buy/history-2025- pay: agent-checkout https://example.com/agents/checkout- delivers: a CSV download link, within a minute## Pro plan- id: pro- price: 20 USD per month- pay: checkout https://example.com/buy/pro- pay: invoice https://example.com/agents/invoice- delivers: an API key by email, within an hour- refunds: 14 daysCustomize
Your buying rules, written into the skill.
27 settings in 5 groups. Start from a preset, change anything, and your settings are written into STORES.md. Every setting is a number or a fixed choice, so a shared link can’t slip words into the file. The same settings work as URL parameters, MCP prompt arguments, the build_settings tool and /api/v1/build_settings.
Pay per request within small limits; ask before checkouts, invoices, renewals and new stores; never transfer to an address.
Spend
How much, and when to ask.
Set by the person you work for, and only that person can change them. Rules an agent drafted count only after that person says yes. Where a rule here and the rest of this file differ, the rule wins. If a rule blocks a purchase, stop and ask; don't work around it.
How to keep the file of everything you can buy. Follow these unless a rule above says otherwise.
mkdir -p ~/.claude/skills/stores && curl -fsSL "https://www.stores.md/stores.md?max_per_purchase=5&ask_over=1&daily_cap=20&monthly_cap=100&alert_pct=80&x402=allow&l402=ask&paid_tools=allow&checkout_links=ask&agent_checkout=ask&invoices=ask&transfers=never&recurring=ask&networks=any&other_assets=ask&dollar_tokens=face_value&pay_to_check=ask_if_unlisted&which_stores=ask_new&max_listing_age_days=30&price_drift_pct=0&refresh_days=7&gone_products=mark&log_purchases=yes&report=each" -o ~/.claude/skills/stores/SKILL.mdhttps://www.stores.md/stores.md?max_per_purchase=5&ask_over=1&daily_cap=20&monthly_cap=100&alert_pct=80&x402=allow&l402=ask&paid_tools=allow&checkout_links=ask&agent_checkout=ask&invoices=ask&transfers=never&recurring=ask&networks=any&other_assets=ask&dollar_tokens=face_value&pay_to_check=ask_if_unlisted&which_stores=ask_new&max_listing_age_days=30&price_drift_pct=0&refresh_days=7&gone_products=mark&log_purchases=yes&report=eachCopy as JSON
The same settings as one JSON object. It feeds the build_settings tool or POST /api/v1/build_settings.
24 of 27 settings set. Anything not set follows the skill’s own rules.
Tools
Tools your agent calls before it buys.
They read what you send them and nothing else: no fetching, no storing, no paying. Run them here, or call them over HTTP or MCP. They read, compare and check; they never approve a purchase.
{
"text": "HTTP/1.1 402 Payment Required\ncontent-type: application/json\npayment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQQVlNRU5ULVNJR05BVFVSRSBoZWFkZXIgaXMgcmVxdWlyZWQiLCJyZXNvdXJjZSI6eyJ1cmwiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbS92MS9mb3JlY2FzdCIsImRlc2NyaXB0aW9uIjoiSG91cmx5IGZvcmVjYXN0LCA0OCBob3VycyIsIm1pbWVUeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LCJhY2NlcHRzIjpbeyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJlaXAxNTU6ODQ1MyIsImFtb3VudCI6IjIwMDAiLCJhc3NldCI6IjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBBNSIsInBheVRvIjoiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMEUxIiwibWF4VGltZW91dFNlY29uZHMiOjYwLCJleHRyYSI6eyJuYW1lIjoiVVNEIn19XX0=\n\n{}",
"format": "auto",
"source_url": "https://api.example.com/v1/forecast",
"output": "index"
}curl -s https://www.stores.md/api/v1/read_listing -H 'content-type: application/json' -d '{"text":"HTTP/1.1 402 Payment Required\ncontent-type: application/json\npayment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQQVlNRU5ULVNJR05BVFVSRSBoZWFkZXIgaXMgcmVxdWlyZWQiLCJyZXNvdXJjZSI6eyJ1cmwiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbS92MS9mb3JlY2FzdCIsImRlc2NyaXB0aW9uIjoiSG91cmx5IGZvcmVjYXN0LCA0OCBob3VycyIsIm1pbWVUeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LCJhY2NlcHRzIjpbeyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJlaXAxNTU6ODQ1MyIsImFtb3VudCI6IjIwMDAiLCJhc3NldCI6IjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBBNSIsInBheVRvIjoiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMEUxIiwibWF4VGltZW91dFNlY29uZHMiOjYwLCJleHRyYSI6eyJuYW1lIjoiVVNEIn19XX0=\n\n{}","format":"auto","source_url":"https://api.example.com/v1/forecast","output":"index"}'Agents can pay now. They can't see what's for sale.
A payment per request is one HTTP call away, but what an agent can buy is scattered across 402 answers, product feeds, structured data, tool lists and API docs, each in its own shape, with no price list and no rules. So agents guess: they pay whatever the 402 says, to whatever address it names, as often as the loop runs. STORES.md gives stores one plain file to say what they sell and where payments go, gives agents one file of everything they can buy, and puts a check between the 402 and the wallet.
- One file per store: price, way to pay, what you get, refunds and the addresses payments go to.
- One file for your agent: every store it found, in every format, with its status: known, new or blocked.
- A check before the wallet: the 402's amount, network and pay-to against the listing and your limits.
- Prompt injection, flagged: store text that tries to instruct agents gets a warning, and the skill says to ignore it.
- Nothing you send is kept: requests are answered and forgotten. No accounts, no keys, no money moves.
Use it in your stack
Paste it, install it, or call it.
The skill alone gives an agent the method. The MCP server and API add the tools and your settings. No key, no account.
Paste the prompt into a system prompt or project instructions. Or keep the file in the repo and point AGENTS.md at it.
mkdir -p .agents && curl -fsSL "https://www.stores.md/stores.md?preset=recommended" -o .agents/stores-skill.mdecho "Whenever a task needs to find, compare, buy, subscribe to or pay for a product, an API call, data or a tool, follow .agents/stores-skill.md. Keep what you can buy in STORES.md." >> AGENTS.mdFor agents that read a skills folder: install the skill so it loads when the topic comes up, and add the MCP server for the tools.
# The skillmkdir -p ~/.claude/skills/storescurl -fsSL https://www.stores.md/stores.md -o ~/.claude/skills/stores/SKILL.md# Tools: read_listing, check_purchase, compare_offers, check_stores_md, build_settingsclaude mcp add --transport http stores https://www.stores.md/mcpFor editors that read an mcp.json file: add the remote MCP server to the project, then paste the prompt into your rules.
// .cursor/mcp.json{ "mcpServers": { "stores": { "url": "https://www.stores.md/mcp" } } }// .vscode/mcp.json{ "servers": { "stores": { "type": "http", "url": "https://www.stores.md/mcp" } } }Any client that speaks remote MCP over HTTP can add it as a custom connector. Read-only, so there is nothing to authorize.
url: https://www.stores.md/mcptransport: streamable-http # stateless, JSON responsestools: read_listing, check_purchase, compare_offers, check_stores_md, build_settingsprompts: stores # the skill, with your settingsGET with query parameters or POST a JSON body. CORS open. An OpenAPI document is at /openapi.json.
# Every tool: GET or POST https://www.stores.md/api/v1/<tool>curl -s https://www.stores.md/api/v1 | jq '.tools[].name'curl -s "https://www.stores.md/api/v1/read_listing?text=HTTP%2F1.1+402+Payment+Required%0Acontent-type%3A+application%2Fjson%0Apayment-required%3A+eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQQVlNRU5ULVNJR05BVFVSRSBoZWFkZXIgaXMgcmVxdWlyZWQiLCJyZXNvdXJjZSI6eyJ1cmwiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbS92MS9mb3JlY2FzdCIsImRlc2NyaXB0aW9uIjoiSG91cmx5IGZvcmVjYXN0LCA0OCBob3VycyIsIm1pbWVUeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LCJhY2NlcHRzIjpbeyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJlaXAxNTU6ODQ1MyIsImFtb3VudCI6IjIwMDAiLCJhc3NldCI6IjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBBNSIsInBheVRvIjoiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMEUxIiwibWF4VGltZW91dFNlY29uZHMiOjYwLCJleHRyYSI6eyJuYW1lIjoiVVNEIn19XX0%3D%0A%0A%7B%7D&source_url=https%3A%2F%2Fapi.example.com%2Fv1%2Fforecast" | jq .summarycurl -s "https://www.stores.md/api/v1/settings" | jq '.presets[].id'claude mcp add --transport http stores https://www.stores.md/mcpExample code
Call it from your own code.
Working calls against the API. The full reference is at /api/v1 and /openapi.json.
Check a payment request over MCP before your wallet signs anything.
// Check a payment request over MCP before your wallet signs anything.const answer = await fetch("https://api.example.com/v1/forecast"); // 402 Payment Requiredconst raw = `HTTP/1.1 ${answer.status}\npayment-required: ${answer.headers.get("payment-required") ?? ""}\n\n${await answer.text()}`;const res = await fetch("https://www.stores.md/mcp", { method: "POST", headers: { "content-type": "application/json", accept: "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "check_purchase", arguments: { payment_request: raw, preset: "recommended", max_per_purchase: 2 } }, }),});const { result } = await res.json();const { verdict, summary } = result.structuredContent; // fits_your_rules | ask_first | stopif (verdict !== "fits_your_rules") throw new Error(summary); // ask the person instead of payingRead a 402 answer into STORES.md, then check it before paying. Nothing is fetched or stored.
# Read a 402 answer into STORES.md, then check it before paying. Nothing is fetched or stored.curl -si https://api.example.com/v1/forecast > answer.txt # your agent gets the 402 itselfjq -Rs '{text: ., source_url: "https://api.example.com/v1/forecast"}' answer.txt \ | curl -s https://www.stores.md/api/v1/read_listing -H 'content-type: application/json' -d @- \ | jq -r .stores_md >> STORES.mdjq -Rs --rawfile md STORES.md '{payment_request: ., stores_md: $md, preset: "recommended", spent_today: 0.4}' answer.txt \ | curl -s https://www.stores.md/api/v1/check_purchase -H 'content-type: application/json' -d @- \ | jq '{verdict, summary, log_line}'FAQ
Is stores.md a marketplace?
Where does the list of every store come from?
Does a fit from check_purchase mean the payment is safe?
How is this different from llms.txt, product feeds or x402 discovery?
Is this advice?
Does it show real stores or prices?
Can an agent set up its own settings?
build_settings tool. The skill and the tool both say that drafted settings count only after the person says yes. Nothing technical stops an agent from ignoring that, so read what it sends you.