Quote and create from natural language
A user describes an order in plain English. The agent resolves the tenant + merchant, gets carrier rate quotes, creates a draft shipment with the chosen rate, and confirms.
This is the canonical "I want to ship this thing" flow — the path from user intent to a booked shipment in the fewest tool calls.
When to use
- Internal ops copilot: ad-hoc shipments without going through the Dashboard.
- Order-management agent: when an order arrives via email or chat and needs a manual shipment created.
- Customer-facing storefront agent (with tight guardrails) — quote a delivery option without going to a checkout page.
Tool sequence
get_accessible_tenants (which tenant?)
│
▼
get_merchants (which merchant within the tenant?)
│
▼
get_shipping_rates (what are the carrier options + costs?)
│
▼
user picks a rate
│
▼
create_shipment(draft=true) (save the chosen rate as a draft)
│
▼
confirm_shipment (book the carrier)
Example agent prompt
"Ship 2 boxes from our Dubai warehouse to Sara at 25 Maple Street, Riyadh, postcode 11564. COD AED 350. What are my options?"
The agent narrates rate options, the user picks one, and the agent books it.
Walkthrough
Step 1 — resolve tenant and merchant
get_accessible_tenants()
get_merchants(tenantId="…")
If the user's prompt mentioned a brand or merchant name, match it
against get_merchants. If the tenant is ambiguous, the agent should
ask before proceeding — never guess.
Step 2 — get rate quotes
get_shipping_rates(
tenantId="…",
shipment={
"merchant": "…",
"pickup": { "location_id": "DXB-WH-01" },
"dropoff": {
"address1": "25 Maple Street",
"city": "Riyadh",
"country": "SA",
"postcode": "11564",
"contact_name": "Sara",
"contact_phone": "…"
},
"parcels": [
{ "quantity": 2, "weight": 1.5 }
],
"payment": {
"currency": "AED",
"payment_on_delivery": 350
}
}
)
Returns eligible carrier-account options with their estimated cost and service-level info. The agent narrates the options ("DHL — AED 28, 2-day; Aramex — AED 22, 3-day; …") and waits for the user to pick.
Step 3 — create as a draft
Once the user picks (or the agent picks based on a rule like
"cheapest" or "fastest"), create as a draft. Unlike get_shipping_rates,
create_shipment takes the shipment fields flat at the top level
— not wrapped in a shipment object:
create_shipment(
tenantId="…",
draft=true,
merchant="…",
references={ "partner_shipment_reference": "…" },
payment={ "currency": "AED", "payment_on_delivery": 350 },
pickup={ "location_id": "DXB-WH-01" },
dropoff={
"address1": "25 Maple Street",
"city": "Riyadh",
"country": "SA",
"postcode": "11564",
"contact_name": "Sara",
"contact_phone": "…"
},
items=[ … ],
parcels=[ { "quantity": 2, "weight": 1.5 } ],
carrier_account={ "id": "<chosen account>", "name": "<chosen service>" }
)
Required fields per the input schema are tenantId, references,
payment, pickup, dropoff, and items. draft=true lets the
agent edit before locking in.
Step 4 — confirm
confirm_shipment(
tenantId="…",
shipment_id="<id from step 3>"
)
The carrier is booked. The response includes the tracking number and the label URL.
This pattern spends real money — every confirmed shipment incurs carrier fees. In any agent that books on behalf of a non-trusted user, require an explicit confirmation step between rates and create_shipment, and between create_shipment and confirm_shipment.
Variations
- Skip the draft — pass
draft=false(or omit the param) oncreate_shipmentand skipconfirm_shipmententirely. Simpler, but you lose the draft-edit window. - Multi-merchant batch — for an OMS that creates shipments across many merchants, loop steps 3 and 4 per merchant. Resolve the tenant once, the merchants once, then iterate.
- Quote-only mode — stop after step 2. The agent just narrates rate options for a human to act on. Useful when MCP is exposed to customer-facing agents that shouldn't book directly.
Pitfalls
- Address validation. If the dropoff address is malformed,
get_shipping_ratesreturns errors per carrier, not a global reject. The agent should narrate the error and ask the user to fix the address before retrying. - COD currency mismatch.
payment.currencyandpayment.payment_on_deliverymust be coherent — the agent shouldn't infer currency from the country. - Custom attributes. If the merchant routes via custom-attribute
rules (
get_custom_attributes), the agent must collect those values before creating, or risk a routing fallback.
Related patterns
- Diagnose a stuck shipment — for after-the-fact problems with shipments this pattern created.
- Reschedule a delivery on customer request — for after-the-fact changes to the delivery window.