pier39-merchant-server
Drop-in negotiate.v1 backend for any storefront. You bring a catalog.json. The library brings the chat agent, the discovery files, and the rate limiting. Two minutes from pip install to a running negotiable backend, via the pier39-merchant CLI wizard.
Quickstart (recommended)
pip install pier39-merchant-server
pier39-merchant init
The wizard asks for your store name, your Anthropic API key, and where to load products from (sample data, generic CSV, or a Shopify export). It writes catalog.json, serve.py, and .env into the current folder. Then:
pier39-merchant serve # run locally on port 8000
pier39-merchant deploy # deploy to Fly.io (requires flyctl)
The merchant skill is bundled inside the package — no git clone required.
Manual / library use
If you'd rather wire it up yourself:
pip install pier39-merchant-server
Six lines, including the import:
from pier39_merchant_server import serve
serve(catalog_path="catalog.json", host="0.0.0.0", port=8000)
(The library auto-discovers the skill at ~/.claude/skills/pier39-merchant/ if installed there, otherwise falls back to the bundled copy. Override with PIER39_MERCHANT_SKILL_PATH env var or pass skill_path= directly.)
That gives you, on http://0.0.0.0:8000:
| Path | Method | Purpose |
|---|---|---|
/negotiate.json + /.well-known/negotiate.json |
GET | negotiate.v1 protocol descriptor |
/llms.txt |
GET | AI-readable site index |
/api/store/catalog |
GET | Public product catalog (hidden fields stripped) |
/api/store/chat/start?product_id=<id> |
GET | Open chat session |
/api/store/chat/<sid>/say?message=<urlencoded> |
GET | Send shopper turn |
/api/store/chat/<sid> |
GET | Read running history |
/api/store/chat/start |
POST | Same as GET, for browser widgets |
/api/store/chat/<sid>/message |
POST | Same as GET, for browser widgets |
/api/health |
GET | Liveness check |
All public, all CORS-permissive (Access-Control-Allow-Origin: *).
Catalog format
A catalog.json looks like this — see examples/tiny_store/catalog.json for a working minimal example:
{
"store": {
"name": "Your Store",
"city": "City, ST",
"rep_name": "Casey",
"tagline": "...",
"policy_default": "Free shipping. 30-day return. ..."
},
"products": [
{
"id": "widget-pro",
"kind": "widget",
"name": "Widget Pro",
"subtitle": "Short product line",
"description": "Long description (model, accessories, etc.)",
"year_made": 2024,
"condition": "Brand new",
"list_price": 199,
"floor": 165,
"levers": [
"Free expedited shipping (~$15 retail value)",
"Bonus accessory kit ($29 retail)",
"Extended warranty (12 → 24 months)"
],
"inventory_note": "..."
}
]
}
The floor, levers, and inventory_note fields are hidden — they appear only in the merchant agent's private system prompt, never in any GET response. The library's /api/store/catalog endpoint strips them automatically.
Deeper control
If you need to customize, instantiate MerchantApp directly:
from pier39_merchant_server import MerchantApp
app = MerchantApp(
catalog_path="catalog.json",
skill_path="/custom/path/to/pier39-merchant",
model="claude-opus-4-6", # default: claude-sonnet-4-6
max_chat_starts_per_hour_per_ip=20, # default: 8
max_messages_per_chat=50, # default: 30
max_message_length=3000, # default: 2000
session_idle_ttl_seconds=7200, # default: 3600 (1h)
)
app.run(host="0.0.0.0", port=8000)
You can also pull app.make_handler_class() and mount it under your own ThreadingHTTPServer / nginx / wsgi setup if you have an existing stack.
Required env vars
ANTHROPIC_API_KEY— for the merchant chat agentPIER39_MERCHANT_SKILL_PATH(optional) — override skill auto-discovery
What you get for free
Any AI shopper agent that speaks negotiate.v1 can now negotiate at your store with no further coordination. The Pier39 MCP connector is one such shopper — install it in Claude Desktop and you can immediately negotiate at any negotiate.v1 storefront.
See also
- PROTOCOL.md — the formal protocol spec
- pier39-skills — the merchant + shopper Claude Agent Skills
- Atlas demo — full reference implementation
License
MIT.
Release files for pier39-merchant-server 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pier39_merchant_server-0.2.0.tar.gz | 34.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pier39_merchant_server-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 69.5 kB
Release files / pier39_merchant_server-0.2.0.tar.gz
| Download URL | pier39_merchant_server-0.2.0.tar.gz |
|---|---|
| Size | 34.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab0a600e1d11b8af6afcedf08ca1a3d2482b7788ae318821e9710b2815777fca
|
|
BLAKE2b-256 checksum How to use checksums |
60e8ab9253d28c2a8ca6eba447e98302a2d4f39ba0ce62c8a7e8a96e93d8485c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / pier39_merchant_server-0.2.0-py3-none-any.whl
| Download URL | pier39_merchant_server-0.2.0-py3-none-any.whl |
|---|---|
| Size | 34.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8bce97643d3b1f7f3cca29e2dfd93ba04fb23338f20c7f2f9e1f201bd7ae028e
|
|
BLAKE2b-256 checksum How to use checksums |
967c8f3ce7ab9d0eaf743a3553b288d7f82a1a33f51abdf8eb936a27a49d2bd6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|