Enables interaction with Shopify store data through the GraphQL Admin API, providing tools for managing products, variants, collections, customers, orders, draft orders, and navigation menus.
Click on "Install 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 MCP Servershow me the 5 most recent orders from store1"
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
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: 🚀 NPX Command:
✅ Fully API Compliant: All 35 tools have been validated against the Shopify Admin GraphQL API specification to ensure compatibility and reliability.
🌐 Deployment Modes: Now supports both local (stdio) and remote (HTTP) deployment:
Local Mode: Run directly in Claude Desktop via stdio transport
Remote Mode: Deploy as an HTTP server with OAuth 2.0 authentication on Render, Heroku, etc.
Documentation: See REMOTE_SERVER.md for remote deployment guide
Features
Multi-Store Support: Manage multiple Shopify stores from a single MCP server instance
Product Management: Create, update products, manage variants and images
Collection Management: Create, update collections and manage product associations
Customer Management: Load customer data and manage customer tags
Order Management: Advanced order querying and filtering, draft order creation
Menu Management: Create, update, and delete navigation menus
GraphQL Integration: Direct integration with Shopify's GraphQL Admin API
Comprehensive Error Handling: Clear error messages for API and authentication issues
Prerequisites
Node.js (version 16 or higher)
Shopify Custom App Access Token (see setup instructions below)
Setup
Shopify Access Token
To use this MCP server, you'll need to create a custom app in your Shopify store:
From your Shopify admin, go to Settings > Apps and sales channels
Click Develop apps (you may need to enable developer preview first)
Click Create an app
Set a name for your app (e.g., "Shopify MCP Server")
Click Configure Admin API scopes
Select the following scopes based on your needs:
read_products,write_products(for product, variant, image, and collection management)read_customers,write_customers(for customer management)read_orders,write_orders(for order and draft order management)read_online_store_navigation,write_online_store_navigation(for menu management)
Click Save
Click Install app
Click Install to give the app access to your store data
After installation, you'll see your Admin API access token
Copy this token - you'll need it for configuration
Usage with Claude Desktop
To manage Shopify stores, add this to your claude_desktop_config.json:
Important: Each store needs:
id: A unique identifier for the store (e.g., "main", "eu-store", "store1")domain: The myshopify.com domainaccessToken: The Shopify Admin API access token
All tools require a storeId parameter to specify which store to interact with. Use the list-stores tool to see available stores.
For a single store, use the same format with one store in the array:
Locations for the Claude Desktop config file:
MacOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%/Claude/claude_desktop_config.json
Alternative: Run Locally with Environment Variables
Multi-Store with Environment Variable
Create a .env file with your store configurations:
Single Store with Environment Variables
For a single store:
Then run:
Direct Installation (Optional)
If you want to install the package globally:
Then run it with the multi-store format:
Available Tools
Note: All tools (except list-stores) require a storeId parameter to specify which store to interact with.
Image Upload Best Practices
When uploading product images using the create-product-image tool, you have three options:
File Path (Most Token-Efficient): Provide the local file path
When you drag-and-drop an image into Claude, acknowledge the image but provide the file path instead
Example:
/Users/username/Downloads/product-photo.jpgThe MCP server reads the file directly, using minimal tokens
External URL: Provide a URL to an image hosted elsewhere
Example:
https://example.com/images/product.jpgMost efficient if the image is already hosted online
Base64 (Fallback): Provide base64-encoded data
Uses significantly more tokens (~33% larger than binary)
Only recommended when file path is not available
Recommended workflow in Claude Desktop:
Store Management
list-storesList all configured stores
Returns store IDs, domains, and API versions
No inputs required
Job Management
get-job-statusCheck the status of an asynchronous job (e.g., from collection product operations)
Inputs:
storeId(string, required): The store IDjobId(string, required): Job ID (GID format: gid://shopify/Job/...)
Returns: Job object with
id,done(boolean), and status messageUse this to poll job completion after async operations like
add-products-to-collectionorremove-products-from-collection
Product Management
get-productsGet all products or search by title or SKU from a specific store
Supports three modes: search by title, search by SKU, or get all products
Inputs:
storeId(string, required): The store ID to querysearchTitle(string, optional): Search products by title (supports wildcards). Example: 'shirt' finds products with 'shirt' in the titlesearchSku(string, optional): Search products by variant SKU (supports wildcards with ). Examples: 'ABC-123' for exact match, or 'ABC-' to find all SKUs starting with 'ABC-'. When provided, searchTitle is ignoredlimit(number, default: 10): Maximum number of products to return
Returns:
When searching by SKU: Products with
matchedVariantsarray containing variants that matched the searchWhen searching by title or getting all: Products with
variantsarray (first 5 variants per product)searchModefield indicates which mode was used: 'sku', 'title', or 'all'
get-variants-by-skusEfficiently fetch multiple product variants by their SKUs in a single API call
Optimized for batch operations like creating draft orders with many line items
Inputs:
storeId(string, required): The store ID to queryskus(array of strings, required): Array of SKUs to search for (max 250 per request)
Returns:
variants: Object mapping each SKU to its variant details (variantId, price, inventory, product info)summary: Object withrequested,found, andnotFoundcountsnotFoundSkus: Array of SKUs that were not found in the store
Example usage: Reduce N API calls to 1 when creating draft orders with multiple products
Note: Maximum 250 SKUs per request due to GraphQL query limits
get-product-by-idGet a specific product by ID from a specific store
Inputs:
storeId(string, required): The store ID to queryproductId(string): ID of the product to retrieve
create-productCreate new product in a specific store
Inputs:
storeId(string, required): The store ID to create product intitle(string): Title of the productdescriptionHtml(string, optional): Description of the productvendor(string, optional): Vendor of the productproductType(string, optional): Type of the producttags(array of strings, optional): Tags of the productstatus(string, optional): Status of the product "ACTIVE", "DRAFT", "ARCHIVED". Default "DRAFT"
update-productUpdate an existing product's information
Inputs:
storeId(string, required): The store IDid(string, required): Product ID (GID format)title(string, optional): Title of the productdescriptionHtml(string, optional): Description of the productvendor(string, optional): Vendor of the productproductType(string, optional): Type of the producttags(array of strings, optional): Tags of the productstatus(string, optional): Status of the product
create-product-variantCreate a new variant for an existing product
Inputs:
storeId(string, required): The store IDproductId(string, required): Product ID (GID format)price(string, optional): Price of the variantcompareAtPrice(string, optional): Compare at pricesku(string, optional): SKU of the variantbarcode(string, optional): Barcode of the variantinventoryPolicy(enum, optional): "DENY" or "CONTINUE"inventoryQuantities(array, optional): Inventory quantities at locationsoptionValues(array of objects, optional): Variant option values with option names (format:[{optionName: "Size", name: "Large"}])taxable(boolean, optional): Whether the variant is taxable
update-product-variantUpdate an existing product variant
Inputs:
storeId(string, required): The store IDproductId(string, required): Product ID (GID format)id(string, required): Variant ID (GID format)price(string, optional): Price of the variantcompareAtPrice(string, optional): Compare at pricesku(string, optional): SKU of the variantbarcode(string, optional): Barcode of the variantinventoryPolicy(enum, optional): "DENY" or "CONTINUE"inventoryQuantities(array, optional): Inventory quantities at locationsoptionValues(array of objects, optional): Variant option values with option namestaxable(boolean, optional): Whether the variant is taxable
create-product-imageCreate a new image for a product (supports URL, file path, or base64 upload)
Inputs:
storeId(string, required): The store IDproductId(string, required): Product ID (GID format)src(string, optional): URL of the image (external URL)filePath(string, optional): Local file path to the image (most token-efficient)attachment(string, optional): Base64-encoded image data (for backward compatibility)altText(string, optional): Alt text for the imagefilename(string, optional): Filename (optional, inferred from filePath if not provided)
Note: Either
src,filePath, orattachmentmust be providedRecommended: Use
filePathfor best token efficiency. When you drag-and-drop an image into Claude, provide the local file path instead of using the base64 data.
update-product-imageUpdate an existing product image's properties
Inputs:
storeId(string, required): The store IDproductId(string, required): Product ID (GID format)id(string, required): Image ID (GID format)altText(string, optional): Alt text for the image
delete-product-imageDelete a product image
Inputs:
storeId(string, required): The store IDproductId(string, required): Product ID (GID format)id(string, required): Image ID (GID format)
Collection Management
get-collectionsGet all collections or search collections from a specific store
Inputs:
storeId(string, required): The store ID to queryquery(string, optional): Search query to filter collectionslimit(number, default: 10): Number of collections to retrieve
Returns: Collections with product count, rules, images, and pagination info
get-collection-by-idGet a single collection by ID from a specific store
Inputs:
storeId(string, required): The store ID to querycollectionId(string, required): Collection ID (GID format: gid://shopify/Collection/...)
Returns: Full collection details including SEO, products (first 10), and rules
create-collectionCreate a new collection (manual or automated/smart)
Inputs:
storeId(string, required): The store IDtitle(string, required): Title of the collectiondescriptionHtml(string, optional): HTML descriptionhandle(string, optional): URL handleruleSet(object, optional): Rules for automated/smart collectionsappliedDisjunctively(boolean): Use OR (true) or AND (false) logicrules(array): Array of rule conditionscolumn(enum): Field to match (TITLE, TYPE, VENDOR, TAG, PRODUCT_METAFIELD_DEFINITION, etc.)relation(enum): Comparison operator (EQUALS, CONTAINS, GREATER_THAN, etc.)condition(string): Value to matchconditionObjectId(string, optional): Required for metafield-based rules
products(array of strings, optional): Product IDs for manual collections (GID format)image(object, optional): Collection imagesrc(string): Source URLaltText(string, optional): Alt text
sortOrder(enum, optional): How products are sorted (BEST_SELLING, MANUAL, PRICE_ASC, etc.)templateSuffix(string, optional): Template suffix
Note: Collection is unpublished by default. Use
publishablePublishmutation to publish.
update-collectionUpdate an existing collection
Inputs: Same as create-collection, plus:
id(string, required): Collection ID (GID format)
add-products-to-collectionAdd products to a manual collection (asynchronous operation)
Inputs:
storeId(string, required): The store IDid(string, required): Collection ID (GID format)productIds(array of strings, required): Product IDs to add (GID format, up to 250 products)
Returns: Job object with
idanddonestatus for tracking the async operationNote: Uses
collectionAddProductsV2mutation which processes asynchronously
remove-products-from-collectionRemove products from a manual collection (asynchronous operation)
Inputs:
storeId(string, required): The store IDid(string, required): Collection ID (GID format)productIds(array of strings, required): Product IDs to remove (GID format, up to 250 products)
Returns: Job object with
idanddonestatus for tracking the async operationNote: Only works with manual collections (not smart/automated collections)
Customer Management
get-customersGet customers or search by name/email from a specific store
Inputs:
storeId(string, required): The store ID to querysearchQuery(optional string): Filter customers by name or emaillimit(optional number, default: 10): Maximum number of customers to return
get-customer-by-idGet a single customer by ID with detailed information
Inputs:
storeId(string, required): The store ID to querycustomerId(string, required): Customer ID (GID format: gid://shopify/Customer/...)
Returns: Full customer details including addresses, state, tax exemption, spending history, and recent orders (first 10)
create-customerCreate a new customer in a specific store
Inputs:
storeId(string, required): The store IDfirstName(string, required): Customer's first namelastName(string, required): Customer's last nameemail(string, required): Customer's email addressphone(string, optional): Customer's phone numbertags(array of strings, optional): Tags to associate with the customernote(string, optional): Note about the customertaxExempt(boolean, optional): Whether the customer is exempt from taxesaddresses(array of objects, optional): Customer addresses with address1, address2, city, country, province, zip, etc.metafields(array of objects, optional): Metafields to associate with the customer
update-customerUpdate a customer's information in a specific store
Inputs:
storeId(string, required): The store ID to update customer inid(string, required): Shopify customer ID (numeric ID only, like "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 taxesmetafields(array of objects, optional): Customer metafields for storing additional data
get-customer-ordersGet orders for a specific customer from a specific store
Inputs:
storeId(string, required): The store ID to querycustomerId(string, required): Shopify customer ID (numeric ID only, like "6276879810626")limit(optional number, default: 10): Maximum number of orders to return
Order Management
get-ordersGet orders with optional filtering from a specific store
Inputs:
storeId(string, required): The store ID to querystatus(optional string): Filter by order statuslimit(optional number, default: 10): Maximum number of orders to return
get-order-by-idGet a specific order by ID from a specific store
Inputs:
storeId(string, required): The store ID to queryorderId(string, required): Full Shopify order ID (e.g., "gid://shopify/Order/6090960994370")
update-orderUpdate an existing order with new information in a specific store
Inputs:
storeId(string, required): The store ID to update order inid(string, required): Shopify order IDtags(array of strings, optional): New tags for the orderemail(string, optional): Update customer emailnote(string, optional): Order notescustomAttributes(array of objects, optional): Custom attributes for the ordermetafields(array of objects, optional): Order metafieldsshippingAddress(object, optional): Shipping address information
Draft Order Management
get-draft-ordersGet all draft orders or search draft orders from a specific store
Inputs:
storeId(string, required): The store ID to queryquery(string, optional): Search query to filter draft orderslimit(number, default: 10): Number of draft orders to retrieve
Returns: Draft orders with line items (first 10), customer info, and pagination info
get-draft-order-by-idGet a single draft order by ID from a specific store
Inputs:
storeId(string, required): The store ID to querydraftOrderId(string, required): Draft Order ID (GID format: gid://shopify/DraftOrder/...)
Returns: Complete draft order details including line items (first 50), addresses, shipping, discounts, and full pricing breakdown
create-draft-orderCreate a new draft order
Inputs:
storeId(string, required): The store IDlineItems(array, required): Line items for the ordercustomerId(string, optional): Customer ID (GID format)email(string, optional): Customer emailphone(string, optional): Customer phoneshippingAddress(object, optional): Shipping addressbillingAddress(object, optional): Billing addressnote(string, optional): Note for the draft order (input uses 'note', response returns 'note2')tags(array of strings, optional): TagstaxExempt(boolean, optional): Tax exemption statusshippingLine(object, optional): Shipping details
update-draft-orderUpdate an existing draft order
Inputs: Same as create-draft-order, plus:
id(string, required): Draft Order ID (GID format)
Menu Management
get-menusGet all navigation menus from a specific store
Inputs:
storeId(string, required): The store ID to querylimit(number, default: 10): Number of menus to retrieve
Returns: Menus with nested items (up to 3 levels) and pagination info
get-menuGet a single navigation menu by ID from a specific store
Inputs:
storeId(string, required): The store ID to querymenuId(string, required): Menu ID (GID format: gid://shopify/Menu/...)
Returns: Complete menu structure with nested items (up to 3 levels deep)
create-menuCreate a new navigation menu
Inputs:
storeId(string, required): The store IDtitle(string, required): Title of the menuhandle(string, required): URL handle for the menuitems(array, required): Menu items with nested structure supportEach item must have:
title(string, required): Title of the menu itemtype(enum, required): Type of menu item - "FRONTPAGE", "COLLECTIONS", "COLLECTION", "PRODUCT", "CATALOG", "PAGE", "BLOG", "ARTICLE", "POLICY", "HTTP", "SHOP_POLICY"url(string, optional): URL for the menu item (can be relative or absolute)resourceId(string, optional): Resource ID if linking to a product, collection, etc. (GID format)tags(array of strings, optional): Tags to filter a collectionitems(array, optional): Nested menu items for submenus
update-menuUpdate an existing navigation menu
Inputs:
storeId(string, required): The store IDid(string, required): Menu ID (GID format)title(string, required): Title of the menuhandle(string, optional): URL handle for the menuitems(array, required): Menu items (replaces all existing items)Same structure as create-menu items, plus:
id(string, optional): Menu item ID (GID format) - for updating existing items
delete-menuDelete a navigation menu
Inputs:
storeId(string, required): The store IDid(string, required): Menu ID (GID format)
Debugging
Viewing MCP Logs
If you encounter issues, check Claude Desktop's MCP logs:
Debug Logging
To enable detailed debug logging, set the DEBUG environment variable to true in your Claude Desktop config:
Debug logging will show:
Request start/completion timestamps
GraphQL query variables
Detailed error information
Permission-related errors
Request Timeout Configuration
By default, GraphQL requests timeout after 30 seconds. You can customize this with the GRAPHQL_TIMEOUT_MS environment variable:
Common Issues
Request hangs or times out:
Check that your Shopify app has the required API scopes (see Installation)
Verify your access token is valid
Check network connectivity to Shopify
Enable
DEBUG=trueto see detailed request logs
Permission errors:
Errors will indicate which scopes are missing
Go to Shopify Admin > Settings > Apps and sales channels > [Your App] > Configuration
Add the required scopes and reinstall the app
API Compliance
This server has been thoroughly validated against the Shopify Admin GraphQL API specification:
✅ 35 tools validated - All GraphQL operations comply with current Shopify Admin API
✅ API version 2023-07 - Default version, configurable per store
✅ Comprehensive validation - All mutations and queries have been verified using Shopify's schema validation tools
Key API Changes Implemented
The following tools have been updated to use the latest Shopify API patterns:
Product Variants: Uses
productVariantsBulkCreateandproductVariantsBulkUpdatemutationsProduct Images: Uses media-based API (
productCreateMedia,productUpdateMedia,productDeleteMedia)Menu Management: Uses direct mutation arguments with
MenuItemCreateInputandMenuItemUpdateInputCollections: Supports both manual and automated/smart collections with async operations
Development
To contribute or modify this project:
Project Structure
src/index.ts- Main server initialization and tool registrationsrc/stores/- Store management and configuration parsingsrc/tools/- Individual tool implementations for Shopify operations
License
MIT