# Preznt > Send flowers to anyone in the USA, the UK, Germany, Switzerland or Italy from an AI agent, via MCP (Model Context Protocol). Alpha service. ## How to connect Preznt is used through MCP — direct REST API access is not supported. - **Hosted MCP endpoint (Streamable HTTP): `https://api.preznt.net/mcp`** — connect with just the URL, no API key. The endpoint is the same for every client; only where the config lives and what the URL field is called differ: - **Claude Code**: `claude mcp add --scope user --transport http preznt https://api.preznt.net/mcp`. `--scope user` registers it for every directory; without it the server is only registered for the directory you ran the command in. Claude Code loads MCP servers at startup, so restart it after adding and check the server is listed as connected with `/mcp` (or `claude mcp list`) before prompting — an agent that says it has no florist/Preznt tools has not loaded the server. - **Claude Desktop**: Settings → Customize → Connectors → "+" → "Add custom connector", name it `Preznt` and paste `https://api.preznt.net/mcp` as the URL; leave the OAuth client ID/secret under "Advanced settings" empty. Connectors is not a top-level entry in the settings sidebar — it sits under Customize (the "+" in the composer, then Connectors → "Manage connectors", reaches the same page). Custom connectors are available on every plan (Free is capped at one), and the connection is made from Anthropic's servers rather than your machine. This is separate configuration from Claude Code: `claude mcp add` never touches the desktop app, so a server added with it will not appear here no matter how often the app is restarted. Where a Team/Enterprise workspace has custom connectors switched off, bridge it locally instead via Settings → Developer (under the "Desktop app" heading in the sidebar) → Edit Config with `{"mcpServers":{"preznt":{"command":"npx","args":["-y","mcp-remote","https://api.preznt.net/mcp"]}}}` (needs Node) and restart the app — `claude_desktop_config.json` itself only accepts stdio commands, never a `url`. - **Lovable and other app builders**: nothing to register — put the build prompt (which carries `https://api.preznt.net/mcp`) in the chat and the agent wires the app it generates to the endpoint. Example of a gift page built this way: https://preznt-petal-pleasures.lovable.app - **Any other MCP-capable client**: register `https://api.preznt.net/mcp` as a remote (Streamable HTTP) server. Which file the entry goes in and what the URL field is called (`url`, `serverUrl`, …) is the client's own convention — check its docs; the URL is the whole config either way. - Human docs: https://preznt.net/docs/agent — per-client setup at https://preznt.net/docs/agent#setup (`#claude-code`, `#claude-desktop`, `#lovable`, `#other-agents`), and a copy-paste prompt for building a gift page on top of the tools at https://preznt.net/docs/agent#build - Local/stdio alternative (from a checkout of the Preznt repo): `claude mcp add preznt -- npx tsx src/mcp/server.ts` - Five tools: `search_products`, `get_product`, `create_order`, `get_order_status`, `create_support_ticket`. Per-tool reference (every parameter, the result shape, and what each error status means): https://preznt.net/docs/tools - The endpoint is stateless: POST JSON-RPC messages; GET is not supported (405). A `GET` answering 405 and a `DELETE` answering 405 are both correct — there is no SSE stream and no session to tear down, so neither indicates a broken endpoint. - Troubleshooting `preznt ✗ failed to connect` in Claude Code: (1) restart Claude Code — servers load at startup; (2) run `claude mcp get preznt` to see which scope won — a `preznt` entry added earlier at *local* or *project* scope (e.g. the stdio variant below) silently overrides the `--scope user` one and is the entry that is failing, so `claude mcp remove preznt -s local` (or `-s project`) and re-add; (3) check the URL was not truncated when copied — it must end in `/mcp`. If `preznt` is not listed *at all*, the entry went somewhere the client is not reading: `claude mcp add` writes Claude Code's config only, so it never shows in the Claude desktop app (add it there as a custom connector instead). Full guide: https://preznt.net/docs/agent#troubleshooting - Local/stdio alternative needs a checkout of the Preznt repo and `tsx`, and must be run from the repo root. No API key is required. Requests are rate-limited (50 orders per payer email address/24h, 60 requests/min, plus further per-IP limits that are not published). A rate-limited response carries `Retry-After` (seconds) — wait that long before retrying. There is also a **service-wide fulfilment cap: at most 500 paid orders may be waiting to be placed**. While that queue is full, `create_order` refuses `production` orders with a **503** carrying `retryable: true` and a `Retry-After` of an hour — nothing is charged and no order is created. It is not a per-caller limit and not a fault in your request; the orders are placed by hand, so the queue drains at human speed. `test` orders are never refused for this reason. ## Alpha notice Preznt is in alpha, provided on a **best-effort basis**, but the whole chain is real: the emails, the payment, and the delivery. A `production` order that reaches `accepted` **is placed with a florist and the flowers are really delivered** to the recipient address on the requested date. Placement is done by hand, which is why the queue is capped (below) and why `confirmed` can lag `accepted` by a few hours. If an order cannot be fulfilled, it is refunded in full. A `test` order is the same flow with **nothing charged and nothing delivered** — the human gets a confirmation link instead of a payment link. It exists so you can integrate against the real thing without spending anyone's money. Make clear to your user which of the two you are about to create. **All five delivery countries are in production.** A `production` order really charges the human, in the delivery country's own currency — $100 in the USA, £100 in the UK, €100 in Germany and Italy, CHF 100 in Switzerland. Use `test` unless the user has actually asked for a real, paid order. ## Product One product per country, in one category (flowers) — the same bouquet in each: | Product | Price | Delivered in | Modes open | | --- | --- | --- | --- | | **Signature Flower Bouquet (USA)** | **$100.00 USD** | the USA | `test` and `production` | | **Signature Flower Bouquet (UK)** | **£100.00 GBP** | the UK | `test` and `production` | | **Signature Flower Bouquet (Germany)** | **€100.00 EUR** | Germany | `test` and `production` | | **Signature Flower Bouquet (Switzerland)** | **CHF 100.00 CHF** | Switzerland | `test` and `production` | | **Signature Flower Bouquet (Italy)** | **€100.00 EUR** | Italy | `test` and `production` | Each product is delivered in exactly one country and priced in that country's currency — there is no conversion, and `recipient.country` must match the product's `deliveryCountry`. Filter with `search_products` (`country: "US"` / `"GB"` / `"DE"` / `"CH"` / `"IT"`, and `"UK"` is accepted for `"GB"`) to get the current product ID for where you are sending. ## Ordering 1. `search_products` → pick a `product_id` 2. `create_order` → provide `product_id`, `mode` (**required** — `"test"` or `"production"`), `delivery_date`, `payer_email` (**required, except see below**), `recipient` (name, street address, city, `country`, plus a 2-letter state and zip for a US address, or the postal code alone elsewhere — a UK postcode, a German or Italian five-digit PLZ/CAP, a Swiss four-digit PLZ), optional `payer_phone` (**UK orders only**, instead of or alongside `payer_email`), `payer_name` and `gift_message` (max 255 chars — the florist's card limit; a longer message is refused, never cut off). Returns an `order_id` immediately. 3. Tell the user to check their email (including spam) or texts, whichever you gave — the order is waiting on them, not on you. 4. `get_order_status` → poll by `order_id`. **A created order is not an accepted order.** `create_order` returns a *pending* order, and only the human behind `payer_email`/`payer_phone` can move it on, by acting on a link sent to them by email and/or text. That link is never returned to you. **Orders cannot be cancelled once paid.** ## Test vs production (`mode`, required) `mode` has no default — decide it with the user, and use `test` unless they have asked for a real, paid order. Every delivery country is open for both modes, so the choice is the user's intent, not the destination. | | `test` | `production` | | --- | --- | --- | | Initial status | `pending_confirmation` | `pending_payment` | | The human receives | a **confirmation link**, by email and/or (UK only) text | a **Stripe payment link**, by email and/or (UK only) text | | To reach `accepted` | they open the link and confirm | they pay the full price | | Charged | **nothing, ever** | **yes** — the real product price | | Flowers delivered | **no** | **yes** — once paid, placed by hand with a florist | Everything else is identical: same validation, same rate limits, same statuses, same 48h link expiry. What differs is only money and flowers — `production` charges the human and delivers, `test` does neither (see the alpha notice). One asymmetry: only `production` is subject to the 500-order fulfilment cap above, because only a paid order becomes work for the people who place them. If a `production` order comes back 503 for capacity, `test` still works. An order that stays at `pending_confirmation` or `pending_payment` is waiting on the human. That is normal — do not retry `create_order`; each retry resends to them again and consumes the per-address/per-mobile limit. ## Payer contact: email (required) and, for UK orders, phone `payer_email` is the email address of the **human** placing the order, and it is mandatory for every order **except** a UK one where you give `payer_phone` instead (you may give both). Preznt sends that contact info the link the order depends on — the confirmation link in `test` mode, the Stripe payment link in `production` — by whichever channel(s) you supplied. - **Ask the user for their address/number — never invent or guess either.** Reserved example domains are rejected: `example.com`/`.org`/`.net`, and anything under the `.test`, `.example`, `.invalid` or `.localhost` TLDs. Reaching for one of those when the user has not given you an address produces a 400, not a working order. - **Supplying either is the user's consent to be contacted about this order.** Only pass an address/number whose owner asked you to place the order and agreed to be reached that way. Preznt sends transactional messages only: one carrying the confirmation or payment link, and (email only) one receipt once the order is accepted. No marketing is ever sent. - Give the bare address (`name@domain.tld`) — a display name or angle brackets (`Ada `) is rejected. - The payer's address does **not** have to be in the delivery country: a US payer can order UK flowers and vice versa. - The format is validated, but not whether the mailbox exists; a well-formed address at a dead mailbox just means the email bounces and the link never arrives. - The link is deliberately **not returned to the calling agent** — only the human can confirm or pay. - Max 50 orders per email address per 24h, and independently max 50 orders per UK mobile per 24h. - The `create_order` response reports whether each channel you gave was sent — `confirmation_email.sent` (address masked) and, if you gave a phone, `confirmation_sms.sent` (number masked); `get_order_status` echoes them as `confirmation_email_sent`/`confirmation_sms_sent`. The order is stuck only if **every** channel you gave failed — one working channel is enough. - On a failed send the relevant object also carries `failure` (the category) and `retryable`. **Only retry when `retryable` is true** — for email that means the address was rejected (`invalid_destination`) or has previously bounced or complained and is now suppressed (`suppressed`); for SMS it means the number was rejected (`invalid_destination`), opted out (`opted_out`), or has hit the unconfirmed-message cap (`unconfirmed_limit` — see below) — ask the user for a different address/number and create a new order. When it is `false` the problem is on Preznt's side and ordering again will fail identically; for a production order every attempt also opens another Stripe Checkout session. Tell the user, and email hello@preznt.net with the order ID — the order is valid and can be resumed once sending is restored. - Tell the user to check spam if the mail has not arrived. Preznt sends from `noreply@preznt.net`, signed with DKIM. ### `payer_phone` (UK orders only) Only accepted when `recipient.country` is `"GB"`/`"UK"` — Preznt cannot text anywhere else yet, and the field is rejected with a 400 on any other order. Give a UK mobile: `07xxx xxxxxx` or `+447xxx xxxxxx`; a landline is rejected. **No receipt by SMS** — the receipt once the order reaches `accepted` goes by email only, so a UK order that gives `payer_phone` alone gets no receipt message at all (only the confirmation/payment link). **Message limit:** at most two texts to a phone number that has never had an order confirmed — the human never clicked the confirmation link (test) or paid (production). Confirming any one order sent to that number lifts the limit permanently. Hitting it returns `confirmation_sms.failure: "unconfirmed_limit"`; do not keep retrying the same number — ask the user for a different one, or for `payer_email` instead. ## Delivery dates `delivery_date` is ISO 8601 (`YYYY-MM-DD`) and must be: - at least **3 business days** from today. Business days are counted in the *delivery* country: weekends and its public holidays don't count towards the three, so an order placed on a Friday cannot be delivered before the following Wednesday, and a long holiday weekend pushes it further out. - at most **3 months** from today - a **weekday** (no Saturday/Sunday delivery) - not a public holiday **in the country the order is delivered to** — US federal holidays (including observed dates), UK bank holidays, or the German, Swiss or Italian calendar. The UK list is the union of the England & Wales, Scotland and Northern Ireland calendars; the German one is the union of all sixteen Länder and the Swiss one covers the widely-observed cantonal days, so a few dates are refused country-wide that only part of the country observes. Italy's national holidays are uniform, and Good Friday is a working day there. Invalid dates get a 422-style error naming the violated rule and, for lead-time errors, the earliest possible date. ## Delivery addresses `recipient` must be a physical street address in one of the five delivery countries, and `recipient.country` must match the delivery country of the product you chose. - `country` — `"US"`, `"GB"` (`"UK"` accepted), `"DE"`, `"CH"` or `"IT"`; each also answers to its own name (`Deutschland`, `Suisse`, `Italia`, …). **Defaults to `"US"` when omitted**, which is what Preznt did before UK delivery existed. - **US** — `state` is required and must be one of the **50 states or DC**; US territories (PR, VI, GU, AS, MP) and military APO/FPO codes (AA, AE, AP) are **not served**. `zip` must be a **real US zip code located in that state** — a zip belonging to another state is rejected, and the error names the state it actually belongs to. - **UK** — `zip` is the full postcode (`SW1A 1AA`); case and spacing are normalized for you. England, Scotland, Wales and Northern Ireland are all served. Jersey (JE), Guernsey (GY), the Isle of Man (IM) and BFPO are **not served** — they are not part of the UK. `state` is an optional county and may be omitted. - **Germany** — `zip` is the five-digit Postleitzahl (`10115`). `state` is an optional Bundesland and may be omitted. - **Switzerland** — `zip` is the four-digit PLZ/NPA (`8001`). Liechtenstein (`9485`–`9498`), Campione d'Italia (`6911`) and Büsingen am Hochrhein (`8238`) use Swiss postcodes but are **not served** — they are not in Switzerland. `state` is an optional canton and may be omitted. - **Italy** — `zip` is the five-digit CAP (`00184`). San Marino (`47890`–`47899`) and Vatican City (`00120`) use Italian CAPs but are **not served** — they are separate countries. `state` is an optional provincia and may be omitted. - **No PO Boxes** in any country — flowers need a doorstep, so `PO Box 123` and its local equivalents (`Postfach`, `Packstation`, `case`/`casella postale`) are rejected. Like date errors, address errors come back as a 422 naming the violated rule. ## Order statuses - `pending_confirmation` — test order waiting for the human to click the confirmation link (initial status in `test` mode) - `pending_payment` — production order waiting for the human to pay (initial status in `production` mode) - `payment_expired` — the 48h payment link lapsed unpaid - `accepted` — order received; reached only once the human confirmed or paid - `confirmed` — order placed - `delivered` — delivered - `failed` — could not be fulfilled (escalate via `create_support_ticket`) - `cancelled` — cancelled by Preznt - `unknown` — no order with this ID / status cannot be determined ## Support `create_support_ticket` files a ticket for human follow-up (provide `issue_type`, `description`, and a contact email or phone). Response promised within 24 hours. You can also email hello@preznt.net. ## Occasion guides (written for humans) Prose pages on why and when to send flowers — what to write on the card, and which delivery date the occasion actually wants. Useful when a user asks *whether* to send flowers rather than how; the ordering rules they quote are the ones enforced here. - https://preznt.net/guides — index of all of them - https://preznt.net/guides/wedding-flowers — weddings (send to the couple's home, not the venue; Saturday weddings mean the Friday before) - https://preznt.net/guides/funeral-flowers — funerals and sympathy (we cannot reach a funeral in under 3 business days; the weeks after are the better gesture) - https://preznt.net/guides/birthday-flowers — birthdays, including belated ones - https://preznt.net/guides/flowers-for-mum — mothers, and why Mother's Day always means the Friday before (it is a Sunday in all five countries) - https://preznt.net/guides/flowers-for-your-partner — partners, anniversaries and Valentine's Day - https://preznt.net/guides/new-baby-flowers — new parents (home, not the maternity ward; week two beats week one) - https://preznt.net/guides/get-well-flowers — illness, recovery and the hard months with no card category - https://preznt.net/guides/thank-you-flowers — thanking someone, including the workplace gift-policy caveat - https://preznt.net/guides/apology-flowers — apologies (the apology comes first, the flowers follow) - https://preznt.net/guides/sending-flowers-abroad — cross-border sending, per-country address rules and excluded territories ## Legal - Terms: https://preznt.net/terms (no cancellation once paid; best-effort service) - Privacy: https://preznt.net/privacy - Contact: https://preznt.net/contact