A solid connector for the Shopify GraphQL Admin API that gives you full CRUD operations across products, customers, orders, and metafields directly from Claude or Cursor. Handles both modern client credentials auth and legacy access tokens, supports cursor-based pagination, and includes advanced filtering with Shopify's query syntax. You get 31 tools covering everything from inventory management to order fulfillment and refunds. The server automatically manages token refresh for OAuth apps and provides comprehensive error handling. Ideal when you need to automate Shopify store operations or build custom workflows that span multiple store resources without writing API boilerplate.
(please leave a star if you like!)
MCP Server for Shopify API, enabling interaction with store data through GraphQL API. This server provides tools for managing products, customers, orders, and more.
📦 Package Name: shopify-mcp
🚀 Command: shopify-mcp (NOT shopify-mcp-server)
This server supports two authentication methods:
As of January 1, 2026, new Shopify apps are created in the Dev Dashboard and use OAuth client credentials instead of static access tokens.
read_products, write_productsread_customers, write_customersread_orders, write_ordersThe server will automatically exchange these for an access token and refresh it before it expires (tokens are valid for ~24 hours).
If you have an existing custom app with a static shpat_ access token, you can still use it directly.
Client Credentials (recommended):
{
"mcpServers": {
"shopify": {
"command": "npx",
"args": [
"shopify-mcp",
"--clientId",
"<YOUR_CLIENT_ID>",
"--clientSecret",
"<YOUR_CLIENT_SECRET>",
"--domain",
"<YOUR_SHOP>.myshopify.com"
]
}
}
}
Static Access Token (legacy):
{
"mcpServers": {
"shopify": {
"command": "npx",
"args": [
"shopify-mcp",
"--accessToken",
"<YOUR_ACCESS_TOKEN>",
"--domain",
"<YOUR_SHOP>.myshopify.com"
]
}
}
}
Locations for the Claude Desktop config file:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%/Claude/claude_desktop_config.jsonClient Credentials:
claude mcp add shopify -- npx shopify-mcp \
--clientId YOUR_CLIENT_ID \
--clientSecret YOUR_CLIENT_SECRET \
--domain your-store.myshopify.com
Static Access Token (legacy):
claude mcp add shopify -- npx shopify-mcp \
--accessToken YOUR_ACCESS_TOKEN \
--domain your-store.myshopify.com
If you prefer to use environment variables instead of command-line arguments:
Create a .env file with your Shopify credentials:
Client Credentials:
SHOPIFY_CLIENT_ID=your_client_id
SHOPIFY_CLIENT_SECRET=your_client_secret
MYSHOPIFY_DOMAIN=your-store.myshopify.com
Static Access Token (legacy):
SHOPIFY_ACCESS_TOKEN=your_access_token
MYSHOPIFY_DOMAIN=your-store.myshopify.com
Run the server with npx:
npx shopify-mcp
If you want to install the package globally:
npm install -g shopify-mcp
Then run it:
shopify-mcp --clientId=<ID> --clientSecret=<SECRET> --domain=<YOUR_SHOP>.myshopify.com
--apiVersion: Specify the Shopify API version (default: 2026-01). Can also be set via SHOPIFY_API_VERSION environment variable.⚠️ Important: If you see errors about "SHOPIFY_ACCESS_TOKEN environment variable is required" when using command-line arguments, you might have a different package installed. Make sure you're using shopify-mcp, not shopify-mcp-server.
All list query tools (get-products, get-customers, get-orders, get-customer-orders) support:
after / before (cursor strings), with pageInfo in the response (hasNextPage, hasPreviousPage, startCursor, endCursor)sortKey (enum specific to each resource) and reverse (boolean)query or searchQuery parameter accepting Shopify query syntaxget-products
searchTitle (string, optional): Filter products by title (wraps in title:*...*)limit (number, default: 10): Maximum number of products to returnquery (string, optional): Raw Shopify query string (e.g. "status:active vendor:Nike tag:sale")sortKey (string, optional): One of CREATED_AT, ID, INVENTORY_TOTAL, PRODUCT_TYPE, PUBLISHED_AT, RELEVANCE, TITLE, UPDATED_AT, VENDORreverse (boolean, optional): Reverse the sort orderafter / before (string, optional): Pagination cursorsget-product-by-id
productId (string, required): Shopify product GIDproductType, descriptionHtml, seo, options (with optionValues), media (images), variants, collections, tags, vendor, price range, inventorycreate-product
productOptions, Shopify registers all option values but only creates one default variant (first value of each option, price $0). Use manage-product-variants with strategy: REMOVE_STANDALONE_VARIANT afterward to create all real variants with prices.title (string, required): Title of the productdescriptionHtml (string, optional): Description with HTMLhandle (string, optional): URL slug. Auto-generated from title if omittedvendor (string, optional): Vendor of the productproductType (string, optional): Type of the producttags (array of strings, optional): Product tagsstatus (string, optional): "ACTIVE", "DRAFT", or "ARCHIVED". Default "DRAFT"seo (object, optional): { title, description } for search enginesmetafields (array of objects, optional): Custom metafields (namespace, key, value, type)productOptions (array of objects, optional): Options to create inline, e.g. [{ name: "Size", values: [{ name: "S" }, { name: "M" }] }]. Max 3 options.collectionsToJoin (array of strings, optional): Collection GIDs to add the product toupdate-product
id (string, required): Shopify product GIDtitle (string, optional): New titledescriptionHtml (string, optional): New descriptionhandle (string, optional): New URL slugvendor (string, optional): New vendorproductType (string, optional): New product typetags (array of strings, optional): New tags (overwrites existing)status (string, optional): "ACTIVE", "DRAFT", or "ARCHIVED"seo (object, optional): { title, description } for search enginesmetafields (array of objects, optional): Metafields to set or updatecollectionsToJoin (array of strings, optional): Collection GIDs to add the product tocollectionsToLeave (array of strings, optional): Collection GIDs to remove the product fromredirectNewHandle (boolean, optional): If true, old handle redirects to new handledelete-product
id (string, required): Shopify product GIDmanage-product-options
productId (string, required): Shopify product GIDaction (string, required): "create", "update", or "delete"variantStrategy (string, optional): "LEAVE_AS_IS" (default) or "CREATE" — controls whether new variant combinations are generated when adding optionsaction: "create":
options (array, required): Options to create, e.g. [{ name: "Size", values: ["S", "M", "L"] }]action: "update":
optionId (string, required): Option GID to updatename (string, optional): New name for the optionposition (number, optional): New positionvaluesToAdd (array of strings, optional): Values to addvaluesToDelete (array of strings, optional): Value GIDs to removeaction: "delete":
optionIds (array of strings, required): Option GIDs to deletemanage-product-variants
productId (string, required): Shopify product GIDstrategy (string, optional): How to handle the default variant when creating. "DEFAULT" (removes "Default Title" automatically), "REMOVE_STANDALONE_VARIANT" (recommended for full control), or "PRESERVE_STANDALONE_VARIANT"variants (array, required): Variants to create or update. Each variant:
id (string, optional): Variant GID for updates. Omit to create newprice (string, optional): Price, e.g. "49.00"compareAtPrice (string, optional): Compare-at price for showing discountssku (string, optional): SKU (mapped to inventoryItem.sku)tracked (boolean, optional): Whether inventory is tracked. Set false for print-on-demandtaxable (boolean, optional): Whether the variant is taxablebarcode (string, optional): Barcodeweight (number, optional): Weight of the variantweightUnit (string, optional): "GRAMS", "KILOGRAMS", "OUNCES", or "POUNDS"optionValues (array, optional): Option values, e.g. [{ optionName: "Size", name: "A4" }]delete-product-variants
productId (string, required): Shopify product GIDvariantIds (array of strings, required): Variant GIDs to deleteget-customers
searchQuery (string, optional): Freetext or Shopify query syntax (e.g. "country:US tag:vip orders_count:>5")limit (number, default: 10): Maximum number of customers to returnsortKey (string, optional): One of CREATED_AT, ID, LAST_UPDATE, LOCATION, NAME, ORDERS_COUNT, RELEVANCE, TOTAL_SPENT, UPDATED_ATreverse (boolean, optional): Reverse the sort orderafter / before (string, optional): Pagination cursorsget-customer-by-id
id (string, required): Shopify customer ID (numeric only, e.g. "6276879810626")create-customer
firstName (string, optional): Customer's first namelastName (string, optional): Customer's last nameemail (string, optional): Customer's email addressphone (string, optional): Customer's phone numbertags (array of strings, optional): Tags to applynote (string, optional): Note about the customertaxExempt (boolean, optional): Whether the customer is exempt from taxesmetafields (array of objects, optional): Custom metafields (namespace, key, value, type)addresses (array of objects, optional): Customer addresses (address1, address2, city, provinceCode, zip, country, phone)update-customer
id (string, required): Shopify customer ID (numeric only, e.g. "6276879810626")firstName (string, optional): Customer's first namelastName (string, optional): Customer's last nameemail (string, optional): Customer's email addressphone (string, optional): Customer's phone numbertags (array of strings, optional): Tags to apply to the customernote (string, optional): Note about the customertaxExempt (boolean, optional): Whether the customer is exempt from taxesemailMarketingConsent (object, optional): Email marketing consent settings
marketingState (string, required): "NOT_SUBSCRIBED", "SUBSCRIBED", "UNSUBSCRIBED", or "PENDING"consentUpdatedAt (string, optional): ISO 8601 timestampmarketingOptInLevel (string, optional): "SINGLE_OPT_IN", "CONFIRMED_OPT_IN", or "UNKNOWN"metafields (array of objects, optional): Customer metafieldsdelete-customer
id (string, required): Shopify customer ID (numeric only, e.g. "6276879810626")customer-merge
customerOneId (string, required): GID of the first customercustomerTwoId (string, required): GID of the second customeroverrideFields (object, optional): Override which fields to keep from which customer (firstName, lastName, email, phone, defaultAddress, note, tags)manage-customer-address
customerId (string, required): Customer GIDaction (string, required): "create", "update", or "delete"addressId (string, optional): Address GID (required for update/delete)address (object, optional): Address fields (required for create/update): address1, address2, city, company, countryCode, firstName, lastName, phone, provinceCode, zipsetAsDefault (boolean, optional): Set as customer's default addressget-orders
status (string, optional): "any", "open", "closed", or "cancelled". Default "any"limit (number, default: 10): Maximum number of orders to returnquery (string, optional): Raw Shopify query string (e.g. "financial_status:paid fulfillment_status:shipped tag:rush")sortKey (string, optional): One of CREATED_AT, ORDER_NUMBER, TOTAL_PRICE, FINANCIAL_STATUS, FULFILLMENT_STATUS, UPDATED_AT, CUSTOMER_NAME, PROCESSED_AT, ID, RELEVANCEreverse (boolean, optional): Reverse the sort orderafter / before (string, optional): Pagination cursorsget-order-by-id
#77235 or 77235), numeric ID (8054938337547), or full GID (gid://shopify/Order/...)orderId (string, required): Order name, numeric ID, or full GIDupdate-order
id (string, required): Shopify order GIDtags (array of strings, optional): New tags for the orderemail (string, optional): Update customer email on the ordernote (string, optional): Order notesphone (string, optional): Phone number for the orderpoNumber (string, optional): Purchase order numbercustomAttributes (array of objects, optional): Custom key-value attributesmetafields (array of objects, optional): Order metafieldsshippingAddress (object, optional): Shipping address fieldsget-customer-orders
customerId (string, required): Shopify customer ID (numeric only, e.g. "6276879810626")limit (number, default: 10): Maximum number of orders to returnsortKey (string, optional): Same sort keys as get-ordersreverse (boolean, optional): Reverse the sort orderafter / before (string, optional): Pagination cursorsorder-cancel
orderId (string, required): Order GIDreason (string, required): "CUSTOMER", "DECLINED", "FRAUD", "INVENTORY", "OTHER", or "STAFF"restock (boolean, required): Whether to restock inventorynotifyCustomer (boolean, default: false): Notify the customerstaffNote (string, optional): Internal noterefund (boolean, optional): Refund to original payment methodorder-close-open
orderId (string, required): Order GIDaction (string, required): "close" or "open"order-mark-as-paid
orderId (string, required): Order GIDcreate-fulfillment
lineItemsByFulfillmentOrder (array, required): Fulfillment orders and line items to fulfilltrackingInfo (object, optional): { number, url, company } tracking detailsnotifyCustomer (boolean, default: false): Send shipping notificationrefund-create
orderId (string, required): Order GIDrefundLineItems (array, optional): Line items to refund with lineItemId, quantity, restockType (CANCEL/RETURN/NO_RESTOCK), locationIdshipping (object, optional): { amount, fullRefund } shipping refundnote (string, optional): Refund notenotify (boolean, optional): Send refund notificationcreate-draft-order
lineItems (array, required): Product variants (variantId) or custom items (title + price). Max 499customerId (string, optional): Customer GIDemail, phone, note, tags, poNumber (optional)shippingAddress, billingAddress (objects, optional)appliedDiscount (object, optional): { title, value, valueType } order-level discountcomplete-draft-order
draftOrderId (string, required): Draft order GIDpaymentGatewayId (string, optional): Payment gateway GIDget-metafields
ownerId (string, required): GID of any resourcenamespace (string, optional): Filter by namespacefirst (number, default: 25): Number of metafields to returnafter (string, optional): Pagination cursorset-metafields
metafields (array, required): Metafields to set, each with ownerId, key, value, and optional namespace, typedelete-metafields
metafields (array, required): Metafields to delete, each with ownerId, namespace, keyinventory-set-quantities
reason (string, required): Reason for change (e.g. "correction", "cycle_count_available")name (string, required): "available" or "on_hand"quantities (array, required): Items with inventoryItemId, locationId, quantitymanage-tags
id (string, required): GID of the resourcetags (array of strings, required): Tags to add or removeaction (string, required): "add" or "remove"The get-orders tool's query parameter supports Shopify search syntax:
| Filter | Example |
|---|---|
name | name:#77235 |
created_at | created_at:>2024-01-01 or created_at:2024-01-01..2024-03-31 |
updated_at | updated_at:>2024-06-01 |
financial_status | financial_status:paid |
fulfillment_status | fulfillment_status:shipped |
status | status:open |
email | email:customer@example.com |
tag / tag_not | tag:vip tag_not:wholesale |
discount_code | discount_code:SUMMER20 |
sku | sku:PROD-001 |
risk_level | risk_level:high |
gateway | gateway:shopify_payments |
test | test:true |
If you encounter issues, check Claude Desktop's MCP logs:
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
MIT
com.mcparmory/google-sheets
domdomegg/google-sheets-mcp
henilcalagiya/google-sheets-mcp
cct15/war-dashboard-data
moooonad/mcp-google-sheets-full
io.github.br0ski777/csv-to-json