Storefront MCPStorefront MCP

Storefront MCP

A public, per-channel MCP endpoint that lets AI shopping agents search and read a store's live catalog with structured JSON-RPC calls instead of crawling HTML.

Every vibe-coded sales channel gets its own public MCP (Model Context Protocol) endpoint. AI shopping agents (ChatGPT, Claude, and any MCP-speaking client) can connect to it directly and get structured catalog data: search results, product detail, the category tree, and store identity, without crawling pages or parsing HTML.

This endpoint exists independently of the npx create-brainerce-store scaffold. If you're building a storefront by hand against the SDK, you can wire discovery and consumption yourself using the reference below. If you generated your storefront with the scaffold, it already advertises this endpoint through app/agents.md/route.ts and you don't need to do anything extra.

Endpoint

POST https://api.brainerce.com/api/mcp/storefront/{salesChannelId}

salesChannelId is your channel's public vc_* id (the same one you pass as salesChannelId when constructing BrainerceClient). No apiKey, no Authorization header, no session: this is a public, unauthenticated, read-only surface, scoped entirely by the channel id in the URL.

A GET to the same URL returns 405. The endpoint is a Streamable HTTP MCP server that is deliberately stateless: it never issues a session id, and every POST is handled independently, so there is no server-sent-events stream to open with GET.

Protocol

Send JSON-RPC 2.0 messages in the request body. protocolVersion is 2025-03-26. A single request works, and so does a JSON-RPC batch (an array of requests) up to 20 entries; a larger batch is rejected as a single JSON-RPC error before any entry runs.

initialize

{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {} }

Returns protocolVersion, capabilities: { tools: {} }, serverInfo, and an instructions string that tells the agent how to use the four tools and that checkout happens on the storefront itself.

tools/list

{ "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }

Returns the four tool definitions below (name, description, JSON Schema inputSchema).

tools/call

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": { "name": "search_products", "arguments": { "query": "hiking boots" } }
}

The result comes back as the standard MCP tool-call shape, { content: [{ type: "text", text: "<JSON string>" }] }, with isError: true added when the tool failed (unknown store connection, a disallowed scope, a missing required argument, or a not-found lookup). A JSON-RPC level error (-32601 unknown method, -32603 internal error, -32600 batch too large) is reserved for protocol-level failures, not tool failures.

Tools

All four tools are read-only. There is no cart, checkout, or write surface on this endpoint by design: get_store_info's response and the initialize instructions both point the agent at the product's url to hand the shopper off to the storefront to buy.

Each read additionally respects the channel's configured allowedScopes (a products:read or categories:read scope must be enabled for the channel, same as any other vibe-coded read) and the same per-channel publish gating the storefront itself uses, so an agent using this endpoint can never see a product or category that wasn't published to that channel.

ToolArgumentsReturns
search_productsquery (string, optional free text over name/description/SKU), page (number, default 1), limit (number, default 10, max 20){ products: [...], page, total, totalPages }. Each product is a compact row: id, name, slug, sku, url, price, salePrice, availability, brand, image, summary.
get_productslug (string, required, accepts a slug or a product id)The same compact fields as above, plus gtin, mpn, full description (HTML stripped, capped at 2000 chars), categories ({ name, slug }[]), and variants ({ sku, name, price, salePrice, availability }[]).
list_categoriesnone{ categories: [{ name, slug, parentId, id }] }, up to 200 rows.
get_store_infonone{ name, description, currency, contactEmail, domain, note }. note is the same "checkout happens on the storefront" reminder.

price and salePrice are pre-formatted display strings in the channel's currency (salePrice is only present while a sale window is active). availability is the same normalized string the storefront SDK returns elsewhere (in stock / out of stock / backorder, based on the product's or variant's inventory).

Rate limits and abuse controls

The endpoint is throttled to 120 requests per 60 seconds. Because it takes no credential, treat it as a public surface: don't assume you can raise the limit per caller, and don't build a flow that depends on high call volume.

Every tool call is also counted (fire-and-forget, doesn't affect the response) toward the channel's "AI reads you" analytics in the dashboard, tagged by the calling agent when it's identifiable from the User-Agent header.

Discovery

The recommended way to advertise this endpoint to agents is the same /agents.md convention used for AI-answer-engine discovery (see Core Integration → /llms.txt + /agents.md): list the full endpoint URL and the four tool names under a "Machine-readable surfaces" heading, so an agent that reads /agents.md first knows to call this endpoint instead of parsing your HTML. The npx create-brainerce-store scaffold's app/agents.md/route.ts does exactly this automatically once NEXT_PUBLIC_BRAINERCE_SALES_CHANNEL_ID is set; if you're not using the scaffold, add the same line to whatever you serve at /agents.md.