Skip to main content
Glama

update_order

Update order metadata: email, tags, note, or custom attributes. Tags and custom attributes are fully replaced—read current values first to merge. Use for fixing email typos, adding fulfillment notes, or attaching internal tags.

Instructions

Update an existing order's metadata: email, tags, internal note, or custom attributes. Most order fields are immutable post-creation in Shopify (line items, totals, customer-of-record can't be changed via the Admin API after the fact) — for those, use refund_order or cancel_order to back out, then create a corrected order. Tags and customAttributes are full replacements: read the current values first if you want to merge rather than replace. Use when fixing a typo'd email, adding a fulfillment-team note, or attaching internal segmentation tags.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesOrder GID or numeric ID to update. Most order fields are immutable post-creation; only the metadata fields below can be edited via this tool.
emailNoNew customer email. Pass to update or fix the contact email.
tagsNoNew tag set. REPLACES the existing tags entirely. Read current tags first if you want to merge rather than replace.
noteNoNew internal staff note. Replaces any prior note.
customAttributesNoCustom attributes (cart attributes / order notes). Replaces the entire set if provided.

Implementation Reference

  • Schema definition for the update_order tool's input parameters: id (required), email, tags, note, and customAttributes (all optional).
    const updateOrderSchema = {
      id: z
        .string()
        .describe(
          "Order GID or numeric ID to update. Most order fields are immutable post-creation; only the metadata fields below can be edited via this tool.",
        ),
      email: z
        .string()
        .email()
        .optional()
        .describe("New customer email. Pass to update or fix the contact email."),
      tags: z
        .array(z.string())
        .optional()
        .describe(
          "New tag set. REPLACES the existing tags entirely. Read current tags first if you want to merge rather than replace.",
        ),
      note: z
        .string()
        .optional()
        .describe("New internal staff note. Replaces any prior note."),
      customAttributes: z
        .array(z.object({ key: z.string(), value: z.string() }))
        .optional()
        .describe(
          "Custom attributes (cart attributes / order notes). Replaces the entire set if provided.",
        ),
    };
  • Handler function for update_order that builds the input object, calls the ORDER_UPDATE_MUTATION GraphQL mutation, and returns a success message with the order name and ID.
      async (args) => {
        const input: Record<string, unknown> = { id: toGid(args.id, "Order") };
        if (args.email !== undefined) input.email = args.email;
        if (args.tags !== undefined) input.tags = args.tags;
        if (args.note !== undefined) input.note = args.note;
        if (args.customAttributes !== undefined) {
          input.customAttributes = args.customAttributes;
        }
    
        const data = await client.graphql<{
          orderUpdate: {
            order: { id: string; name: string; email?: string | null; tags?: string[] | null; note?: string | null } | null;
            userErrors: ShopifyUserError[];
          };
        }>(ORDER_UPDATE_MUTATION, { input });
        throwIfUserErrors(data.orderUpdate.userErrors, "orderUpdate");
        const o = data.orderUpdate.order;
        if (!o) {
          return {
            content: [
              { type: "text" as const, text: "orderUpdate returned no order." },
            ],
          };
        }
        return {
          content: [
            {
              type: "text" as const,
              text: `Updated order ${o.name} — ${o.id}`,
            },
          ],
        };
      },
    );
  • GraphQL mutation ORDER_UPDATE_MUTATION that sends OrderInput to Shopify's orderUpdate endpoint, returning id, name, email, tags, note, and userErrors.
    const ORDER_UPDATE_MUTATION = /* GraphQL */ `
      mutation OrderUpdate($input: OrderInput!) {
        orderUpdate(input: $input) {
          order {
            id
            name
            email
            tags
            note
          }
          userErrors { field message }
        }
      }
    `;
  • Registration of the 'update_order' tool on the MCP server via server.tool() with its name, description, schema, and handler function.
    server.tool(
      "update_order",
      "Update an existing order's metadata: email, tags, internal note, or custom attributes. Most order fields are immutable post-creation in Shopify (line items, totals, customer-of-record can't be changed via the Admin API after the fact) — for those, use refund_order or cancel_order to back out, then create a corrected order. Tags and customAttributes are full replacements: read the current values first if you want to merge rather than replace. Use when fixing a typo'd email, adding a fulfillment-team note, or attaching internal segmentation tags.",
      updateOrderSchema,
      async (args) => {
        const input: Record<string, unknown> = { id: toGid(args.id, "Order") };
        if (args.email !== undefined) input.email = args.email;
        if (args.tags !== undefined) input.tags = args.tags;
        if (args.note !== undefined) input.note = args.note;
        if (args.customAttributes !== undefined) {
          input.customAttributes = args.customAttributes;
        }
    
        const data = await client.graphql<{
          orderUpdate: {
            order: { id: string; name: string; email?: string | null; tags?: string[] | null; note?: string | null } | null;
            userErrors: ShopifyUserError[];
          };
        }>(ORDER_UPDATE_MUTATION, { input });
        throwIfUserErrors(data.orderUpdate.userErrors, "orderUpdate");
        const o = data.orderUpdate.order;
        if (!o) {
          return {
            content: [
              { type: "text" as const, text: "orderUpdate returned no order." },
            ],
          };
        }
        return {
          content: [
            {
              type: "text" as const,
              text: `Updated order ${o.name} — ${o.id}`,
            },
          ],
        };
      },
    );
  • src/server.ts:58-58 (registration)
    Top-level call to registerOrderTools which registers all order tools including update_order on the MCP server.
    registerOrderTools(s, shopify);
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses critical behaviors: tags and customAttributes are full replacements (not additive), and most order fields are immutable. It does not cover idempotency, side effects (e.g., webhooks), or rate limits, but the provided behavioral details are substantial for safe usage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured paragraph of four sentences. It front-loads the primary action, immediately follows with constraints, then provides usage examples and warnings. No redundant or extraneous content; every sentence provides essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is well-covered given the schema richness and sibling context. It mentions alternative tools and constraints. However, it lacks any mention of return behavior or confirmation upon success. Since no output schema exists, a brief note on what the tool returns (e.g., updated order object) would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds value by emphasizing the replacement semantics for tags and customAttributes beyond the schema text, and by reinforcing the immutability constraint on the id parameter. This extra context improves parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool updates specific metadata fields (email, tags, note, custom attributes) and explicitly contrasts immutable fields, distinguishing it from siblings like refund_order and cancel_order. It specifies the resource ('existing order') and the exact scope of modification.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use scenarios (fixing typos, adding notes, segmentation tags) and when-not-to-use guidance (immutable fields), directly referencing alternative tools (refund_order, cancel_order). It also cautions about full replacement behavior for tags and customAttributes, advising to read current values for merging.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/miller-joe/shopify-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server