set_metafield
Create or update a metafield on any Shopify resource by specifying ownerId, namespace, key, type, and value. Replaces existing metafield with same (ownerId, namespace, key) triple, otherwise creates new.
Instructions
Create or update (upsert) a single metafield on any supported Shopify resource — product, variant, collection, customer, order, draft order, shop, or shop policies. The (ownerId, namespace, key) triple is the unique identifier; calling this tool with an existing triple replaces the value, otherwise creates a new metafield. The type must be a Shopify-supported metafield type and the value must serialize per that type — e.g. JSON types take a JSON string, references take a target GID, primitives take literal text. Errors come back as MCP tool errors with the validation messages from Shopify.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ownerId | Yes | GID of the resource to attach the metafield to (e.g. gid://shopify/Product/123, gid://shopify/Collection/456, gid://shopify/Customer/789, gid://shopify/Order/...) | |
| namespace | Yes | Metafield namespace (2-255 chars). Convention: app-specific prefix. | |
| key | Yes | Metafield key within the namespace (1-64 chars). | |
| type | Yes | Metafield type: 'single_line_text_field', 'multi_line_text_field', 'number_integer', 'number_decimal', 'boolean', 'json', 'url', 'date', 'date_time', 'rating', 'color', 'weight', 'volume', 'dimension', 'money', 'rich_text_field', or reference types like 'product_reference', 'collection_reference', 'file_reference'. | |
| value | Yes | Metafield value, serialized per the type. JSON/reference types take a JSON string; primitives take the literal string. |
Implementation Reference
- src/tools/metafields.ts:121-161 (handler)The handler/function that executes the 'set_metafield' tool logic — calls the Shopify GraphQL MetafieldsSet mutation with ownerId, namespace, key, type, and value, then returns the saved metafield details.
async (args) => { const data = await client.graphql<{ metafieldsSet: { metafields: Metafield[]; userErrors: ShopifyUserError[]; }; }>(METAFIELDS_SET_MUTATION, { metafields: [ { ownerId: args.ownerId, namespace: args.namespace, key: args.key, type: args.type, value: args.value, }, ], }); throwIfUserErrors(data.metafieldsSet.userErrors, "metafieldsSet"); const mf = data.metafieldsSet.metafields[0]; if (!mf) { return { content: [ { type: "text" as const, text: "metafieldsSet returned no metafield." }, ], }; } return { content: [ { type: "text" as const, text: [ "Metafield saved:", ` ${mf.namespace}.${mf.key} (${mf.type})`, ` = ${mf.value}`, ` ID: ${mf.id}`, ` Owner: ${mf.ownerType}`, ].join("\n"), }, ], }; }, - src/tools/metafields.ts:70-96 (schema)Zod schema defining the input parameters for set_metafield: ownerId, namespace, key, type, and value.
const setMetafieldSchema = { ownerId: z .string() .describe( "GID of the resource to attach the metafield to (e.g. gid://shopify/Product/123, gid://shopify/Collection/456, gid://shopify/Customer/789, gid://shopify/Order/...)", ), namespace: z .string() .min(2) .max(255) .describe("Metafield namespace (2-255 chars). Convention: app-specific prefix."), key: z .string() .min(1) .max(64) .describe("Metafield key within the namespace (1-64 chars)."), type: z .string() .describe( "Metafield type: 'single_line_text_field', 'multi_line_text_field', 'number_integer', 'number_decimal', 'boolean', 'json', 'url', 'date', 'date_time', 'rating', 'color', 'weight', 'volume', 'dimension', 'money', 'rich_text_field', or reference types like 'product_reference', 'collection_reference', 'file_reference'.", ), value: z .string() .describe( "Metafield value, serialized per the type. JSON/reference types take a JSON string; primitives take the literal string.", ), }; - src/tools/metafields.ts:117-162 (registration)Registration of the 'set_metafield' tool on the McpServer with its name, description, schema, and handler function via server.tool().
server.tool( "set_metafield", "Create or update (upsert) a single metafield on any supported Shopify resource — product, variant, collection, customer, order, draft order, shop, or shop policies. The (ownerId, namespace, key) triple is the unique identifier; calling this tool with an existing triple replaces the value, otherwise creates a new metafield. The `type` must be a Shopify-supported metafield type and the `value` must serialize per that type — e.g. JSON types take a JSON string, references take a target GID, primitives take literal text. Errors come back as MCP tool errors with the validation messages from Shopify.", setMetafieldSchema, async (args) => { const data = await client.graphql<{ metafieldsSet: { metafields: Metafield[]; userErrors: ShopifyUserError[]; }; }>(METAFIELDS_SET_MUTATION, { metafields: [ { ownerId: args.ownerId, namespace: args.namespace, key: args.key, type: args.type, value: args.value, }, ], }); throwIfUserErrors(data.metafieldsSet.userErrors, "metafieldsSet"); const mf = data.metafieldsSet.metafields[0]; if (!mf) { return { content: [ { type: "text" as const, text: "metafieldsSet returned no metafield." }, ], }; } return { content: [ { type: "text" as const, text: [ "Metafield saved:", ` ${mf.namespace}.${mf.key} (${mf.type})`, ` = ${mf.value}`, ` ID: ${mf.id}`, ` Owner: ${mf.ownerType}`, ].join("\n"), }, ], }; }, ); - src/server.ts:61-71 (registration)Top-level invocation where registerMetafieldTools is called with the MCP server and Shopify client in the server setup.
registerMetafieldTools(s, shopify); registerDraftOrderTools(s, shopify); registerCollectionTools(s, shopify); registerVariantTools(s, shopify); registerFulfillmentTools(s, shopify); registerWebhookTools(s, shopify); registerMetaobjectTools(s, shopify); registerAnalyticsTools(s, shopify); registerBridgeTools(s, shopify, comfyui, config.comfyUIDefaultCkpt); return s; }; - src/tools/metafields.ts:19-35 (helper)GraphQL mutation string METAFIELDS_SET_MUTATION used by the set_metafield handler to send the metafieldsSet mutation to Shopify.
const METAFIELDS_SET_MUTATION = /* GraphQL */ ` mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) { metafieldsSet(metafields: $metafields) { metafields { id namespace key type value ownerType createdAt updatedAt } userErrors { field message code } } } `;