AI Customer Service

Let your customer-service AI answer “where’s my order?” on its own, by reading live fulfilment data straight from Move Fresh.

Move Fresh publishes a small, read-only service that any AI assistant supporting the Model Context Protocol (MCP) can connect to — including Claude, ChatGPT and most agent frameworks. Your AI agent looks up an order at the moment a customer asks, instead of a person checking a portal.

At a glance

Endpointhttps://mcp.movefresh.com/mcp
ProtocolModel Context Protocol, over streamable HTTP
AuthenticationBearer token — your MCP secret, issued by Move Fresh
AccessRead-only, limited to your brand’s orders
Toolsget_delivery_status, list_orders

Getting access

MCP access is off until you switch it on for you. Ask your Move Fresh account manager for instructions on how to get your brand an MCP secret from our app.

Treat it like a password: keep it in your application’s backend, never in browser code or anywhere a customer could reach it. If it is exposed, switch MCP off and on again, to get a new secret.

Connecting your support agent

Point your MCP client at the endpoint and present your secret as the authorisation token. Here it is wired into the Claude API’s MCP connector:

client.beta.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    betas=["mcp-client-2025-11-20"],
    mcp_servers=[{
        "type": "url",
        "url": "https://mcp.movefresh.com/mcp",
        "name": "move-fresh",
        "authorization_token": "YOUR_MCP_SECRET",
    }],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "move-fresh"}],
    messages=[{"role": "user", "content": "Where is order TB-1234567?"}],
)

The tools

Two read-only tools. Your agent decides when to call them — get_delivery_status for a single order, list_orders for many.

get_delivery_status(order_reference)

order_reference is the order’s reference exactly as it appears on the order, including your brand prefix (for example TB-1234567). This is the most accurate answer available: once the parcel is moving it uses the courier’s own live tracking.

{
  "found": true,
  "status": "dispatched",
  "message": "This order was dispatched yesterday at 4:02 PM. It is
              estimated to be delivered on 23 September from
              7:00 AM to 8:00 PM.",
  "estimated_delivery_from":  "2026-09-23T07:00:00+01:00",
  "estimated_delivery_to":    "2026-09-23T20:00:00+01:00",
  "target_delivery_deadline": "2026-09-23T20:00:00+01:00",
  "estimate_source": "move_fresh",
  "courier_reference": "JD0002128900",
  "courier_link": "https://track.dhlparcel.co.uk/JD0002128900"
}

If the reference isn’t recognised you get {"found": false, "message": "Order not found."}.

list_orders(status, created_after, created_before, updated_since, page)

Lists the delivery status of your orders, most recent first, up to 200 per page. All arguments are optional:

  • status — filter by status, e.g. done or in_process.
  • created_after / created_before — ISO dates (YYYY-MM-DD) on the order’s creation date.
  • updated_since — an ISO timestamp. Returns only orders that have changed since then, whether they moved through the warehouse or were updated by the courier. This is the efficient way to poll for what has moved since you last looked.
  • page — page number, starting at 1. Call again with the next page while has_next_page is true.

Each order carries the same fields as get_delivery_status, alongside total_count and has_next_page.

One difference worth knowing. The estimates on the list method can be up to 15 minutes out of date, and will not include the 2-hour delivery window available on the day of delivery. When you need the fully up-to-date estimate for one order, including any delivery window, call get_delivery_status for it.

Response fields

FieldMeaning
foundWhether an order with that reference exists for your brand.
statusWhere the order is in fulfilment. See the list below.
messageA ready-to-show sentence summarising the status and, where relevant, the estimate. Safe to relay to a customer as-is.
estimated_delivery_fromwhen availableStart of the expected delivery window, ISO 8601 with time zone.
estimated_delivery_towhen availableEnd of the expected delivery window, ISO 8601 with time zone.
target_delivery_deadlineonce dispatchedThe latest the order was expected to arrive, fixed when it shipped. Unlike the estimate above, it doesn’t move. See Is the order late?
estimate_sourcewhen availableWhere the estimate came from — the courier’s tracking, or Move Fresh.
courier_referenceonce dispatchedThe courier’s consignment / tracking number.
courier_linkonce dispatchedA tracking URL on the courier’s own website.
date_failed_deliveryfailed delivery onlyWhen the courier attempted delivery and could not complete it.
delivery_failure_typefailed delivery onlyWhy it failed, in a fixed form you can branch on. See When a delivery doesn’t happen. Absent if the courier recorded no reason.

