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.
Metadata
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 | Provenance | Actions |
|---|---|---|---|---|
| pier39_merchant_server-0.2.0.tar.gz | 34.8 kB | Without provenance | Details for pier39_merchant_server-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pier39_merchant_server-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for pier39_merchant_server-0.2.0-py3-none-any.whl |
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
|
Security for pier39-merchant-server 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.