ShelfProtocol
Shelf Protocol · Developer docs

Stop your agent buying from a store it can't verify.

One function call, before checkout. It returns yes or no, and a reason you can show the user.

The one line

# pip install shelfprotocol
from shelfprotocol import lookup, can_buy

profile = lookup("acme-coffee.example")
ok, why = can_buy(profile, amount_usd=40)
# → (True, "OK: $40.00 is within the $250.00 autonomous limit.")

Defaults to the hosted registry at api.shelfprotocol.com. Point at a self-hosted one with the SHELF_URL environment variable.

Fails closed. An unknown merchant, an unverified domain, or an amount over the merchant's declared ceiling all return False with a reason. You have to opt out deliberately to get anything else.

LangChain and CrewAI

# pip install "shelfprotocol[langchain]"
from langchain.agents import create_agent
from shelfprotocol.langchain_tools import get_tools

agent = create_agent(model, tools=get_tools())
# pip install "shelfprotocol[crewai]"
from crewai import Agent
from shelfprotocol.crewai_tools import get_tools

buyer = Agent(role="Purchasing agent", goal="...", tools=get_tools())

Both expose the same five tools: shelf_lookup, shelf_search, shelf_can_buy, shelf_catalog, shelf_products. The shelf_ prefix keeps them from colliding with the generic search tool most agent stacks already carry — pass get_tools(prefix="") if you'd rather have the bare names.

The agent-facing tools are stricter than the SDK. shelf_can_buy has no require_verified argument at all, so a manipulated prompt can't talk an agent into skipping domain verification. Deliberate opt-out stays available in code you write yourself, via the SDK's can_buy() directly.

crewai pins mcp~=1.28, which contradicts the [mcp] extra's mcp>=2.0, so shelfprotocol[mcp,crewai] won't resolve. Either extra alone is fine — the CrewAI adapter and the MCP server are two routes to the same tools.

MCP

# pip install "shelfprotocol[mcp]"
{
  "mcpServers": {
    "shelfprotocol": { "command": "shelfprotocol-mcp" }
  }
}

Drop that into Claude Desktop, Claude Code, or any other MCP client and it can check the registry before buying anything, without you writing any code.

Registry API

Public, unauthenticated, no key required for reads. Browsable at api.shelfprotocol.com/docs.

EndpointWhat it does
GET /v1/merchants/{domain}One merchant's full profile
GET /v1/searchFind merchants by name, category, protocol, verified status
GET /v1/productsSearch products across every merchant
GET /v1/merchants/{domain}/catalogOne merchant's cached catalog
GET /v1/statsRegistry totals
POST /v1/merchantsRegister a merchant
POST /v1/merchants/{domain}/claimTake ownership of an imported listing
POST /v1/merchants/{domain}/verifyComplete the DNS TXT check

Registering a merchant by hand

Most store owners should use the five-minute version instead. This is the raw call.

# 1. host this at https://yourdomain.com/.well-known/shelf.json
{
  "shelf_version": "0.1",
  "merchant": { "name": "Your Store", "domain": "yourdomain.com" },
  "agent_policy": { "agents_allowed": true, "max_autonomous_order_usd": 250 },
  "checkout": { "protocol": "AP2" },
  "catalog": { "feed_url": "https://yourdomain.com/shelf-catalog.json" }
}

# 2. register it
curl -X POST https://api.shelfprotocol.com/v1/merchants -d @shelf.json

# 3. add the returned DNS TXT record, then verify
curl -X POST https://api.shelfprotocol.com/v1/merchants/yourdomain.com/verify \
  -H "X-Api-Key: $SHELF_API_KEY"

Full schema in spec/SPEC.md.

Getting a store removed

If a store is listed and doesn't want to be, removal is unconditional — no questions, no retention pitch. Email luis@signalall.com or open an issue. Acknowledged within one business day, gone within five.

Removal is permanent rather than a delete: the domain goes on a suppression list the importer checks before it makes any request, so a later bulk import can't quietly put the store back.