Storefront MCP Coming soon

A store's address is also an MCP server for its customers' AI assistants: browse, order and pay without leaving the chat.

Not open yet. Storefronts open when SatsRail switches them on, for merchants on a plan that includes one. Until then every storefront answers "store unavailable". This page describes the server as it is built, so assistant developers can prepare.

Connect

Each store has one address, https://www.satsrail.com/<store>/storefront. A browser gets the store's page there; an MCP client POSTs JSON-RPC 2.0 to the same URL (MCP 2025-06-18, Streamable HTTP, one message per request, no batches). Add it to an assistant as a custom connector:

{
  "mcpServers": {
    "la-casita": {
      "type": "http",
      "url": "https://www.satsrail.com/la-casita/storefront"
    }
  }
}

Every tool acts on the store in the URL. A store that is closed answers its tools with store_unavailable; an address no store has answers 404.

Signing in

The catalog needs no sign-in. Ordering does: the customer connects the assistant once, through OAuth 2.1, with their SatsRail customer account, and the connection then works at every SatsRail store.

  1. Calling an ordering tool without a token answers 401 with WWW-Authenticate: Bearer resource_metadata="https://www.satsrail.com/.well-known/oauth-protected-resource/<store>/storefront", scope="shop".
  2. That document (RFC 9728) names the store's address as the resource, the authorization server (https://www.satsrail.com, RFC 8414 metadata at /.well-known/oauth-authorization-server) and the one scope, shop.
  3. Register at POST /oauth/register (RFC 7591) asking for scope: "shop".
  4. Send the customer to /oauth/authorize with scope=shop, PKCE (S256 only) and, optionally, resource= the store's address (RFC 8707). The customer signs in and approves.
  5. Exchange the code at POST /oauth/token. Access tokens last two hours; refresh tokens rotate.

Every request is checked again: a revoked connection, a locked account or a revoked token is refused at once with 401. A shop token works only here, never on the merchant API or the merchant MCP, and a merchant's API key or token is refused here. The customer disconnects an assistant from Connected assistants on their account.

Tools

ToolNeedsWhat it does
get_catalognothingThe store's products on sale with prices, taxes and product types. Filter by product_type, min_price and max_price (in the store's currency, not cents), sort (price_asc, price_desc) or q (name_i_cont, product_type_id_eq, price_gteq, price_lteq, s). Any other filter is refused, never ignored.
create_ordersign-inOpens the customer's one open order at this store, or returns it, with the shipping address and phone when the store asks for them
add_order_item / update_order_item / remove_order_itemsign-inChange what the open order holds, by a product's id from get_catalog; each answers the order with its totals
get_ordersign-inThe open order, or one of the customer's orders here, with items, taxes, totals and status
pay_ordersign-inThe link the customer opens to pay the order in bitcoin, or by card where the store takes cards. The assistant never pays.
reset_ordersign-inEmpties the open order to start over
list_my_orderssign-inThe customer's orders at this store with payment and delivery status

A catalog read without a token, from a script (every store's address answers on https://app.satsrail.com too):

curl -s https://app.satsrail.com/la-casita/storefront \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_catalog","arguments":{"sort":"price_asc"}}}'

Limits

Calls without a token are limited per IP address, like page views; calls with one, per token across every store. Past either you get 429 with Retry-After. Each call a signed-in customer's assistant makes is logged by tool name and outcome, never its arguments.