MCP tools
Deliveries and warehouses
MCP tools for deliveries that fulfil sales orders, warehouses and destinations.
A delivery records goods leaving a warehouse for a destination. It has a sequential number within your organization (DEL-000001), line items and a status, and it can fulfil a sales order or relate to a tender. Warehouses and destinations are saved places you reuse, not a stock ledger: the platform does not track quantities in a warehouse.
How deliveries move a sales order forward, and how differences from the order are shown, is explained in Orders. The sales order tools themselves are in Sales and purchase orders.
| Tool | What it does |
|---|---|
| warehouses_list | List warehouses |
| warehouses_get | Get a warehouse |
| warehouses_create | Create a warehouse |
| warehouses_update | Update a warehouse |
| warehouses_delete | Delete a warehouse |
| destinations_list | List destinations |
| destinations_get | Get a destination |
| destinations_create | Create a destination |
| destinations_update | Update a destination |
| destinations_delete | Delete a destination |
| deliveries_list | List deliveries |
| deliveries_get | Get a delivery |
| deliveries_create | Create a delivery |
| deliveries_update | Update a delivery |
| deliveries_delete | Delete a delivery |
| deliveries_set_status | Set a delivery's status |
Warehouses
A warehouse is a place deliveries leave from. A delivery copies its warehouse's details when it is created, so editing the warehouse later never changes older delivery records.
warehouses_list
Lists your organization's warehouses, newest first. Deactivated warehouses are left out unless you ask for them with include_inactive.
Read-only · scope logistics.read · roles: owner, admin, sales, purchasing, viewer, viewer (no pricing) · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
include_inactive | boolean | No | Set to true to include deactivated warehouses. They are hidden by default. |
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Results per page: 20 by default, 100 at most. |
Returns: A page of warehouses in data, with total, page, page_size and total_pages.
warehouses_get
Fetches one warehouse by its ID: its name, address, contact person and whether it is active.
Read-only · scope logistics.read · roles: owner, admin, sales, purchasing, viewer, viewer (no pricing) · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The warehouse's ID, from warehouses_list. |
Returns: The warehouse record, in warehouse.
warehouses_create
Creates a warehouse that deliveries can ship from. Only the name is required, and a new warehouse is active.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The warehouse's name, 1 to 200 characters. |
address | string | No | The warehouse's street address, up to 500 characters. |
city | string | No | The warehouse's city, up to 100 characters. |
contact_name | string | No | The on-site contact person, up to 200 characters. |
contact_phone | string | No | The contact's phone number, up to 50 characters. |
notes | string | No | Free-form notes, up to 2,000 characters. |
{
"name": "Riyadh Central Warehouse",
"address": "Industrial City, Second Phase",
"city": "Riyadh",
"contact_name": "Khalid Al-Otaibi",
"contact_phone": "+966 11 555 0142"
}Returns: The warehouse that was created, in warehouse.
warehouses_update
Changes a warehouse's details, or hides it from pickers by sending is_active as false (true brings it back). Only what you send changes, and at least one field is required.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The warehouse's ID. |
name | string | No | The new name, 1 to 200 characters. It cannot be cleared. |
address | string | No | The warehouse's street address, up to 500 characters. Send null to clear it. |
city | string | No | The warehouse's city, up to 100 characters. Send null to clear it. |
contact_name | string | No | The on-site contact person, up to 200 characters. Send null to clear it. |
contact_phone | string | No | The contact's phone number, up to 50 characters. Send null to clear it. |
notes | string | No | Free-form notes, up to 2,000 characters. Send null to clear it. |
is_active | boolean | No | false deactivates the warehouse so it drops out of the default lists, and true makes it active again. |
{
"id": 3,
"contact_name": "Faisal Al-Harbi",
"contact_phone": "+966 11 555 0177"
}Returns: The warehouse after the change, in warehouse.
- Deliveries already created keep the details they copied, so the edit does not change them.
warehouses_delete
Deletes a warehouse. When any delivery refers to it, the warehouse is deactivated instead of deleted so those delivery records stay meaningful, and the reply says which happened.
Deletes or overwrites data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The warehouse's ID. |
Returns: ok and deactivated: true means the warehouse was kept and deactivated, false means it was deleted.
- A deactivated warehouse comes back with warehouses_update and
is_activeset totrue. A deleted one cannot be recovered.
Destinations
A destination is a receiving party you deliver to repeatedly, such as a hospital or a branch, saved so you can copy its details into deliveries. A delivery is not linked to a saved destination: you read its details and put them in the destination_* parameters when you create the delivery.
destinations_list
Lists your organization's saved destinations, newest first. Deactivated ones are left out unless you ask for them with include_inactive.
Read-only · scope logistics.read · roles: owner, admin, sales, purchasing, viewer, viewer (no pricing) · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
include_inactive | boolean | No | Set to true to include deactivated destinations. They are hidden by default. |
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Results per page: 20 by default, 100 at most. |
Returns: A page of destinations in data, with total, page, page_size and total_pages.
destinations_get
Fetches one saved destination by its ID: its name, address and contact person.
Read-only · scope logistics.read · roles: owner, admin, sales, purchasing, viewer, viewer (no pricing) · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The destination's ID, from destinations_list. |
Returns: The destination record, in destination.
destinations_create
Saves a delivery destination for reuse. Only the name is required, and a new destination is active.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The destination's name, 1 to 200 characters. |
address | string | No | The destination's street address, up to 500 characters. |
city | string | No | The destination's city, up to 100 characters. |
contact_name | string | No | The on-site contact person, up to 200 characters. |
contact_phone | string | No | The contact's phone number, up to 50 characters. |
notes | string | No | Free-form notes, up to 2,000 characters. |
{
"name": "King Fahd Hospital, Pharmacy Store",
"address": "Al Olaya Street",
"city": "Riyadh",
"contact_name": "Nora Al-Qahtani",
"contact_phone": "+966 11 555 0188"
}Returns: The destination that was saved, in destination.
destinations_update
Changes a saved destination's details, or hides it from pickers by sending is_active as false (true brings it back). Only what you send changes, and at least one field is required.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The destination's ID. |
name | string | No | The new name, 1 to 200 characters. It cannot be cleared. |
address | string | No | The destination's street address, up to 500 characters. Send null to clear it. |
city | string | No | The destination's city, up to 100 characters. Send null to clear it. |
contact_name | string | No | The on-site contact person, up to 200 characters. Send null to clear it. |
contact_phone | string | No | The contact's phone number, up to 50 characters. Send null to clear it. |
notes | string | No | Free-form notes, up to 2,000 characters. Send null to clear it. |
is_active | boolean | No | false deactivates the destination so it drops out of the default lists, and true makes it active again. |
{
"id": 12,
"is_active": false
}Returns: The destination after the change, in destination.
- Deliveries already created keep their own copy of the destination details, so the edit does not change them.
destinations_delete
Deletes a saved destination for good. No delivery is affected, because each delivery carries its own copy of the destination details. This cannot be undone.
Deletes or overwrites data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The destination's ID. |
Returns: A confirmation of the deletion, in ok.
- To hide a destination but keep it, use destinations_update with
is_activeset tofalseinstead of deleting.
Deliveries
The usual order of statuses is draft, scheduled, in_transit and delivered, plus cancelled for a delivery that will not happen. Every delivery starts as a draft, and its status is changed with deliveries_set_status, not by editing it.
deliveries_list
Lists your organization's deliveries, newest first, each with the names of its tender, sales order and warehouse. Filter by status, tender, sales order or warehouse.
Read-only · scope logistics.read · roles: owner, admin, sales, purchasing, viewer, viewer (no pricing) · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Only deliveries in this status: draft, scheduled, in_transit, delivered or cancelled. |
tender_id | integer | No | Only this tender's deliveries. |
sales_order_id | integer | No | Only the deliveries that fulfil this sales order. |
warehouse_id | integer | No | Only deliveries from this warehouse. |
page | integer | No | Page number, starting at 1. |
page_size | integer | No | Results per page: 20 by default, 100 at most. |
Returns: A page of deliveries in data, with total, page, page_size and total_pages. Each delivery has id, delivery_number, status, scheduled_at, delivered_at, the destination name and city, the warehouse_snapshot, and a short summary of its tender, sales order and current warehouse.
- Line items are not in the list. Use deliveries_get to read them.
deliveries_get
Fetches one delivery in full: its header, its lines, and the tender, sales order and current warehouse it is linked to.
Read-only · scope logistics.read · roles: owner, admin, sales, purchasing, viewer, viewer (no pricing) · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The delivery's ID, from deliveries_list. |
Returns: delivery (the header, with warehouse_snapshot), items (the lines in order), and tender, warehouse and sales_order, each null when there is none.
warehouse_snapshotis what was copied when the delivery was created and never changes.warehouseis the warehouse's current record, which may have changed since.
deliveries_create
Creates a delivery with at least one line. The platform gives it a sequential number, it starts as a draft, and the warehouse's details are copied onto it when you give warehouse_id.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
tender_id | integer | No | The tender the delivery relates to, with the ID from the tender tools. It must be visible to your organization. |
sales_order_id | integer | No | The sales order the delivery fulfils, with the ID from sales_orders_list. After saving, the order moves forward on its own: to in_progress once it has a delivery that is not cancelled, and to fulfilled once every line is delivered. |
warehouse_id | integer | No | The warehouse the goods leave from, with the ID from warehouses_list. Its details are copied onto the delivery when it is created. |
destination_name | string | Yes | The name of the receiving party, 1 to 200 characters. Required. |
destination_address | string | No | The receiving party's address, up to 500 characters. |
destination_city | string | No | The delivery city, up to 100 characters. |
destination_contact_name | string | No | The person who receives the goods, up to 200 characters. |
destination_contact_phone | string | No | The receiving contact's phone number, up to 50 characters. |
scheduled_at | string | No | The dispatch or delivery time in ISO 8601 with a time zone, such as 2026-10-12T09:00:00+03:00 or one ending in Z. A time without a zone is rejected. |
notes | string | No | Notes on the delivery, up to 2,000 characters. |
items | object[] | Yes | The goods on the delivery, 1 to 500 lines. Required. |
items[].product_id | integer | No | The catalog product this line ships, with the ID from products_list. Optional. |
items[].sales_order_item_id | integer | No | The sales-order line this line ships against, with the ID from sales_orders_get. It must be a line of the order named in sales_order_id. The delivered quantity of each order line is counted from it. |
items[].description | string | Yes | What is being shipped, 1 to 1,000 characters. |
items[].quantity | number | Yes | The quantity, zero or more. Fractions are accepted. |
items[].unit | string | No | The unit of the quantity as free text, such as box, up to 50 characters. |
items[].notes | string | No | Notes on the line, up to 1,000 characters. |
{
"tender_id": 48213,
"sales_order_id": 77,
"warehouse_id": 3,
"destination_name": "King Fahd Hospital, Pharmacy Store",
"destination_address": "Al Olaya Street",
"destination_city": "Riyadh",
"destination_contact_name": "Nora Al-Qahtani",
"destination_contact_phone": "+966 11 555 0188",
"scheduled_at": "2026-10-12T09:00:00+03:00",
"notes": "Deliver to the pharmacy store, gate 2",
"items": [
{
"product_id": 1204,
"sales_order_item_id": 311,
"description": "Syringe 5 ml, Luer lock, sterile",
"quantity": 200,
"unit": "box"
},
{
"description": "Examination gloves, nitrile, size M",
"quantity": 80,
"unit": "box"
}
]
}Returns: delivery_id and the number given to the delivery, in delivery_number.
- The number follows your organization's sequence, such as
DEL-000014, and never changes afterwards. - The tender must be visible to your organization, and the warehouse and sales order must belong to it, or the call is refused. A line with a
sales_order_item_idneedssales_order_idand must be a line of that order, or the call is refused as well. - A delivery records what actually shipped, so a line with more than the ordered quantity is accepted. The difference shows on the sales order page as a deviation from the order.
deliveries_update
Changes a delivery's destination, schedule, notes, links or lines. Only what you send changes; the status is changed with a separate tool.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The delivery's ID. |
tender_id | integer | No | The tender the delivery relates to, with the ID from the tender tools. It must be visible to your organization. Send null to remove the link. |
sales_order_id | integer | No | The sales order the delivery fulfils, with the ID from sales_orders_list. After saving, the order moves forward on its own: to in_progress once it has a delivery that is not cancelled, and to fulfilled once every line is delivered. Send null to remove the link. |
warehouse_id | integer | No | The warehouse the goods leave from, with the ID from warehouses_list. Changing it does not refresh the warehouse details stored on the delivery, which keep what was copied at creation. Send null to remove the link. |
destination_name | string | No | The name of the receiving party, 1 to 200 characters. It cannot be cleared. |
destination_address | string | No | The receiving party's address, up to 500 characters. Send null to clear it. |
destination_city | string | No | The delivery city, up to 100 characters. Send null to clear it. |
destination_contact_name | string | No | The person who receives the goods, up to 200 characters. Send null to clear it. |
destination_contact_phone | string | No | The receiving contact's phone number, up to 50 characters. Send null to clear it. |
scheduled_at | string | No | The dispatch or delivery time in ISO 8601 with a time zone, such as 2026-10-12T09:00:00+03:00 or one ending in Z. A time without a zone is rejected. Send null to clear it. |
notes | string | No | Notes on the delivery, up to 2,000 characters. Send null to clear it. |
items | object[] | No | The goods on the delivery, 1 to 500 lines. When sent, it replaces the whole list, so send the complete list. Leave it out to keep the stored lines. |
items[].product_id | integer | No | The catalog product this line ships, with the ID from products_list. Optional. |
items[].sales_order_item_id | integer | No | The sales-order line this line ships against, with the ID from sales_orders_get. It must be a line of the order named in sales_order_id. The delivered quantity of each order line is counted from it. |
items[].description | string | Yes | What is being shipped, 1 to 1,000 characters. |
items[].quantity | number | Yes | The quantity, zero or more. Fractions are accepted. |
items[].unit | string | No | The unit of the quantity as free text, such as box, up to 50 characters. |
items[].notes | string | No | Notes on the line, up to 1,000 characters. |
{
"id": 412,
"scheduled_at": "2026-10-14T10:30:00+03:00",
"notes": "Moved at the hospital's request"
}Returns: delivery_id of the delivery after the change.
itemsreplaces the whole list: a line you leave out is removed, and a line you keep that belongs to an order line needs itssales_order_item_idsent again. Leaveitemsout and the lines stay as they are.- If you change or clear
sales_order_idwithout sendingitems, the delivery's lines are unlinked from the old order's lines and stop counting toward it. - The delivery number and the stored warehouse copy cannot be edited. The status is changed with deliveries_set_status.
- After saving, the linked sales order's status is reviewed again, moving forward only.
deliveries_delete
Deletes a delivery together with its lines. This cannot be undone, and the linked sales order keeps whatever status it has reached.
Deletes or overwrites data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The delivery's ID. |
Returns: A confirmation of the deletion, in ok.
- To stop a delivery without erasing it, move it to
cancelledwith deliveries_set_status: a cancelled delivery counts for nothing toward any order.
deliveries_set_status
Moves a delivery to a new status. Any move between statuses is allowed, so a mistake is fixed by moving back, and the linked sales order's status is worked out again afterwards.
Changes data · scope logistics.write · roles: owner, admin · Pro and Enterprise plans
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The delivery's ID. |
status | string | Yes | The new status: draft, scheduled, in_transit, delivered or cancelled. |
{
"id": 412,
"status": "delivered"
}Returns: ok and status, the status the delivery is now in.
delivered_atis stamped when the delivery entersdeliveredand cleared when it leaves that status.- The sales order only moves forward: a delivery becoming
deliveredcan take it toin_progressand thenfulfilled, but moving the delivery back never moves the order back. The order has its own status tool for that.