Order status values

Before dispatch, each carrying an estimate:

  • pending
  • waiting
  • ready
  • in_process
  • packed
  • deferred

After dispatch:

  • dispatched
  • in_transit
  • delivered

Needs attention, and no estimate is given:

  • on_hold
  • cancelled
  • rescheduled
  • failed_delivery

Estimate accuracy

Every estimate is tagged with its source, so your assistant can pitch its confidence accordingly.

estimate_sourceMeaning
a courier name, e.g.
dhl_parcel, yodel
A live estimate from the courier, available on the day of delivery.
move_freshOur own calculation from the shipping deadline, service used, the courier’s usual transit time to that particular postcode, and taking account of any holidays.

Is the order late?

A five-day-old order isn’t necessarily a problem — it depends what was expected. Once an order is dispatched, target_delivery_deadline records the latest it was expected to arrive, fixed at the moment it shipped. Compare it with estimated_delivery_to:

OrderDeadlineCurrent estimateRead as
Next-day service, now day five22 Sep26 SepFour days late. Worth apologising for and escalate.
Five-day service to a remote area26 Sep26 SepOn track, just a long journey. Reassure the customer.

The deadline doesn’t move, so the gap between the two is the slippage. If they agree, nothing has gone wrong however long the service takes. Before an order is dispatched there is no deadline to hold the courier to, so the field isn’t present.

When a delivery doesn’t happen

Two statuses mean the parcel’s arrival is no longer something we can predict, so no estimate is given at all and your agent should hand the customer to a person rather than offer a date:

StatusWhat has happened
rescheduledThe customer has arranged a new delivery time directly with the courier. Reported even if a delivery was attempted first, because it describes the current arrangement.
failed_deliveryThe courier attempted delivery and could not complete it. date_failed_delivery says when, and delivery_failure_type says why.

The message already explains the failure in words you can relay. delivery_failure_type gives the same thing in a fixed form, so your agent can ask for the right thing rather than flag a generic problem:

delivery_failure_typeSuggested response
cardedNobody was in. Tell the customer the courier will make two attempts to deliver. Escalate if they need help.
incorrect_addressFind out the correct address and then escalate.
no_valid_idExplain that the courier needs a passport, driving license or similar for certain high-value deliveries or where they need to prove age.
refused, return_to_senderThe parcel is heading back to us. Escalate for a refund or reshipment.
damagedEscalate for a replacement.
delayed, vehicle_breakdown, major_incident, weatherOutside anyone’s control. Apologise and escalate for an updated date.
otherNo detail given. Escalate.

The field is absent when the courier recorded no reason, in which case the message says only that there has been a problem. Treat that the same as other.

Example assistant prompt

A starting point for your assistant’s system prompt, written against the two tools and the fields above. Adapt the tone to your brand and fill in the placeholders {{BRAND}}, {{PREFIX}}, {{ESCALATION_ROUTE}} and {{CONTACT_ROUTE}}.

Show the full example prompt
You are the customer-service assistant for {{BRAND}}. You help customers with
their orders — most often "where is my order?" — in a warm, concise,
professional tone.

TOOLS
On the "move-fresh" server you have two read-only tools:

- get_delivery_status(order_reference) — one order, in full detail. Use this
  for any question about a specific order. It is the most accurate: once the
  parcel is moving it uses the courier's own live tracking.
