shopify-admin-mcp-server
Provides tools for interacting with the Shopify Admin GraphQL API, enabling management of orders, products, variants, media, inventory and per-location fulfilment by SKU, customers, collections, discounts, abandoned checkouts, blog content, pages, metafields, bulk variant updates, and analytics.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@shopify-admin-mcp-server check where SKU TSHIRT-BLK-M is stocked"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Shopify MCP Server v4.0.1
Shopify Admin GraphQL API 2026-01 MCP server. 54 tools aligned to the OAuth scopes actually granted on the token — orders, products, variants, media, inventory & per-location fulfilment, customers, collections, discounts, abandoned checkouts, blog content, pages, metafields, bulk variant updates, and analytics.
Every GraphQL operation is validated against the 2026-01 schema, and all 24 read tools plus the inventory write tools are verified against a live store.
npx -y shopify-admin-mcp-serverRequires SHOPIFY_STORE_DOMAIN and SHOPIFY_ACCESS_TOKEN. Full setup in Setup.
Location fulfilment by SKU
The headline capability: turn a location's ability to stock and fulfil a variant on or off, addressed by SKU rather than by GID.
shopify_get_variant_locations { sku: "TSHIRT-BLK-M" }
→ active_locations: where it IS stocked, with available/on_hand/committed/incoming,
plus can_deactivate and any deactivation_blocked_reason
→ inactive_locations: where it is NOT stocked
→ inventory_item_id: for the stock tools below
shopify_set_variant_locations {
sku: "TSHIRT-BLK-M",
locations: [
{ location: "Melbourne Warehouse", activate: true }, // by name or GID
{ location: "Pop-up Store", activate: false }
]
}Backed by inventoryBulkToggleActivation, so multiple locations are applied in one call. Activating starts the location at 0 available — follow with shopify_set_inventory.
Deactivation is destructive: it discards that location's stock for the variant. Shopify refuses when the variant has committed stock or pending fulfilments there. Check can_deactivate first.
Guardrails: a SKU that matches zero or more than one variant is rejected rather than guessed at, and an unknown location name lists the valid ones.
Related MCP server: Shopify MCP Server
Tools (54)
Shop & Orders
Tool | Scopes | Description |
| — | Store info: name, domain, plan, currency, timezone |
|
| List orders in a date range with financials and line items |
|
| Single order by GID: addresses, fulfillments, refunds |
|
| Auto-paginated aggregate: revenue, AOV, product breakdown |
|
| Lightweight count for a date range |
Inventory & Locations
Tool | Scopes | Description |
|
| All store locations with addresses |
|
| By SKU: which locations stock/fulfil a variant, and which don't |
|
| By SKU: activate/deactivate fulfilment at locations |
|
| Quantities per location for a variant GID |
|
| Change stock by a delta ("we sold 3") |
|
| Set stock to an exact value, with compare-and-set |
|
| Move stock between locations transactionally |
|
| Per-SKU settings: tracked, unit cost, HS/HTS code, country of origin |
Customs / HTS data
shopify_update_inventory_item sets the customs fields Shopify needs before it will generate international
shipping labels — harmonizedSystemCode (6–13 digits; 6110.20.20 and 61102020 are both accepted),
countryCodeOfOrigin, provinceCodeOfOrigin, and per-destination countryHarmonizedSystemCodes overrides.
Country codes are case-insensitive. Read the current values back under customs in
shopify_get_variant_locations.
shopify_set_inventory defaults to compare-and-set: pass compareQuantity and Shopify rejects the write if
someone changed the value underneath you. ignoreCompareQuantity: true forces it, at the risk of clobbering a
concurrent update.
Bulk variant updates
Tool | Scope | What it does |
|
| Apply customs, cost, pricing, identifier and weight changes to many variants at once |
|
| Report which variants are missing HS codes or country of origin |
Select variants with skus, productIds, query, onlyMissingHsCode or onlyMissingOrigin,
combined with AND. The common customs backfill is one call:
onlyMissingHsCode: true, harmonizedSystemCode: "611030", countryCodeOfOrigin: "AU"dryRun defaults to true when price or compareAtPrice is set and false otherwise, so
pricing changes need an explicit dryRun: false. maxVariants (default 500) refuses rather than
truncating. sku cannot be changed in bulk.
Analytics & marketing
Tool | Scope | What it does |
|
| Run a ShopifyQL query and get a table back |
|
| Campaign/post events with UTM parameters |
|
| One customer's activity timeline |
Marketing events are only populated when a marketing integration publishes to Shopify; an empty list means none is connected.
Products, Variants & Media
Tool | Scopes | Description |
|
| List/search products with variants, inventory, pricing (paginated) |
|
| Add tags to every product matching a search query, paging server-side; skips already-tagged products, supports |
|
| Full detail: variants, options, media, collections, SEO |
|
| Create a product, with options and images |
|
| Update fields and variant prices/SKUs |
|
| Permanent delete (requires |
|
| Copy a product; the copy defaults to DRAFT |
|
| Attach images/video from public URLs |
|
| Add variants against the product's options |
|
| Permanent delete (requires |
Customers
Tool | Scopes | Description |
|
| Search by name, email, or any Shopify filter |
|
| Full profile with addresses and recent orders |
|
| Add tags to any Shopify resource |
|
| Remove tags from any Shopify resource |
Collections
Tool | Scopes | Description |
|
| List/search collections with SEO |
|
| Create a manual or smart (rule-based) collection |
|
| Update title, description, and SEO |
|
| Add products to a manual collection (async) |
|
| Remove products from a manual collection (async) |
Pages, Blogs & Articles
Tool | Scopes | Description |
|
| List/search store pages |
|
| Full page content and publish status |
|
| Update title, HTML body, handle, publish status |
|
| List/search blogs |
|
| Blog with 10 most recent articles |
|
| Update title, handle, comment policy |
|
| Articles for a blog |
|
| Full article with HTML, author, tags |
|
| Create a blog article |
|
| Update content, tags, author, publish status |
Search, Metafields & Commerce
Tool | Scopes | Description |
|
| Unified search across products, articles, blogs, pages |
| varies by resource | Get metafields for any resource |
| varies by resource | Create or update a metafield |
| varies by resource | Delete a metafield by GID |
|
| List draft orders with line items and totals |
|
| List all discounts (code + automatic) via |
|
| Abandoned checkouts with recovery URL and line items |
Not included (scopes not granted)
These are deliberately absent — the tools would 403 at runtime. Add the scopes to the custom app and reinstall to get a new token, then they can be built:
Capability | Scopes needed |
Create/cancel fulfilments, tracking numbers, move fulfilment between locations |
|
Order edits, refunds, cancellations, order tagging |
|
Returns |
|
Create/complete draft orders |
|
Create discount codes |
|
Publish products to sales channels |
|
Create/edit locations |
|
Architecture
src/
index.ts # entry point — wires the tool modules together
shopify-client.ts # config, GraphQL client (429 retry), errors, MCP response helpers
resolvers.ts # SKU → variant, location name → GID
variant-fields.ts # shared variant field validation/normalisation (HS codes, weight, etc.)
variant-select.ts # selector (skus/productIds/query/missing-customs) → concrete variant list
bulk.ts # field-agnostic bulk variant writer: grouping, chunking, per-product results
tools/
orders.ts # shop, orders, summary, count
products.ts # products, variants, media
inventory.ts # locations, variant⇄location activation, stock
customers.ts # customers, resource tagging
content.ts # pages, blogs, articles, metafields, search
commerce.ts # collections, draft orders, discounts, abandoned checkouts
bulk-variants.ts # bulk variant field updates, customs coverage audit
analytics.ts # ShopifyQL query tool
marketing.ts # marketing events, customer event timelines
tests/
*.test.ts # Vitest unit tests — one file per module under testEach module exports a single registerXTools(server) function. No file exceeds 800 lines.
Setup
1. Create a Shopify Custom App
Shopify Admin → Settings → Apps and sales channels → Develop apps
Click Create an app
Under Configure Admin API scopes, enable:
read_all_orders,read_ordersread_analytics,read_reports,read_customer_eventsread_checkoutsread_customersread_price_rules,read_discountsread_draft_ordersread_inventory,write_inventory,read_inventory_transfers,write_inventory_transfersread_locationsread_marketing_integrated_campaigns,read_marketing_eventsread_online_store_pages,write_online_store_pagesread_content,write_contentread_products,write_products
Click Install app
Copy the Admin API access token
To confirm what a token actually has, query { currentAppInstallation { accessScopes { handle } } }.
2. Install
Run straight from npm — no clone, no build:
npx -y shopify-admin-mcp-serverOr install it globally:
npm install -g shopify-admin-mcp-servergit clone <repo> shopify-admin-mcp-server
cd shopify-admin-mcp-server
npm install
npm run build3. Configure the MCP client
{
"mcpServers": {
"shopify": {
"command": "npx",
"args": ["-y", "shopify-admin-mcp-server"],
"env": {
"SHOPIFY_STORE_DOMAIN": "mystore.myshopify.com",
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
}
}
}
}{
"mcpServers": {
"shopify": {
"command": "node",
"args": ["/full/path/to/shopify-admin-mcp-server/dist/index.js"],
"env": {
"SHOPIFY_STORE_DOMAIN": "mystore.myshopify.com",
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
}
}
}
}4. Restart the client
Environment Variables
Variable | Required | Example |
| Yes |
|
| Yes |
|
Notes
All GIDs use the format
gid://shopify/ResourceType/12345Rate limits are handled automatically with retry-after backoff (up to 3 retries)
Responses over 100,000 characters are truncated with a notice
API version: 2026-01
discountNodesreplacescodeDiscountNodes(removed in 2026-01)Destructive tools (
shopify_delete_product,shopify_delete_variants) require an explicitconfirm: trueinventoryAdjustQuantities/inventorySetQuantitiesidempotency keys are optional until 2026-04, when they become required
Fixed in v4.0.0
Five tools were silently broken against 2026-01 and failed on every call. All are now fixed and verified live:
Tool | Bug |
| Used non-existent |
| Selected |
| Selected |
| Selected |
| Used four money fields that don't exist on |
productCreate / productUpdate were also migrated off the deprecated input: ProductInput! argument to product: ProductCreateInput / ProductUpdateInput.
Available Tools
54 toolsshopify_add_product_mediaAdd Media to Shopify ProductA
Attach images or video to a product from publicly reachable URLs.
Shopify fetches each URL asynchronously, so media comes back with status UPLOADED/PROCESSING and becomes READY shortly after. A URL Shopify cannot reach fails silently into a FAILED status — re-read the product with shopify_get_product_by_id to confirm.
Inputs: media (required), productId (required).
shopify_add_tagsAdd Tags to Shopify ResourceAIdempotent
Add tags to any Shopify resource you have write access to (products, articles, collections). Tags are additive — existing tags are preserved.
Note: requires write access on the target resource type (e.g. write_products for products).
Inputs: id (required), tags (required).
shopify_adjust_inventoryAdjust Shopify Inventory (by delta)A
Change stock by a RELATIVE amount at one location — e.g. delta: -3 to remove three units.
Accepts a SKU (preferred) or an explicit inventoryItemId. Location may be a GID or a name. To set an exact number instead of a delta, use shopify_set_inventory.
The variant must already be stocked at the location — activate it first with shopify_set_variant_locations.
Inputs: delta (required), location (required), sku, name, +2 more.
shopify_analytics_queryQuery Store Analytics (ShopifyQL)ARead-onlyIdempotent
Run a ShopifyQL query against the store's analytics and get back a table.
ShopifyQL shape: FROM SHOW [GROUP BY ] [SINCE ] [UNTIL ] [ORDER BY ] [LIMIT n]
Datasets include sales, orders, products, customers.
Examples: FROM sales SHOW total_sales GROUP BY month SINCE -12m ORDER BY month FROM sales SHOW total_sales, orders GROUP BY product_title SINCE -30d ORDER BY total_sales DESC LIMIT 10 FROM orders SHOW average_order_value SINCE -90d
A syntax error is reported as an error, not as an empty table — an empty result genuinely means no matching data.
Inputs: query (required).
shopify_audit_variant_customsAudit Variant Customs CoverageARead-onlyIdempotent
Report which variants are missing customs data — the HS/HTS code and country of origin Shopify needs before it will generate international shipping labels.
Returns totals, the distinct HS codes already in use with their variant counts, and the list of variants missing data. Use this to aim a backfill before running shopify_bulk_update_variants.
Read-only — it never writes.
Inputs: limit, includeVariants.
shopify_bulk_tag_productsBulk Add Tags to Matching ProductsAIdempotent
Add tags to every product matching a Shopify search query, paging through all matches server-side in one call — no manual pagination or per-product tagging round trips.
Example: query: "title:jersey OR title:bib OR title:t-shirt", tags: ["reviewsizing"]
Skips products that already carry every tag given. Set dryRun:true to preview the match set (and see which products would be skipped as already-tagged) before writing anything.
Inputs: tags (required), query (required), dryRun, maxProducts.
shopify_bulk_update_variantsBulk Update VariantsAIdempotent
Apply the same field changes to many variants in one go — customs data, cost, pricing, identifiers and shipping weight.
Select the variants with any combination of skus, productIds, query, onlyMissingHsCode and onlyMissingOrigin (combined with AND). At least one selector is required.
The common customs backfill is: onlyMissingHsCode: true, harmonizedSystemCode: '611030', countryCodeOfOrigin: 'AU'
dryRun defaults to TRUE when price or compareAtPrice is set, and FALSE otherwise — so pricing changes require an explicit dryRun: false, while customs and cost writes apply immediately. A dry run reports exactly which variants would change and writes nothing.
maxVariants (default 500) is a hard refusal, not a truncation: if the selector matches more, nothing is written and you are told the match count.
SKU cannot be changed here — bulk-rewriting SKUs would break the selectors used to address variants. Use shopify_update_inventory_item for single-SKU changes.
Inputs: cost, skus, price, query, +18 more.
shopify_collection_add_productsAdd Products to CollectionAIdempotent
Add products to a MANUAL collection.
This fails on smart (rule-based) collections — their membership is decided by the rules, not by hand. Shopify processes the change asynchronously and returns a job; job.done: false just means it's still running, not that it failed.
Inputs: productIds (required), collectionId (required).
shopify_collection_remove_productsRemove Products from CollectionADestructiveIdempotent
Remove products from a MANUAL collection. The products themselves are not deleted — only their membership of this collection.
Processed asynchronously, same as adding.
Inputs: productIds (required), collectionId (required).
shopify_create_articleCreate Shopify ArticleC
Create a new blog article with HTML body, author, summary, and tags.
Inputs: body (required), title (required), author (required), blogId (required), +3 more.
shopify_create_collectionCreate Shopify CollectionA
Create a collection.
Two kinds:
Manual (default): you choose the products, via shopify_collection_add_products.
Smart: pass ruleSet and Shopify keeps membership up to date automatically. e.g. { appliedDisjunctively: false, rules: [{ column: "TAG", relation: "EQUALS", condition: "sale" }] } appliedDisjunctively: false = products must match ALL rules; true = ANY rule. Common columns: TAG, TITLE, TYPE, VENDOR, VARIANT_PRICE, VARIANT_INVENTORY.
A collection's rule set cannot be added later — decide smart vs manual now.
Inputs: title (required), seo, handle, ruleSet, +2 more.
shopify_create_productCreate Shopify ProductA
Create a product. Defaults to DRAFT status — pass status: "ACTIVE" to publish immediately.
Options and variants:
Give productOptions (e.g. Size → S/M/L) to create a product with real variants.
Then call shopify_create_variants to add the priced variants against those options.
With no productOptions, Shopify creates a single default variant; set its price with shopify_update_product.
Images can be attached at creation via imageUrls (each must be a publicly reachable URL).
Inputs: title (required), seo, tags, handle, +6 more.
shopify_create_variantsCreate Product VariantsA
Add new variants to an existing product.
Each variant must supply optionValues matching the product's options — e.g. for a product with options Size and Colour: optionValues: [{ optionName: "Size", name: "M" }, { optionName: "Colour", name: "Black" }]. Read the product's options first with shopify_get_product_by_id.
strategy REMOVE_STANDALONE_VARIANT deletes the auto-created default variant — use it when adding the first real variants to a product that was created without options.
Inputs: variants (required), productId (required), strategy.
shopify_delete_metafieldDelete Shopify MetafieldADestructiveIdempotent
Delete a metafield by GID. Get the ID first with shopify_get_metafields.
Inputs: metafieldId (required).
shopify_delete_productDelete Shopify ProductADestructiveIdempotent
PERMANENTLY delete a product and all its variants, media, inventory items, and collection memberships. This CANNOT be undone.
Prefer setting status to ARCHIVED via shopify_update_product if there is any chance you'll want it back. Completed orders containing the product are unaffected.
Inputs: confirm (required), productId (required).
shopify_delete_variantsDelete Product VariantsADestructiveIdempotent
PERMANENTLY delete variants from a product, along with their inventory items. This CANNOT be undone.
A product must keep at least one variant — deleting all of them fails.
Inputs: confirm (required), productId (required), variantIds (required).
shopify_duplicate_productDuplicate Shopify ProductA
Copy a product, including its variants and options, under a new title. The copy defaults to DRAFT so it can't accidentally go live.
Inputs: newTitle (required), productId (required), newStatus, includeImages.
shopify_get_article_by_idGet Shopify Article by IDBRead-onlyIdempotent
Full article with HTML body, SEO, author, tags, image, and parent blog reference.
Inputs: articleId (required).
shopify_get_articlesGet Shopify Blog ArticlesARead-onlyIdempotent
Get articles from a specific blog. Use shopify_get_blogs first to find the blog GID.
Inputs: blogId (required), limit.
shopify_get_blog_by_idGet Shopify Blog by IDARead-onlyIdempotent
Get a specific blog with its 10 most recent article summaries.
Inputs: blogId (required).
shopify_get_blogsGet Shopify BlogsCRead-onlyIdempotent
List all blogs or search by title.
Inputs: limit, searchTitle.
shopify_get_collectionsGet Shopify CollectionsBRead-onlyIdempotent
List all collections or search by title. Returns SEO fields, sort order, and template suffix.
Inputs: limit, searchTitle.
shopify_get_customerGet Shopify Customer by IDARead-onlyIdempotent
Full customer profile: all addresses, tags, order history (last 5 orders), and lifetime spend.
Inputs: customerId (required).
shopify_get_customer_eventsGet Customer Activity TimelineARead-onlyIdempotent
The activity timeline for one customer — the same events Shopify shows on the customer's admin page, newest first.
Many customers have no recorded events; an empty list is a valid answer.
Inputs: customerId (required), limit.
shopify_get_inventory_levelsGet Inventory Levels for VariantARead-onlyIdempotent
Inventory quantities at each location for a specific variant: available, on_hand, committed, incoming.
Prefer shopify_get_variant_locations — it accepts a SKU and also shows which locations are NOT stocking the variant.
Inputs: variantId (required).
shopify_get_locationsGet Shopify LocationsCRead-onlyIdempotent
All store locations: name, address, active status, and whether each fulfills online orders.
Inputs: limit.
shopify_get_metafieldsGet Shopify MetafieldsARead-onlyIdempotent
Get metafields for any Shopify resource. Requires read access on the owner resource type (e.g. read_products for product metafields).
Inputs: ownerId (required), limit, namespace.
shopify_get_orderGet Shopify Order by IDARead-onlyIdempotent
Get a single order by GID with full detail: line items, shipping/billing address, fulfillments, and refunds.
Inputs: orderId (required).
shopify_get_page_by_idGet Shopify Page by IDARead-onlyIdempotent
Full page content including HTML body, SEO, and publish status. Use after shopify_get_pages to get the full body of a specific page.
Inputs: pageId (required).
shopify_get_pagesGet Shopify PagesCRead-onlyIdempotent
List all store pages or search by title.
Inputs: limit, searchTitle.
shopify_get_product_by_idGet Shopify Product by IDBRead-onlyIdempotent
Full product detail: all variants with inventory item IDs, product options, media, collections, and SEO fields.
Inputs: productId (required).
shopify_get_productsGet Shopify ProductsARead-onlyIdempotent
List or search products. Supports cursor pagination.
Args:
searchTitle: Partial title match
query: Raw Shopify filter e.g. "status:active vendor:Nike tag:sale"
limit: Max results (default 10)
after/before: Pagination cursors
detail: "full" (variants, inventory, pricing, SKUs, images — default) or "summary" (id/title/handle/status/vendor/productType/tags/totalInventory only — much lighter, use this for bulk scans, filtering, or deciding what to tag)
Inputs: after, limit, query, before, +3 more.
shopify_get_shopGet Shopify Shop InfoARead-onlyIdempotent
Get store details: name, email, domain, Shopify plan, currency, timezone, billing address.
Inputs: no named parameters.
shopify_get_variant_locationsGet Variant Location Fulfilment StateARead-onlyIdempotent
Look up a variant by SKU (or variant GID) and see exactly which locations stock and fulfil it.
Returns:
active_locations: locations that CAN stock & fulfil this variant, with available/on_hand/committed/incoming quantities, plus can_deactivate and any deactivation_blocked_reason
inactive_locations: locations that CANNOT — activate one with shopify_set_variant_locations
inventory_item_id: needed by shopify_adjust_inventory / shopify_set_inventory
Call this before shopify_set_variant_locations to see the current state.
Inputs: sku, variantId.
shopify_list_abandoned_checkoutsList Abandoned CheckoutsARead-onlyIdempotent
List abandoned checkouts with customer details, line items, pricing, and the recovery URL. Useful for identifying recovery opportunities and lost revenue.
Only returns checkouts that have not been completed (completedAt is null).
Inputs: after, limit, query.
shopify_list_discountsList Shopify DiscountsARead-onlyIdempotent
List all discounts — code-based (basic, free shipping, BXGY) and automatic. Returns codes, usage counts, and discount values.
Filter by query string. Examples:
"status:ACTIVE"
"discount_type:percentage"
"discount_type:fixed_amount"
"title:SUMMER"
Inputs: after, limit, query.
shopify_list_draft_ordersList Shopify Draft OrdersBRead-onlyIdempotent
List draft orders with status, customer info, line items, and totals.
Filter examples: "status:open", "status:completed", "customer_id:gid://shopify/Customer/123"
Inputs: after, limit, query.
shopify_list_marketing_eventsList Marketing EventsARead-onlyIdempotent
Marketing events recorded against the store — ad campaigns, posts and other attributed activity, with their UTM parameters and run dates.
Only populated when a marketing app or integration publishes events to Shopify. An empty list means no such integration is connected, not that the query failed.
Inputs: after, limit.
shopify_list_ordersList Shopify OrdersBRead-onlyIdempotent
List orders within a date range with financial details, line items, and customer info.
Args:
date_from: Start date YYYY-MM-DD (inclusive)
date_to: End date YYYY-MM-DD (inclusive)
limit: Max orders 1–250 (default 50)
status_filter: Extra Shopify query filter e.g. "financial_status:paid fulfillment_status:unfulfilled"
Inputs: date_to (required), date_from (required), limit, status_filter.
shopify_move_inventoryMove Inventory Between LocationsA
Move stock of one variant from one location to another in a single transactional call — the origin is decremented and the destination incremented together.
Both locations must already stock the variant (activate with shopify_set_variant_locations first).
quantityName pairs the ledger states being moved between, e.g. moving 'available' at the origin to 'available' at the destination. For most stock transfers, leave both as 'available'.
Inputs: quantity (required), toLocation (required), fromLocation (required), sku, +5 more.
shopify_order_countShopify Order CountARead-onlyIdempotent
Lightweight order count for a date range without fetching order details.
Inputs: date_to (required), date_from (required), status_filter.
shopify_remove_tagsRemove Tags from Shopify ResourceAIdempotent
Remove specific tags from any Shopify resource you have write access to (products, articles, collections).
Inputs: id (required), tags (required).
shopify_searchSearch Shopify StoreARead-onlyIdempotent
Unified search across products, articles, blogs, and pages. Runs parallel queries for each type and returns results grouped by type.
Inputs: query (required), limit, types.
shopify_search_customersSearch Shopify CustomersARead-onlyIdempotent
Search customers by name, email, tags, or any Shopify customer query filter.
Example queries: "Jane Smith", "email:bob@example.com", "tag:vip", "state:enabled"
Inputs: after, limit, query.
shopify_set_inventorySet Shopify Inventory (absolute)AIdempotent
Set stock to an EXACT number at one or more locations — e.g. quantity: 42 means "there are now 42".
Use this for stocktakes and when syncing from a system that is the source of truth. For relative changes ("we sold 3"), use shopify_adjust_inventory instead.
Concurrency: by default this uses compare-and-set — pass compareQuantity (the quantity you believe is currently there) and Shopify rejects the write if someone changed it underneath you. Set ignoreCompareQuantity: true to force the write regardless, which risks clobbering a concurrent update.
The variant must already be stocked at the location — activate it first with shopify_set_variant_locations.
Inputs: quantities (required), sku, name, reason, +3 more.
shopify_set_metafieldCreate/Update Shopify MetafieldAIdempotent
Upsert a metafield on any resource you have write access to (products, collections, pages, articles).
Common types: single_line_text_field, multi_line_text_field, integer, boolean, json, url, color, date, file_reference
Inputs: key (required), type (required), value (required), ownerId (required), +1 more.
shopify_set_variant_locationsActivate/Deactivate Variant Fulfilment at LocationsADestructiveIdempotent
Turn location fulfilment ON or OFF for a variant, identified by SKU or variant GID.
activate: true → the location can stock and fulfil this variant (starts at 0 available; follow with shopify_set_inventory to set stock)
activate: false → the location no longer stocks the variant, and its stock there is discarded
Locations may be given as a GID or by name (e.g. "Melbourne Warehouse"), matched case-insensitively. Multiple locations are applied in a single call.
DEACTIVATION IS DESTRUCTIVE: it discards that location's inventory for the variant. Shopify refuses when the variant has committed stock or pending fulfilments there — check can_deactivate via shopify_get_variant_locations first.
Inputs: locations (required), sku, variantId.
shopify_update_articleUpdate Shopify ArticleCIdempotent
Update an article's title, body, summary, tags, author, or publish status.
Inputs: articleId (required), body, tags, title, +3 more.
shopify_update_blogUpdate Shopify BlogCIdempotent
Update a blog's title, handle, template suffix, or comment policy.
Comment policies: MODERATED, AUTO_PUBLISHED, CLOSED
Inputs: blogId (required), title, handle, commentPolicy, +1 more.
shopify_update_collectionUpdate Shopify CollectionCIdempotent
Update a collection's title, description HTML, and SEO metadata.
Inputs: collectionId (required), seo, title, description, +1 more.
shopify_update_inventory_itemUpdate Inventory Item SettingsAIdempotent
Update a variant's inventory-item settings — the per-SKU attributes that aren't pricing:
tracked: whether Shopify tracks stock for this SKU at all (untracked SKUs always sell)
cost: unit cost, used for profit reporting and COGS
requiresShipping: false for digital or service items
Customs / HTS fields, needed before Shopify will generate international shipping labels:
harmonizedSystemCode: the HS/HTS tariff code, 6 to 13 digits. Dots and spaces are stripped, so '6110.20.20' and '61102020' are both accepted.
countryCodeOfOrigin: 2-letter ISO country where the item was made, e.g. 'AU', 'CN'
provinceCodeOfOrigin: province/state code, only used by a few destinations (e.g. 'BC' for Canada)
countryHarmonizedSystemCodes: destination-specific HTS overrides, for when a country wants a longer national code than your 6-digit base. Replaces the whole override list.
Read the current values back with shopify_get_variant_locations. Accepts a SKU or an explicit inventoryItemId. Only provided fields change.
Inputs: sku, cost, tracked, inventoryItemId, +5 more.
shopify_update_pageUpdate Shopify PageAIdempotent
Update a page's title, HTML body, handle, template suffix, and publish status. Only provided fields are changed.
Inputs: pageId (required), body, title, handle, +2 more.
shopify_update_productUpdate Shopify ProductAIdempotent
Update a product's title, description, SEO, status, vendor, tags, or its variants' prices/SKUs. Only provided fields change.
Variants passed here are UPDATED (each needs its variant GID). To add new variants use shopify_create_variants; to remove them use shopify_delete_variants.
Inputs: productId (required), seo, tags, title, +6 more.
shopify_weekly_summaryShopify Weekly Financial SummaryARead-onlyIdempotent
Aggregate financial summary — fetches ALL orders in the period (auto-paginated), calculates revenue totals, AOV, items per order, and product breakdown sorted by revenue.
Inputs: date_to (required), date_from (required), status_filter.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 54 tools
Most tools target a distinct resource and action, and descriptions actively clarify overlaps such as get_variant_locations vs get_inventory_levels and list vs by-id retrieval. The main ambiguity is in the inventory/tagging area, where several tools have related but overlapping responsibilities.
All tools share the shopify_ prefix and use snake_case throughout, with a mostly predictable verb_noun structure. A few descriptive names like weekly_summary, order_count, and search do not follow the exact verb pattern, but the overall convention is highly consistent.
54 tools is far beyond the typical well-scoped MCP range, even for a broad Shopify admin server. The domain justifies breadth, but many operations could be consolidated, making the surface heavy for an agent to navigate reliably.
The surface is strong for products, variants, inventory, collections, content, metafields, tags, and analytics. However, major admin workflows are missing write operations for orders, customers, draft orders, and discounts, and there are no create/delete paths for several content types.
Maintenance
Related MCP Connectors
Shopify MCP Pack — wraps the Shopify Admin REST API (2024-01)
Connect AI to store orders, products and inventory with scoped access and human approvals.
Manage a Shopify store's Sternify bundles, gifts, upsells, banners and reviews via OAuth.
Read EasyStore orders, products and customers; manage stock, fulfillments and customer records.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Shopify stores through GraphQL API, providing tools for managing products, customers, orders, and more.116 npm10MIT
- AlicenseCqualityDmaintenanceEnables interaction with Shopify store data through GraphQL API, providing tools for managing products, customers, orders, blogs, and articles.152,831 npm5MIT
- AlicenseNot gradedqualityDmaintenanceProvides full access to the Shopify Admin GraphQL API through 75 tools for managing products, orders, customers, inventory, and analytics. It supports both static token and OAuth authentication while featuring cost-aware rate limiting for efficient store management.2,831 npmMIT
- AlicenseDqualityDmaintenanceEnables interaction with Shopify store data through the GraphQL API, providing tools for managing products, customers, orders, and collections.212,831 npm9MIT