Skip to main content
Shopify is a read + guardrailed write connector, called via tools/call over POST /shopify/mcp. The connector talks only to Shopify’s Admin GraphQL API (version 2026-04) and is connected through OAuth on your own store (see Forbind Shopify).
Endpoint: https://mcp.consile.ai/shopify/mcp. Shopify is its own named connector with only its own tools. Tool names are namespaced shopify__<tool> in Claude/ChatGPT; the bare names are used here for readability.Read tools are listed with readOnlyHint: true, destructiveHint: false, openWorldHint: false; every write tool with readOnlyHint: false, destructiveHint: true, openWorldHint: true. The endpoint also lists one unprefixed system tool, connect_account.Until a store is connected, a tool call returns a message with a connect link, and connect_account returns one too. Neither link can complete a Shopify connection, because the shop domain has to be entered in the portal. Connect Shopify from app.consile.ai.
Every failure inside the Shopify connector reaches the client as a tool result with isError: true and the text Tool invocation failed. Shopify’s own error detail is not passed through. This covers an expired or revoked connection (for example after the app was uninstalled in Shopify), a missing permission or Protected Customer Data restriction, a malformed id, invalid arguments (for example limit above 250), a graphql_query document that is not a single read-only query, and a write that Shopify rejects. If every call fails, reconnect Shopify in the portal (disconnect, then connect again). See Forbind Shopify. Platform-level refusals (not subscribed, no seat for the signed-in user, not connected, unknown tool) have their own messages; see Errors & limits.

Write safety: guardrail model

The ten write tools share one guardrail.
  1. New products are created DRAFT. A draft product is not visible in any sales channel until explicitly published/activated.
  2. confirm: true is required for: publish_product and unpublish_product; status ACTIVE or ARCHIVED on create_product, update_product and set_product_status; any update_product_variant call that includes price or compareAtPrice; delete_product_variant; and both inventory tools.
  3. Without confirmation you get a dry-run preview and no Shopify call is made. Re-run the identical call with confirm: true to apply.
  4. Failed mutations never look like success: a mutation that Shopify rejects returns a tool error, not a result.
Some writes apply immediately, without a preview: update_product edits that do not set ACTIVE/ARCHIVED (title, description, vendor, type, tags), status DRAFT on update_product or set_product_status (this takes a live product off sale), create_product_variant (including the price of new variants), and update_product_variant without price fields (SKU, barcode, taxable, inventoryPolicy). Orders, draft orders, customers, and discounts are structurally read-only: there are no write tools and no write scopes for them. There is no tool that deletes a product. The graphql_query escape hatch only forwards a single read-only query (see GraphQL query rules). This is a designed-in safety default, not an absolute guarantee. See Write tools & guardrails for the cross-connector policy.

Preview shape

When a write requires confirmation but confirm is omitted or false, the tool returns this instead of calling Shopify. The preview is a normal tool result, not an error:

Shared parameters

Ids

