MCP Server
The Lifepeaks MCP server exposes part of the v2 API as tools, a resource, and prompts that any MCP-compatible AI agent can use. Each tool does exactly what the matching REST endpoint does, with the same scope and the same validation.
Three areas are covered: headless commerce reads and order creation, branded gift-card PDF templates, and configuration of the Lifepeaks-hosted order page.
Payment confirmation, capture, refunds, and negotiated settlement are deliberately not exposed as tools. Those decisions stay with your own server against the REST API.
Connecting
The MCP endpoint speaks JSON-RPC over streamable HTTP:
https://api.lifepeaks.dk/mcp
All requests require a Bearer API key in the Authorization header:
Authorization: Bearer lp_live_<your-key>
The tool list depends on the key. The server registers only the tools the presented key holds the scope for, so an agent with a read-only key never sees a write tool at all. A key with no matching scope connects successfully and sees an empty tool list.
Write tools additionally require the key to be attributable to a credential record, which every key issued through POST /v2/api-keys or the admin UI is.
Install
Claude Code — one command, with the key supplied as a header:
claude mcp add --transport http lifepeaks https://api.lifepeaks.dk/mcp \
--header "Authorization: Bearer lp_live_<your-key>"
Cursor and VS Code install from a deep link. Both carry the endpoint plus a placeholder Authorization header — after installing, replace lp_live_<your-key> with your own key in the client's MCP settings.
Any other MCP client:
npx add-mcp https://api.lifepeaks.dk/mcp
add-mcp registers the endpoint only, so add the Authorization header in that client's MCP configuration afterwards. Without it every call returns 401.
Available tools
Headless commerce
| Tool | Scope required | Description |
|---|---|---|
commerce_list_products | catalog:read | List every product the company sells — its variable-value gift card, its experiences, its events and its special offers — with the limits, prices and fees of each, plus how a card can be delivered, what a buyer may add to it, and the terms |
commerce_list_pickup_points | catalog:read | Find the courier's collection points near one postcode, for a postal order |
commerce_create_quote | quotes:create | Calculate an authoritative quote for one value gift-card line, or for up to twenty lines of one other family |
commerce_get_order | orders:read | Read canonical order, payment, and fulfillment state |
commerce_create_order | orders:create | Create an unpaid order — this never confirms payment |
commerce_create_checkout | checkout:create | Create a Lifepeaks-hosted QuickPay checkout for an unpaid order |
Amounts in these tools are whole numbers of the smallest unit of the currency, exactly as in the REST API: 50000 is DKK 500.00. Whole numbers of the smallest unit avoid rounding errors.
Every product family is read, priced and ordered here. commerce_list_products answers with the same catalog GET /v2/products returns, so an agent can discover a gcv_ experience, an evt_ event or an so_ special offer and the option a buyer wants. commerce_create_quote and commerce_create_order take the same lines the HTTP routes take, under the same rules: every line but a value one names a product_option_id and never an amount, a request carries one value line or one to twenty lines of a single other family, families are never mixed, an option appears once, and one order issues at most 1000 items. Both also take the same delivery object, and commerce_create_quote needs it whenever the buyer is posting the card: a postal quote sent without it reports shipping of 0, and the order then charges up to DKK 175,00 more. Price the selection with commerce_create_quote before creating the order, so the user approves a total Lifepeaks calculated. See Quote and order lines for every rule and the exact 422 a broken line gets.
Read fee_basis before totalling anything. It is per_line for gift cards, experiences and special offers, and per_ticket for events. An agent that assumes one fee per line quotes a two-seat event line short by a whole ticket fee.
An event line carries what the organiser asked for. commerce_create_quote and commerce_create_order accept an optional ticket object on an event line: comment, code, collection_point_id and address. Each one is conditional on something the product publishes — the event's comment.available and the option's requires.code, requires.address and requires.collection_point — so read the product and send only what it asks for. A collection point is an epp_<n> from the event's own event.collection_points and is not what commerce_list_pickup_points answers with; those are courier collection points for posting a gift card. address and collection_point_id are alternatives, and one event takes one comment however many lines name it.
A special offer publishes what the voucher is worth. redemption_value on an offer option is what the issued voucher can be spent on, and it is not always what the buyer pays: an offer configured to redeem at the regular price sells at amount and redeems at regular_amount. Tell the user redemption_value when describing what they are getting.
A business buyer goes in sender.company. commerce_create_order takes the buyer's own company there — name and vat_number always, and street, postcode, city, country as an all-or-nothing set. It is on the sender alone; the recipient schema has no company, because the company an envelope is addressed to is delivery.address.company_name and a different thing. A product whose company_required is true, or an event whose event.requires.company is true, refuses an order without it under sender_company_required. Never invent a VAT number.
A discount code is a plain string, and Lifepeaks does the arithmetic. commerce_create_quote and commerce_create_order take discount_code; there is nowhere for an agent to put a discount amount, deliberately. The answer comes back as amounts.discount, a positive figure that is subtracted, and a top-level discount object naming the code and its percentage. total is subtotal − discount + fees + shipping. A code never reduces fees, never applies to an event ticket or a special offer, and a shipping code comes off amounts.shipping while leaving amounts.discount at 0.
A quote reserves nothing. commerce_create_order locks the option rows and re-checks stock, minimums, maximums and capacity before it writes, so an agent that quoted a last seat can still be refused at the order. Re-quote before asking the user to pay.
Neither an event ticket nor a special offer can be posted. delivery.method of postal on such an order is refused, and their shipping is always 0.
Delivery and the greeting are read before the order, not guessed at, and they come back with the product. Each entry commerce_list_products answers carries delivery_methods — which of sender_email, recipient_email and postal the company actually offers, what each costs, and which of them can be scheduled — and personalization, which says how long a greeting may be and which pictures the company offers for the greeting page. An empty designs list means there is nothing to choose. There is no second tool for either: one product call is everything an agent needs to describe a whole order, and one list cannot fall out of step with another. commerce_create_order then carries the user's answers as greeting and delivery on the order body. See How the card is delivered.
commerce_list_pickup_points is the one delivery fact not already on the product, because collection points open, close and move. It is a live call to the courier and is rate-limited, so ask for points once the user has given a postcode rather than exploring. Its country is a two-letter ISO 3166-1 code; a country name is refused rather than guessed at.
How fast a posted card travels is on the product too. A company that posts its own cards publishes a priorities list of spri_<n> speeds on its postal method, and commerce_create_order names one as delivery.shipping_priority. The key is absent whenever there is no genuine choice, and sending a priority then is refused rather than ignored, so read the product before offering the option. Omitting it charges the cheapest, which is the price destinations[] already publishes.
Marketing consent is recorded, never assumed. commerce_create_order takes the same marketing_consent object the HTTP body takes, so an agent can carry a user's answer onto the order. Send it only when the user was actually shown a consent sentence and acted on it, and put that sentence in consent_text verbatim — it is the evidence, so it must never be composed or paraphrased. Omit the object when nobody was asked. See Marketing consent.
A buyer's own photograph cannot be uploaded over MCP. The protocol has no way to carry the bytes, so greeting.image over MCP names one of the company's own pictures with design_id, or an upload_id that an HTTP client already finalized. An agent with neither should send a message with "source": "none" rather than invent an id.
Branded gift-card PDF templates
| Tool | Scope required | Description |
|---|---|---|
pdf_templates_get_current | pdf_templates:read | Read the template in force for a locale (defaults to da-DK); optional lang |
pdf_templates_list | pdf_templates:read | List stored template versions; optional lang narrows to one locale |
pdf_templates_get | pdf_templates:read | Read one template version |
pdf_templates_preview | pdf_templates:read | Get a controlled preview URL, with no storage details |
pdf_templates_create_upload_intent | pdf_templates:write | Create a short-lived upload target bound to a checksum and a size. The type is always application/pdf and is not an argument |
pdf_templates_finalize | pdf_templates:write | Validate an uploaded file into one immutable version |
pdf_templates_publish | pdf_templates:write | Select a validated version for future orders |
pdf_templates_revert_to_default | pdf_templates:write | Go back to the company-branded default for a locale |
Hosted order page
| Tool | Scope required | Description |
|---|---|---|
orderpage_get_current | orderpage:read | Read the live configuration and published revision metadata; optional lang |
orderpage_list_fields | orderpage:read | List every writable field with its type and constraints |
orderpage_list_revisions | orderpage:read | List draft, published, and archived revisions; optional lang narrows to one locale |
orderpage_get_revision | orderpage:read | Read one revision, including its fields and ETag |
orderpage_preview_draft | orderpage:read | Preview a draft without touching the live page |
orderpage_create_draft | orderpage:write | Start a draft — the live page is unchanged |
orderpage_update_draft | orderpage:write | Edit a draft using its exact ETag |
orderpage_publish_draft | orderpage:write | Publish a reviewed draft to the live page |
Resource
| Resource URI | Scope required | Description |
|---|---|---|
orderpage://schema | orderpage:read | The writable field catalog as a structured resource |
Built-in prompts
| Prompt | Appears when the key can | Purpose |
|---|---|---|
build_headless_checkout | Reach any commerce tool | The safe catalog-to-checkout workflow for a partner storefront |
customize_order_page | Read the order page | The draft-review-publish workflow for the hosted page |
Writes are gated and idempotent
Every write tool takes an idempotency_key — a stable string of 16 to 255 characters that you generate once per logical action and reuse on retry, exactly like the Idempotency-Key header in REST.
Most write tools additionally take confirm, which must be true. Send it only after the user has explicitly approved that specific side effect; an unconfirmed call returns an error instead of acting. The gated tools are commerce_create_order, commerce_create_checkout, pdf_templates_publish, pdf_templates_revert_to_default, orderpage_update_draft, and orderpage_publish_draft.
Order-page workflow
Changing the hosted page goes through a draft, so nothing reaches buyers until it is published:
orderpage_list_fields— discover which fields exist, their types, maximum lengths, and whether they support per-locale values.orderpage_get_current— read what is live today.orderpage_create_draft— start a draft with anidempotency_key, optionally naming alang, aname, and afrom_revision_idto branch from a published revision rather than from the live page. Keep the returnedidandetag.orderpage_update_draft— sendrevision_id, afieldsobject, the exactetagfrom the last read, anidempotency_key, andconfirm: true. Each edit returns a new ETag; use it for the next one.orderpage_preview_draft— review the exact payload the page would render.orderpage_publish_draft— publish with the newestetag, a freshidempotency_key, andconfirm: true.
orderpage_update_draft input shape
{
"revision_id": "opr_7c1e93a4b60d48f2a5e7c081b3d92f64",
"fields": {
"orderform_company_box_bg": "#2d3a8c",
"orderform_signup_text": "Tilmeld dig eksklusive fordele"
},
"etag": "\"opr_7c1e93a4b60d48f2a5e7c081b3d92f64:v1\"",
"idempotency_key": "orderpage_draft_edit_018f4f37b949",
"confirm": true
}
Send only the fields you intend to change. Unknown fields, wrong types, and over-length values are rejected and nothing is written.
Fields marked i18n: true hold one value per locale. Choose the locale when you create the draft with lang; a draft covers a single locale, so translating a page means one draft per locale.
Error handling
A rejected write returns a runtime error carrying a JSON payload. The common causes are:
- A field name that is not in the catalog from
orderpage_list_fields. - A value of the wrong type — a string where
boolis expected, for example. - A value longer than the field's
max. - A stale
etag, meaning someone else edited the draft. Re-read the revision, reconcile, and retry with its new ETag. - A missing or
falseconfirmon a gated write.
Relationship to the REST API
The tools and the REST endpoints act on the same data, so the two can be mixed freely. Three differences are worth knowing:
- The MCP server does not manage API keys. Use
POST /v2/api-keysfor that. - The MCP server always acts on the key's own company. The
companyselector is REST-only, in the query string or in a write body alike, so an agency working on an assigned company's order page usesGET/PATCH /v2/order-page?company=<slug>instead. - Payment and money operations are REST-only. There is no MCP tool for confirming payment, capturing, refunding, or settling.
Skill file
The full skill definition for AI agents is published on this site:
/skills/lifepeaks-order-page/SKILL.md— worked examples, type rules, and the read-then-update workflow in agent-friendly format./skills/lifepeaks-order-page/references/fields.md— the field catalog the skill references.