shopify-admin-mcp-server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SHOPIFY_ACCESS_TOKEN | Yes | Your Shopify Admin API access token | |
| SHOPIFY_STORE_DOMAIN | Yes | Your Shopify store domain, e.g., mystore.myshopify.com |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| shopify_get_shopA | Get store details: name, email, domain, Shopify plan, currency, timezone, billing address. |
| shopify_list_ordersB | List orders within a date range with financial details, line items, and customer info. Args:
|
| shopify_get_orderA | Get a single order by GID with full detail: line items, shipping/billing address, fulfillments, and refunds. |
| shopify_weekly_summaryA | Aggregate financial summary — fetches ALL orders in the period (auto-paginated), calculates revenue totals, AOV, items per order, and product breakdown sorted by revenue. |
| shopify_order_countA | Lightweight order count for a date range without fetching order details. |
| shopify_search_customersA | Search customers by name, email, tags, or any Shopify customer query filter. Example queries: "Jane Smith", "email:bob@example.com", "tag:vip", "state:enabled" |
| shopify_get_customerA | Full customer profile: all addresses, tags, order history (last 5 orders), and lifetime spend. |
| shopify_add_tagsA | 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). |
| shopify_remove_tagsA | Remove specific tags from any Shopify resource you have write access to (products, articles, collections). |
| shopify_get_productsA | List or search products. Supports cursor pagination. Args:
|
| shopify_bulk_tag_productsA | 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. |
| shopify_get_product_by_idB | Full product detail: all variants with inventory item IDs, product options, media, collections, and SEO fields. |
| shopify_create_productA | Create a product. Defaults to DRAFT status — pass status: "ACTIVE" to publish immediately. Options and variants:
Images can be attached at creation via imageUrls (each must be a publicly reachable URL). |
| shopify_update_productA | 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. |
| shopify_delete_productA | 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. |
| shopify_duplicate_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. |
| shopify_add_product_mediaA | 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. |
| shopify_create_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. |
| shopify_delete_variantsA | 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. |
| shopify_get_locationsC | All store locations: name, address, active status, and whether each fulfills online orders. |
| shopify_get_variant_locationsA | Look up a variant by SKU (or variant GID) and see exactly which locations stock and fulfil it. Returns:
Call this before shopify_set_variant_locations to see the current state. |
| shopify_set_variant_locationsA | Turn location fulfilment ON or OFF for a variant, identified by SKU or variant GID.
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. |
| shopify_get_inventory_levelsA | 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. |
| shopify_adjust_inventoryA | 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. |
| shopify_set_inventoryA | 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. |
| shopify_move_inventoryA | 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'. |
| shopify_update_inventory_itemA | Update a variant's inventory-item settings — the per-SKU attributes that aren't pricing:
Customs / HTS fields, needed before Shopify will generate international shipping labels:
Read the current values back with shopify_get_variant_locations. Accepts a SKU or an explicit inventoryItemId. Only provided fields change. |
| shopify_get_pagesC | List all store pages or search by title. |
| shopify_get_page_by_idA | Full page content including HTML body, SEO, and publish status. Use after shopify_get_pages to get the full body of a specific page. |
| shopify_update_pageA | Update a page's title, HTML body, handle, template suffix, and publish status. Only provided fields are changed. |
| shopify_get_blogsC | List all blogs or search by title. |
| shopify_get_blog_by_idA | Get a specific blog with its 10 most recent article summaries. |
| shopify_update_blogC | Update a blog's title, handle, template suffix, or comment policy. Comment policies: MODERATED, AUTO_PUBLISHED, CLOSED |
| shopify_get_articlesA | Get articles from a specific blog. Use shopify_get_blogs first to find the blog GID. |
| shopify_get_article_by_idB | Full article with HTML body, SEO, author, tags, image, and parent blog reference. |
| shopify_create_articleC | Create a new blog article with HTML body, author, summary, and tags. |
| shopify_update_articleC | Update an article's title, body, summary, tags, author, or publish status. |
| shopify_searchA | Unified search across products, articles, blogs, and pages. Runs parallel queries for each type and returns results grouped by type. |
| shopify_get_metafieldsA | Get metafields for any Shopify resource. Requires read access on the owner resource type (e.g. read_products for product metafields). |
| shopify_set_metafieldA | 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 |
| shopify_delete_metafieldA | Delete a metafield by GID. Get the ID first with shopify_get_metafields. |
| shopify_get_collectionsB | List all collections or search by title. Returns SEO fields, sort order, and template suffix. |
| shopify_update_collectionC | Update a collection's title, description HTML, and SEO metadata. |
| shopify_list_draft_ordersB | List draft orders with status, customer info, line items, and totals. Filter examples: "status:open", "status:completed", "customer_id:gid://shopify/Customer/123" |
| shopify_list_discountsA | List all discounts — code-based (basic, free shipping, BXGY) and automatic. Returns codes, usage counts, and discount values. Filter by query string. Examples:
|
| shopify_list_abandoned_checkoutsA | 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). |
| shopify_create_collectionA | Create a collection. Two kinds:
A collection's rule set cannot be added later — decide smart vs manual now. |
| shopify_collection_add_productsA | 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. |
| shopify_collection_remove_productsA | Remove products from a MANUAL collection. The products themselves are not deleted — only their membership of this collection. Processed asynchronously, same as adding. |
| shopify_bulk_update_variantsA | 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. |
| shopify_audit_variant_customsA | 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. |
| shopify_analytics_queryA | 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. |
| shopify_list_marketing_eventsA | 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. |
| shopify_get_customer_eventsA | 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. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
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.