botmetria / ucp
UCP (Universal Commerce Protocol) store-side SDK: make any PHP shop visible and shoppable for AI agents — manifest, agent-readable catalog, checkout sessions with signed cart hand-off.
Package info
pkg:composer/botmetria/ucp
Requires
- php: >=8.1
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^10.5
Suggests
- ext-apcu: Shared session/rate-limit storage across PHP workers on one server (Storage\ApcuStore)
- psr/http-server-middleware: PSR-15 middleware bridge (Bridge\Psr15Middleware)
README
Store-side SDK for UCP (Universal Commerce Protocol): AI agents discover
your store through /.well-known/ucp, read the catalog, build a cart via
checkout sessions and hand a signed cart link to the human — payment always
stays with your store. This package brings the same protocol surface that the
Botmetria WooCommerce plugin ships, to any PHP
platform: custom engines, Laravel, Slim, legacy front controllers.
- Zero required dependencies (PHP ≥ 8.1,
ext-json). - Two capability levels from one integration:
- implement
ProductProviderInterface→ agents see your catalog (manifest honestly reportscheckout: false— "storefront mode"); - also implement
CartProviderInterface→ full agent checkout with HMAC-signed cart hand-off into your native checkout.
- implement
- Wire format is pinned by cross-implementation golden fixtures
(
tests/verify byte-level parity with the WooCommerce plugin and the Botmetria cloud) — seeSPEC.md/ ucp-store spec.
Install
composer require botmetria/ucp
Quick start (plain PHP front controller)
use Botmetria\Ucp\Ucp; use Botmetria\Ucp\ArrayProductProvider; $ucp = new Ucp([ 'store_name' => 'My Shop', 'store_url' => 'https://my-shop.com/', 'currency' => 'EUR', 'country' => 'MD', 'products' => new ArrayProductProvider($myItems), // or your own provider // 'cart' => new MyCartProvider(), // optional: enables agent checkout ]); $ucp->run(); // serves /.well-known/ucp and /ucp/v1/*; otherwise returns control
Put those lines at the very top of your front controller (index.php),
before your application's routing.
Your adapters
use Botmetria\Ucp\ProductProviderInterface; use Botmetria\Ucp\CartProviderInterface; final class MyProducts implements ProductProviderInterface { public function list(int $offset, int $limit, string $query = '', string $category = ''): array { // return canonical item arrays: id, name, url, price, currency (+optional // description, sku, gtin, brand, category[], availability, images[]...) } public function get(string $id): ?array { /* one item or null */ } } final class MyCart implements CartProviderInterface { public function fill(array $items): string { foreach ($items as $item) { $this->cart->add($item['id'], $item['quantity']); // your platform's cart } return '/checkout'; // where to send the shopper } }
That is the whole integration: ~30 lines for catalog-only, ~50 with checkout.
Framework bridges
- Laravel: bind
Ucp::classas a singleton, prependBotmetria\Ucp\Bridge\LaravelMiddlewareto the global middleware stack. - PSR-15 (Slim, Mezzio):
new Bridge\Psr15Middleware($ucp, $responseFactory)first in the pipeline (requirespsr/http-server-middleware).
Sessions & rate limiting
Checkout sessions live 24h in a pluggable key-value store: Storage\FileStore
(default, single server), Storage\ApcuStore (shared across workers), or your
own Storage\KeyValueStoreInterface over Redis for multi-server setups.
A sliding-window rate limiter (120 req / 60 s per IP) guards /ucp/v1/* out
of the box.
Order attribution
When an order born from an agent cart is placed, call
$ucp->markOrdered($sessionId, $orderId) in your order hook — the session id
arrives with the hand-off. Sessions also carry source (chatgpt / perplexity /
claude / …) detected from the agent's User-Agent.
Verify your integration
Run the free agent purchase demo on your domain: a real agent reads your manifest, opens the catalog, picks a product and (with checkout enabled) builds a cart with a live hand-off link.
License
MIT © Botmetria — botmetria.com