Shopify MCP Server
Enables interaction with Shopify store data through GraphQL API, providing tools for managing products, customers, orders, blogs, and articles.
README Documentation
Shopify MCP Server
(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)
Features
- Product Management: Search, retrieve, and update product information, including SEO-optimized content
- Customer Management: Load customer data and manage customer tags
- Order Management: Advanced order querying and filtering
- Blog Management: Create, retrieve, and update blogs with custom templates and comment policies
- Article Management: Create and manage blog articles with rich content, author information, and SEO metadata
- Store Search: Unified search across products, articles, blogs, and pages
- GraphQL Integration: Direct integration with Shopify's GraphQL Admin API
- Comprehensive Error Handling: Clear error messages for API and authentication issues
- LLM-Optimized: Designed for seamless use with AI language models
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:
read_products,write_productsread_customers,write_customersread_orders,write_ordersread_content,write_content(for blogs and articles)
- 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
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"shopify": {
"command": "npx",
"args": [
"shopify-mcp",
"--accessToken",
"<YOUR_ACCESS_TOKEN>",
"--domain",
"<YOUR_SHOP>.myshopify.com"
]
}
}
}
Locations for the Claude Desktop config file:
- MacOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json
Alternative: Run Locally with Environment Variables
If you prefer to use environment variables instead of command-line arguments:
-
Create a
.envfile with your Shopify credentials:SHOPIFY_ACCESS_TOKEN=your_access_token MYSHOPIFY_DOMAIN=your-store.myshopify.com -
Run the server with npx:
npx shopify-mcp
Direct Installation (Optional)
If you want to install the package globally:
npm install -g shopify-mcp
Then run it:
shopify-mcp --accessToken=<YOUR_ACCESS_TOKEN> --domain=<YOUR_SHOP>.myshopify.com
⚠️ 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.
Available Tools
Product Management
-
get-products- Get products or search by title with cursor-based navigation
- Inputs:
searchTitle(optional string): Filter products by titlelimit(optional number, default: 10): Maximum number of products to returnafter(optional string): Cursor for pagination - get items after this cursorbefore(optional string): Cursor for pagination - get items before this cursorreverse(optional boolean, default: false): Reverse the order of the returned products
- Returns:
- Object containing:
products: Array of products, each containing:title: Product title (SEO-optimized)description: Plain text product descriptiondescriptionHtml: HTML-formatted product description- Additional fields: id, handle, status, inventory, pricing, etc.
cursor: Cursor for pagination
pageInfo: Pagination information containing:hasNextPage: Whether there are more items after the current pagehasPreviousPage: Whether there are more items before the current pagestartCursor: Cursor for the first item in the current pageendCursor: Cursor for the last item in the current page
- Object containing:
🌟 Navigation Examples:
- Basic Pagination:
// Get first page of products { "limit": 10 } // Get next page using the endCursor from previous response { "limit": 10, "after": "endCursor_from_previous_response" } // Get previous page using the startCursor from current response { "limit": 10, "before": "startCursor_from_current_response" }- Search with Pagination:
// Search products with pagination { "searchTitle": "t-shirt", "limit": 5, "after": "cursor_from_previous_response" }- Reverse Order:
// Get products in reverse order { "limit": 10, "reverse": true }💡 Pagination Tips:
- Store both
startCursorandendCursorfrom each response - Use
hasNextPageandhasPreviousPageto show/hide navigation controls - Keep the same
limitvalue for consistent page sizes - Use
reversewhen you need newest/oldest items first - Combine with
searchTitlefor paginated search results
-
get-product-by-id- Get a specific product by ID with all its details
- Inputs:
productId(string): The GID of the product to fetch (e.g., "gid://shopify/Product/1234567890")
- Returns:
- Single product object containing:
title: Product title (SEO-optimized)description: Plain text product descriptiondescriptionHtml: HTML-formatted product description- Additional fields: id, handle, status, inventory, pricing, variants, collections, etc.
- Single product object containing:
-
update-product- Update any aspect of a product including basic details, SEO, and variants
- Inputs:
productId(required string): The product's ID (e.g., "gid://shopify/Product/1234567890")title(optional string): New product titledescriptionHtml(optional string): Product description in HTML formatseo(optional object): SEO settingstitle(optional string): SEO-optimized titledescription(optional string): Meta description for search engines
status(optional string): Product status - "ACTIVE", "ARCHIVED", or "DRAFT"vendor(optional string): Product manufacturer or brandproductType(optional string): Category or type of producttags(optional array of strings): Product tags for categorizationvariants(optional array of objects): Product variants to updateid(string): Variant ID to updateprice(optional string): New pricecompareAtPrice(optional string): Original/compare-at pricesku(optional string): Stock Keeping Unitbarcode(optional string): Product barcodeinventoryPolicy(optional string): "DENY" or "CONTINUE" for out-of-stock behavior
🌟 Beginner's Guide to Updating Products
- Basic Product Update:
// Update product title and status { "productId": "gid://shopify/Product/1234567890", "title": "Awesome T-Shirt", "status": "ACTIVE" }- Update SEO Information:
// Make your product more visible in search results { "productId": "gid://shopify/Product/1234567890", "seo": { "title": "Awesome T-Shirt | 100% Cotton | Available in 5 Colors", "description": "High-quality cotton t-shirt perfect for everyday wear. Available in multiple colors and sizes." } }- Update Product Variants:
// Change prices and inventory settings { "productId": "gid://shopify/Product/1234567890", "variants": [ { "id": "gid://shopify/ProductVariant/1234567", "price": "29.99", "compareAtPrice": "39.99", "inventoryPolicy": "DENY" } ] }- Complete Product Update:
// Update multiple aspects at once { "productId": "gid://shopify/Product/1234567890", "title": "Premium Cotton T-Shirt", "vendor": "Fashion Basics", "productType": "Apparel", "tags": ["cotton", "t-shirt", "basics", "summer"], "seo": { "title": "Premium Cotton T-Shirt | Fashion Basics | Multiple Colors", "description": "Experience comfort with our premium cotton t-shirt. Perfect for any occasion." }, "variants": [ { "id": "gid://shopify/ProductVariant/1234567", "price": "29.99", "compareAtPrice": "39.99" } ] }💡 Tips for New Users:
- Start Small: Begin with simple updates (like title or price) before trying complex changes
- Test First: Always test updates on a draft product before modifying live products
- Check IDs: Make sure you have the correct product and variant IDs
- SEO Best Practices:
- Keep SEO titles under 60 characters
- Write descriptive meta descriptions (150-160 characters)
- Include relevant keywords naturally
- Pricing Strategy:
- Use
compareAtPriceto show savings - Keep prices consistent across variants unless size/material differs
- Use
- Inventory Management:
- Use "DENY" for limited stock items
- Use "CONTINUE" for made-to-order items
⚠️ Common Mistakes to Avoid:
- Forgetting to include the product ID
- Using wrong ID formats (always use the full GID format)
- Setting invalid prices (must be strings, not numbers)
- Mixing up variant IDs
- Using HTML in regular text fields
🔍 How to Find IDs:
- Product ID: Available in the product URL or using
get-products - Variant ID: Use
get-product-by-idto see all variants - Always use the full GID format: "gid://shopify/Product/1234567890"
-
update-product-image-alt-text- Update the alt text for a specific product image
- Inputs:
productId(string): The GID of the product to which the image belongs (e.g., "gid://shopify/Product/1234567890")imageId(string): The GID of the product image/media to update (e.g., "gid://shopify/MediaImage/123")altText(string | null): The new descriptive alt text for the image. Set to null to remove. Best practice is to keep it under 125 characters, max 512.
- Returns:
- Updated media object containing:
id: The media IDaltText: The updated alt text
- Updated media object containing:
Collection Management
get-collections- Get collections or search by title
- Inputs:
searchTitle(optional string): Filter collections by titlelimit(optional number, default: 10): Maximum number of collections to return
Blog Management
-
get-blogs- Get all blogs or search by title
- Inputs:
searchTitle(optional string): Filter blogs by titlelimit(optional number, default: 10): Maximum number of blogs to return
- Returns:
- Array of blogs containing:
id: Blog IDtitle: Blog titlehandle: URL-friendly handletemplateSuffix: Template suffix for custom themescommentPolicy: Comment moderation policycreatedAt: Creation timestampupdatedAt: Last update timestamp
- Array of blogs containing:
-
update-blog- Update an existing blog's details
- Inputs:
blogId(string, required): The GID of the blog to update (e.g., "gid://shopify/Blog/1234567890")title(optional string): New blog titlehandle(optional string): New URL-friendly handletemplateSuffix(optional string): New template suffix for custom themescommentPolicy(optional string): New comment policy ("MODERATED" or "CLOSED")
- Returns:
- Updated blog object with the modified fields
-
get-blog-by-id- Get a specific blog by ID with all its details
- Inputs:
blogId(string, required): The GID of the blog to fetch
- Returns:
- Blog object containing:
id: Blog IDtitle: Blog titlehandle: URL-friendly handletemplateSuffix: Template suffixcommentPolicy: Comment policyarticles: Recent articles (first 5)
- Blog object containing:
Article Management
-
get-articles- Get articles from a specific blog
- Inputs:
blogId(string, required): The GID of the blog to get articles fromsearchTitle(optional string): Filter articles by titlelimit(optional number, default: 10): Maximum number of articles to return
- Returns:
- Array of articles containing:
id: Article IDtitle: Article titlehandle: URL-friendly handleauthor: Author informationpublishedAt: Publication datetags: Associated tagsimage: Featured image (if any)
- Array of articles containing:
-
create-article- Create a new article in a specified blog
- Inputs:
blogId(string, required): The GID of the blog to create the article intitle(string, required): The title of the articlecontent(string, required): The content of the article in HTML formatauthor(object, required):name(string, required): The name of the article's author
published(optional boolean): Whether to publish immediately (default: false)tags(optional array of strings): Tags to categorize the article
- Returns:
- Created article object containing:
id: Article IDtitle: Article titlehandle: URL-friendly handle (auto-generated from title)body: Article contentsummary: Article summary (if provided)author: Author informationtags: Associated tagsimage: Featured image details (if provided)
- Created article object containing:
- Example Usage:
// Create a published article with formatted content { "blogId": "gid://shopify/Blog/123456789", "title": "My New Article", "content": "<p>Article content with <strong>HTML formatting</strong>.</p>", "author": { "name": "John Doe" }, "published": true, "tags": ["news", "updates"] } // Create a draft article with future publication { "blogId": "gid://shopify/Blog/123456789", "title": "Upcoming Article", "content": "<p>Draft content...</p>", "author": { "name": "Jane Smith" }, "published": false, "tags": ["draft"] }
-
update-article- Update an existing article's details
- Inputs:
articleId(string, required): The GID of the article to updatetitle(optional string): New article titlebody(optional string): New article contentsummary(optional string): New article summarytags(optional array of strings): New article tagsauthor(optional object): Author informationname(string): Author's name
- Returns:
- Updated article object with the modified fields
-
get-article-by-id- Get a specific article by ID with all its details
- Inputs:
articleId(string, required): The GID of the article to fetch
- Returns:
- Article object containing:
id: Article IDtitle: Article titlehandle: URL-friendly handleauthor: Author informationbody: Article contentblog: Parent blog informationtags: Associated tags
- Article object containing:
Important Notes for Blog and Article Management
-
Working with Blog Content
- Always use
get-blogsfirst to obtain valid blog IDs - Use
get-blog-by-idto fetch detailed information about a specific blog - When updating blogs, only include the fields you want to modify
- The
commentPolicycan only be set to "MODERATED" or "CLOSED"
- Always use
-
Working with Articles
- Articles must be associated with an existing blog
- Use
get-articlesto list articles within a specific blog - When creating or updating articles, the
bodyfield supports HTML content - Author information should always include at least the name
- Tags are case-sensitive and should be consistent across articles
- Image URLs must be publicly accessible
- Handle creation is optional - Shopify will generate one from the title if not provided
-
Best Practices for Article Creation
- Use semantic HTML for article content (e.g.,
<p>,<h2>,<ul>, etc.) - Keep article summaries concise (recommended: 150-160 characters)
- Use consistent tag naming conventions
- Always verify blog IDs before creating articles
- Consider SEO implications when writing titles and content
- Test HTML formatting in a staging environment first
- For drafts, set
published: falseto save without publishing - When using tags, maintain a consistent taxonomy
- Provide descriptive alt text for any images
- Schedule articles strategically using publishDate
- Keep HTML content clean and well-structured
- Use meaningful handles for better SEO
- Consider mobile readability when formatting content
- Use semantic HTML for article content (e.g.,
-
Article Creation Tips
- HTML Content: The content field accepts HTML markup for rich formatting:
<p>First paragraph with <strong>bold text</strong>.</p> <h2>Section Heading</h2> <ul> <li>List item one</li> <li>List item two</li> </ul> - Tags: Use descriptive, consistent tags for better organization:
"tags": ["product-updates", "how-to", "tips"] - Draft Mode: Create unpublished drafts by setting published to false:
{ "published": false, // other fields... } - Author Information: Always provide complete author details:
"author": { "name": "Full Author Name" }
- HTML Content: The content field accepts HTML markup for rich formatting:
Store Search
search-shopify- Perform a unified search across products, articles, blogs, and pages
- Inputs:
query(string, required): The search query to find content across the storetypes(optional array of strings): Types of resources to search for. Available types:- "ARTICLE"
- "BLOG"
- "PAGE"
- "PRODUCT"
first(optional number, default: 10, max: 50): Number of results to return
- Returns:
- Array of search results, each containing:
id: Resource IDtitle: Resource titletype: Resource typeurl: Resource URL- Additional fields based on resource type
- Array of search results, each containing:
- Example Usage:
// Search for articles and blogs about "kawaii" { "query": "kawaii", "types": ["ARTICLE", "BLOG"], "first": 5 } // Search across all content types { "query": "new collection", "first": 10 }
Page Management
-
get-pages- Get all pages or search by title
- Inputs:
searchTitle(optional string): Filter pages by titlelimit(optional number, default: 10): Maximum number of pages to return
- Returns:
- Array of pages containing:
id: Page IDtitle: Page titlehandle: URL-friendly handlebody: Page contentbodySummary: Content summarycreatedAt: Creation timestampupdatedAt: Last update timestamp
- Array of pages containing:
-
update-page- Update an existing page's details
- Inputs:
pageId(string, required): The GID of the page to update (e.g., "gid://shopify/Page/1234567890")title(optional string): New page titlebody(optional string): New page contentbodyHtml(optional string): New HTML contentseo(optional object): SEO settingstitle(optional string): SEO titledescription(optional string): SEO description
published(optional boolean): Whether the page is published
- Returns:
- Updated page object with modified fields
- Example Usage:
// Update page content and SEO { "pageId": "gid://shopify/Page/123456789", "title": "About Our Store", "bodyHtml": "<h1>Welcome!</h1><p>Learn about our story...</p>", "seo": { "title": "About Us - Kawaii Store", "description": "Discover our journey in bringing kawaii culture to you" } }
Collection Management
-
get-collections- Get all collections or search by title
- Inputs:
searchTitle(optional string): Filter collections by titlelimit(optional number, default: 10): Maximum number of collections to return
- Returns:
- Array of collections containing:
id: Collection IDtitle: Collection titlehandle: URL-friendly handledescription: Collection descriptiondescriptionHtml: HTML-formatted descriptionupdatedAt: Last update timestampproductsCount: Number of products in collection
- Array of collections containing:
-
update-collection- Update an existing collection's details
- Inputs:
collectionId(string, required): The GID of the collection to updatetitle(optional string): New collection titledescription(optional string): New collection descriptiondescriptionHtml(optional string): New HTML descriptionseo(optional object): SEO settingstitle(optional string): SEO titledescription(optional string): SEO description
- Returns:
- Updated collection object with modified fields
- Example Usage:
// Update collection with SEO optimization { "collectionId": "gid://shopify/Collection/123456789", "title": "Summer Kawaii Collection", "descriptionHtml": "<p>Discover our cutest summer items!</p>", "seo": { "title": "Summer Kawaii Collection 2025", "description": "Explore our adorable summer collection featuring..." } }
Product Management
-
get-products- Get all products or search by title
- Inputs:
searchTitle(optional string): Filter products by titlelimit(optional number, default: 10): Maximum number of products to return
- Returns:
- Array of products containing:
id: Product IDtitle: Product titlehandle: URL-friendly handledescription: Product descriptiondescriptionHtml: HTML-formatted descriptionstatus: Product statustotalInventory: Total inventory countpriceRange: Product price rangeimages: Product images
- Array of products containing:
-
get-product-by-id- Get detailed information about a specific product
- Inputs:
productId(string, required): The GID of the product to fetch
- Returns:
- Product object containing:
id: Product IDtitle: Product titlehandle: URL-friendly handledescription: Product descriptiondescriptionHtml: HTML-formatted descriptionstatus: Product statustotalInventory: Total inventory countvariants: Product variantsimages: Product imagescollections: Associated collections
- Product object containing:
-
update-product- Update a product's details
- Inputs:
productId(string, required): The GID of the product to updatetitle(optional string): New product titledescriptionHtml(optional string): New HTML description
- Returns:
- Updated product object containing:
id: Product IDtitle: Updated titledescriptionHtml: Updated descriptionupdatedAt: Update timestamp
- Updated product object containing:
Best Practices for Content Management
-
SEO Optimization
- Use descriptive titles and handles
- Provide meta descriptions for all content
- Include relevant keywords naturally
- Keep URLs clean and meaningful
- Use proper heading hierarchy in HTML content
-
Content Organization
- Group related products in collections
- Use consistent naming conventions
- Maintain a clear content hierarchy
- Keep product descriptions detailed and accurate
- Use high-quality images with descriptive alt text
-
Performance Considerations
- Optimize image sizes
- Use appropriate query limits
- Cache frequently accessed content
- Batch updates when possible
- Monitor API usage
-
Content Management Tips
- Regular content audits
- Consistent branding across all content
- Mobile-friendly formatting
- Regular backups of important content
- Version control for major changes
Error Handling
All tools include comprehensive error handling:
- Invalid ID errors
- Permission errors
- Rate limiting errors
- Validation errors
- Network errors
Error responses include:
- Error code
- Field causing the error
- Detailed error message
- Suggestions for resolution
API Limitations
-
Rate Limits
- Respect Shopify's API rate limits
- Use appropriate query limits
- Implement retry logic for failed requests
- Monitor API usage
-
Content Restrictions
- Maximum content lengths
- Supported HTML tags
- Image size limits
- API version compatibility
-
Authentication
- Required access scopes
- Token expiration
- IP restrictions
- App permissions