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_products
read_customers
,write_customers
read_orders
,write_orders
read_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
.env
file 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
startCursor
andendCursor
from each response - Use
hasNextPage
andhasPreviousPage
to show/hide navigation controls - Keep the same
limit
value for consistent page sizes - Use
reverse
when you need newest/oldest items first - Combine with
searchTitle
for 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
compareAtPrice
to 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-id
to 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-blogs
first to obtain valid blog IDs - Use
get-blog-by-id
to fetch detailed information about a specific blog - When updating blogs, only include the fields you want to modify
- The
commentPolicy
can only be set to "MODERATED" or "CLOSED"
- Always use
-
Working with Articles
- Articles must be associated with an existing blog
- Use
get-articles
to list articles within a specific blog - When creating or updating articles, the
body
field 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: false
to 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