- list_orders(status, created_after, created_before, updated_since, page) —
  many orders at once. Use it for questions across the account ("which orders
  are running late?", "what shipped yesterday?"); updated_since is the
  efficient way to see what has moved since you last looked. Every estimate in
  a list is Move Fresh's own calculation, so before telling a customer
  something precise about one order, confirm it with get_delivery_status.

FINDING THE ORDER
- The reference looks like {{PREFIX}}-1234567. If the customer gives only a
  number, prefix it with "{{PREFIX}}-" before calling the tool.
- If you don't have a reference, ask for it first.
- Verify identity before sharing details: ask for the reference AND the email
  or postcode on the order, and only continue if they match. Never read out
  details for an order the customer can't confirm is theirs.

IS IT LATE, OR JUST SLOW?  (do not skip this)
Once an order is dispatched the result includes target_delivery_deadline: the
latest it was expected to arrive, fixed when it shipped. Compare it with
estimated_delivery_to.
- Estimate LATER than the deadline -> genuinely late, by that difference. Say
  so plainly, apologise, and offer {{ESCALATION_ROUTE}}.
- Estimate MATCHING the deadline -> ON TRACK, even if the journey is long. A
  five-day service to a remote area is not a problem. Reassure the customer
  and give the expected date; do not apologise as though something has gone
  wrong.
- Both already in the past -> overdue. Apologise and escalate.
- Before dispatch there is no deadline, so never imply an order is late.

USING THE RESULT
- "message" is a ready-to-use sentence — relay it, or rephrase in our voice.
- Give estimated_delivery_from/to as a friendly local window (e.g. "Tuesday
  23 September, 7am–8pm") and make clear it is an estimate.
- If courier_reference / courier_link are present, share the tracking link.
- Confidence: estimate_source "move_fresh" is our own projection made before
  the courier has scanned the parcel — phrase it a little more tentatively
  ("currently expected"). A courier name (e.g. "dhl_parcel") is a live courier
  estimate — speak with confidence.

BY STATUS
- Before dispatch (pending, waiting, ready, in_process, packed, deferred):
  reassure them it is being prepared and give the estimated delivery.
- dispatched / in_transit: it is on its way — give the estimate, the tracking
  link, and apply the late-or-slow check above.
- delivered: tell them when. If they say it hasn't arrived, apologise and
  escalate.
- rescheduled: the customer has arranged a new time with the courier, so we
  cannot say when it will arrive. Confirm that, do NOT offer a date, and hand
  off via {{ESCALATION_ROUTE}}.
- failed_delivery: relay the message, which explains what happened, and use
  delivery_failure_type to ask for the right thing — confirm the address for
  incorrect_address, arrange a new time for carded, explain the ID needed for
  no_valid_id. Never offer a new delivery date yourself; hand off via
  {{ESCALATION_ROUTE}}.
- on_hold / cancelled: there is a problem and no estimate is given. Do NOT
  invent a delivery date. Apologise and hand off via {{ESCALATION_ROUTE}}.

EDGE CASES
- "found": false means the reference wasn't recognised. Ask them to
  double-check it. Never guess or invent an order.
- If a tool errors or is unreachable, apologise, don't make up a status, and
  offer to escalate.
- list_orders returns up to 200 orders a page. If has_next_page is true and
  you genuinely need more, request the next page — but prefer narrowing with
  the filters.

GUARDRAILS
- State only facts the tools return. Never fabricate order numbers, dates,
  tracking numbers, or statuses.
- The tools are read-only. You can look things up but cannot change, hold,
  cancel, or refund an order — for those, direct the customer to
  {{CONTACT_ROUTE}}.

Of everything here, the “Is it late, or just slow?” instruction is the one we’d least recommend dropping. Without it an assistant tends to apologise for any order still in transit — wrong for a five-day service on day three — and to under-react to a next-day order that is genuinely days overdue.

Keeping it secure

It’s read-only. The tools can look up order and delivery status and nothing else — no order can be created, changed, held, or cancelled through them. No personally identifying information is exposed.

It’s scoped to your brand, and can look up any order in your brand. Keep the secret in your own trusted systems; don’t embed it in a shopper-facing app or hand it to customers.

Rotate any time. If a secret might be exposed, switch the MCP service off and then on again to get a new secret.

Getting started

Ready to switch it on, or want to talk it through? Speak to your Move Fresh account manager.