cancel_order
Cancel a Shopify order while optionally issuing a full refund, restocking inventory, and notifying the customer. Choose from predefined cancellation reasons. Requires the order not be already cancelled or pending fulfillment.
Instructions
Cancel a Shopify order. Triggers an async job (the response includes a jobId; cancellation finishes shortly after the call returns). Combine with refund: true to issue a full refund of any captured payment, or refund: false if the order is unpaid or you'll handle refunds separately via refund_order. restock: true restores cancelled line items back to inventory; set false if items were physically lost/damaged. notifyCustomer: true sends the cancellation email. Cannot cancel an already-cancelled order or one with active fulfillments still in flight (cancel those fulfillments first via cancel_fulfillment).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Order GID or numeric ID to cancel. The order must not already be cancelled. | |
| reason | Yes | Why the order is being cancelled. CUSTOMER (customer requested), FRAUD (suspected fraud), INVENTORY (out of stock), DECLINED (payment declined), STAFF (staff decision), OTHER. | |
| refund | No | Whether to refund the customer's payment as part of cancellation. true = refund any captured payment in full; false = cancel without refunding (use for unpaid orders, or when you'll handle the refund separately). | |
| restock | No | Whether to restock cancelled line items back to inventory. true = decrement inventory back; false = leave inventory as-is (use when items were physically lost/damaged). | |
| staffNote | No | Internal note about the cancellation reason. Visible to staff only. | |
| notifyCustomer | No | Send the customer a cancellation email. Default false. |
Implementation Reference
- src/tools/orders.ts:473-499 (handler)The async handler function for cancel_order. Calls the ORDER_CANCEL_MUTATION GraphQL with orderId (converted via toGid), reason, refund, restock, staffNote, notifyCustomer. Throws on user errors; returns a text response with the job ID or cancellation confirmation.
async (args) => { const data = await client.graphql<{ orderCancel: { job: { id: string; done: boolean } | null; orderCancelUserErrors: ShopifyUserError[]; }; }>(ORDER_CANCEL_MUTATION, { orderId: toGid(args.id, "Order"), reason: args.reason, refund: args.refund, restock: args.restock, staffNote: args.staffNote, notifyCustomer: args.notifyCustomer, }); throwIfUserErrors(data.orderCancel.orderCancelUserErrors, "orderCancel"); const job = data.orderCancel.job; return { content: [ { type: "text" as const, text: job ? `Queued cancellation of ${args.id} (reason: ${args.reason}). Job: ${job.id} (done=${job.done})` : `Cancelled ${args.id} (reason: ${args.reason}).`, }, ], }; }, - src/tools/orders.ts:245-274 (schema)Input schema for cancel_order: id (string), reason (enum: CUSTOMER, FRAUD, INVENTORY, DECLINED, OTHER, STAFF), refund (boolean, default true), restock (boolean, default true), staffNote (optional string), notifyCustomer (optional boolean).
const cancelOrderSchema = { id: z .string() .describe("Order GID or numeric ID to cancel. The order must not already be cancelled."), reason: z .enum(["CUSTOMER", "FRAUD", "INVENTORY", "DECLINED", "OTHER", "STAFF"]) .describe( "Why the order is being cancelled. CUSTOMER (customer requested), FRAUD (suspected fraud), INVENTORY (out of stock), DECLINED (payment declined), STAFF (staff decision), OTHER.", ), refund: z .boolean() .default(true) .describe( "Whether to refund the customer's payment as part of cancellation. true = refund any captured payment in full; false = cancel without refunding (use for unpaid orders, or when you'll handle the refund separately).", ), restock: z .boolean() .default(true) .describe( "Whether to restock cancelled line items back to inventory. true = decrement inventory back; false = leave inventory as-is (use when items were physically lost/damaged).", ), staffNote: z .string() .optional() .describe("Internal note about the cancellation reason. Visible to staff only."), notifyCustomer: z .boolean() .optional() .describe("Send the customer a cancellation email. Default false."), }; - src/tools/orders.ts:469-500 (registration)Registration of cancel_order on the McpServer via server.tool() with its description and schema.
server.tool( "cancel_order", "Cancel a Shopify order. Triggers an async job (the response includes a jobId; cancellation finishes shortly after the call returns). Combine with `refund: true` to issue a full refund of any captured payment, or `refund: false` if the order is unpaid or you'll handle refunds separately via refund_order. `restock: true` restores cancelled line items back to inventory; set false if items were physically lost/damaged. `notifyCustomer: true` sends the cancellation email. Cannot cancel an already-cancelled order or one with active fulfillments still in flight (cancel those fulfillments first via cancel_fulfillment).", cancelOrderSchema, async (args) => { const data = await client.graphql<{ orderCancel: { job: { id: string; done: boolean } | null; orderCancelUserErrors: ShopifyUserError[]; }; }>(ORDER_CANCEL_MUTATION, { orderId: toGid(args.id, "Order"), reason: args.reason, refund: args.refund, restock: args.restock, staffNote: args.staffNote, notifyCustomer: args.notifyCustomer, }); throwIfUserErrors(data.orderCancel.orderCancelUserErrors, "orderCancel"); const job = data.orderCancel.job; return { content: [ { type: "text" as const, text: job ? `Queued cancellation of ${args.id} (reason: ${args.reason}). Job: ${job.id} (done=${job.done})` : `Cancelled ${args.id} (reason: ${args.reason}).`, }, ], }; }, ); - src/tools/orders.ts:74-95 (helper)GraphQL mutation ORDER_CANCEL_MUTATION used by the cancel_order handler to call Shopify's orderCancel mutation.
const ORDER_CANCEL_MUTATION = /* GraphQL */ ` mutation OrderCancel( $orderId: ID! $reason: OrderCancelReason! $refund: Boolean! $restock: Boolean! $staffNote: String $notifyCustomer: Boolean ) { orderCancel( orderId: $orderId reason: $reason refund: $refund restock: $restock staffNote: $staffNote notifyCustomer: $notifyCustomer ) { job { id done } orderCancelUserErrors { field message code } } } `; - src/tools/products.ts:333-336 (helper)Helper function toGid that converts a numeric ID to a Shopify GID (e.g., gid://shopify/Order/123). Used by the cancel_order handler when passing the order ID.
export function toGid(id: string, type: string): string { if (id.startsWith("gid://")) return id; return `gid://shopify/${type}/${id}`; }