All id arguments accept either a bare numeric id or a full GID (gid://shopify/<Type>/<n>). The connector normalises before calling the API: non-digits are stripped from a bare id. An id is not the order number shown in Shopify admin. get_order with 1001 reads gid://shopify/Order/1001, not order #1001. To find an order by its number, call list_orders with query: "name:#1001".

Money

Money is Shopify MoneyV2 ({ amount, currencyCode }); amounts are decimal strings in the shop currency.

Pagination

integer
default:"50"
Maximum rows to return, 1-250. Rows are fetched in pages of up to 100.
string
Shopify search-query syntax, e.g. status:active, vendor:Acme, sku:ABC-1, financial_status:paid, email:a@b.com, country:DK.
List tools return:
There is no cursor argument. If pageInfo.hasNextPage is true, narrow the result with query (for example a date range) instead of paging.

Return shapes

Get tools return the GraphQL data object keyed by its root field, for example { "order": { ... } }. An id that does not exist returns { "order": null }, not an error. list_order_transactions and list_order_fulfillments take no limit and return at most 50 entries.

Read tools (40)

All read tools are annotated readOnlyHint: true.

Shop & policies

Products & variants

Collections

Publications (sales channels)

Inventory

Orders & fulfillment

Draft orders

Customers & B2B companies

Customer and order records can carry personal data (name, email, phone, address). Accessing real-merchant PII requires Shopify’s Protected Customer Data approval for the app; the platform is read-through and never persists it. If Shopify returns an access error for any selected field, the whole call fails (no partial data). Without approval this affects every tool whose result includes customer data: list_orders, get_order, list_draft_orders, get_draft_order, list_customers, get_customer, get_company and list_abandoned_checkouts.

Discounts

Checkouts, shipping & analytics

GraphQL query rules

graphql_query parses the document before sending it and only forwards a single read-only query:
  • exactly one operation, which must be a query (the anonymous { ... } shorthand counts as a query), so two queries in one document are refused;
  • fragment definitions are allowed;
  • mutation and subscription operations, schema or type definitions, and documents that do not parse are refused;
  • the document may be at most 65,536 characters and 20,000 tokens.
variables is an optional JSON object. The result is the raw GraphQL data object. A refused document returns a tool error and Shopify is never called.

Write tools (10 guardrailed)

Write tools mutate your store. New products are created DRAFT. Publishing, unpublishing, status ACTIVE or ARCHIVED, a price on an existing variant, inventory changes and variant deletion require confirm: true; without it the tool returns a preview and calls no API. Other edits apply immediately (see the guardrail model above).

create_product

Create a product. Created DRAFT by default. There is no price parameter: set the price on the product’s variant with update_product_variant.
string
required
string
default:"DRAFT"
ACTIVE (live) or ARCHIVED requires confirm: true; DRAFT is free.
string
string
string
string[]
boolean
Requires confirmation: only when status is ACTIVE or ARCHIVED.

update_product

Update a product’s fields.
string
required
string
string
string
string
string[]
string
boolean
Requires confirmation: only when status → ACTIVE or ARCHIVED. Other field changes, and status DRAFT, apply immediately, also on a live product.

set_product_status

Set a product’s status.
string
required
string
required
ACTIVE, DRAFT, or ARCHIVED.
boolean
Requires confirmation: ACTIVE (live) and ARCHIVED. DRAFT is applied without confirmation, also on a live product (it takes the product off sale).

create_product_variant

Add variants to an existing product.
string
required
object[]
required
At least one. Each variant: optionValues? (array of { "optionName": "Size", "name": "Large" }), price? and compareAtPrice? (decimal strings in the shop currency, e.g. "199.00"), sku? (stored on the inventory item), barcode?, taxable? (boolean), inventoryPolicy? (DENY or CONTINUE; CONTINUE allows selling when out of stock).
boolean
Accepted but ignored.
Requires confirmation: no, and confirm is ignored. The variant is added to the product as it is: on a product that is already ACTIVE and published, the new variant and its price are live immediately.

update_product_variant

Update existing variants (each entry needs an id).
string
required
object[]
required
At least one. Each must include id; may set the same fields as create_product_variant (price, compareAtPrice, sku, barcode, taxable, inventoryPolicy, optionValues).
boolean
Requires confirmation: yes if any variant includes price or compareAtPrice, even if the value is unchanged. Changes to SKU, barcode, taxable and inventoryPolicy alone apply immediately.

delete_product_variant

Delete variants from a product.
string
required
string[]
required
boolean
Set true to apply. Omit it (or false) to get a dry-run preview first.
Requires confirmation: always (destructive).

publish_product

Publish a product to one or more sales channels (makes it live).
string
required
string[]
required
Publication ids from list_publications.
boolean
Set true to apply. Omit it (or false) to get a dry-run preview first.
Requires confirmation: always (makes the product live).

unpublish_product

Remove a product from one or more sales channels.
string
required
string[]
required
boolean
Set true to apply. Omit it (or false) to get a dry-run preview first.
Requires confirmation: always.

set_inventory_quantity

Set an absolute stock quantity at a location. The current value is overwritten without a compare check.
string
required
string
required
integer
required
string
default:"available"
available or on_hand.
string
default:"correction"
boolean
Set true to apply. Omit it (or false) to get a dry-run preview first.
Requires confirmation: always (inventory change).

adjust_inventory_quantity

Adjust stock by a relative delta at a location.
string
required
string
required
integer
required
Positive or negative.
string
default:"available"
available or on_hand.
string
default:"correction"
boolean
Set true to apply. Omit it (or false) to get a dry-run preview first.
Requires confirmation: always (inventory change).

Return values

An applied write returns Shopify’s mutation payload with an empty userErrors array:

Code examples

Shopify rate limits are cost-based (a leaky bucket). A throttled call is retried up to two times, waiting for the bucket to refill; if it is still throttled, the client gets Tool invocation failed. The per-request timeout is 20 s. Some tools (list_inventory_transfers, get_inventory_transfer, get_inventory_shipment, run_analytics_query) read parts of the Admin API that have changed between Shopify API versions and are best-effort against 2026-04; the graphql_query escape hatch covers any gap. See Errors & limits.