shopify-claude-mcp
v0.1.0
Published
MCP server for the Shopify Admin API — read and write your store's products, collections, orders, and online-store content (pages, blogs, articles) with SEO, from Claude.
Maintainers
Readme
shopify-mcp
An MCP server for the Shopify Admin API. It lets Claude read and write your store's products, collections, orders, and online-store content (pages, blogs, articles) — including SEO — directly.
Two ways to authenticate — pick one:
- Access token (easiest). Create a Shopify custom app (Settings → Apps and sales channels →
Develop apps), install it, and copy its Admin API access token (
shpat_…). Pass it as--accessToken. No OAuth, nothing to refresh. - Client credentials. A Dev Dashboard app's
client_id+client_secretare exchanged for a short-lived Admin API token that the server caches and refreshes automatically. Pass--clientId+--clientSecret.
Either way there is no browser step.
Tools
| Tool | What it does |
| --- | --- |
| get_products | List products as a markdown table with optional search query, sort key, and cursor pagination. |
| get_product | Fetch full detail for one product (variants, options, image, SEO) by id. |
| create_product | Create a product (DRAFT by default), optionally setting price/SKU on the default variant and SEO title/description. |
| update_product | Update an existing product's title, description, vendor, type, tags, status, or SEO title/description. |
| delete_product | Permanently delete a product. |
| manage_variants | Create and/or update variants (price, compare-at, SKU, barcode, option values). |
| delete_variants | Delete one or more variants from a product. |
| manage_options | Create / update / delete product options (e.g. Size, Color) and their values. |
| get_collections | List collections as a table (smart vs manual, product counts) with search/sort/pagination. |
| get_collection | Fetch one collection by id, including its rules (if smart), SEO title/description, and member products. |
| create_collection | Create a manual collection, or a smart one by passing rules; optionally set SEO title/description. |
| update_collection | Update a collection's title, description, handle, SEO title/description, or smart rules. |
| delete_collection | Delete a collection (products are not deleted). |
| manage_collection_products | Add/remove products in a manual collection. |
| get_orders | List orders as a markdown table (customer, total, payment & fulfillment status) with search/sort/pagination. |
| get_order | Fetch one order by id: line items, customer, shipping address, status, and totals. |
| update_order | Update an order's email, note, tags, or custom attributes. |
| cancel_order | Cancel an order, optionally refunding and/or restocking (destructive, cannot be undone). |
| manage_order_status | Close (archive) or reopen an order. |
| get_pages | List online-store pages as a markdown table (title, published status, handle) with search/sort/pagination. |
| get_page | Fetch one page by id, including its body (HTML) and SEO title/description. |
| create_page | Create an online-store page, optionally setting SEO title/description. |
| update_page | Update a page's title, body, handle, visibility, or SEO title/description. |
| delete_page | Permanently delete a page. |
| get_blogs | List blogs as a markdown table (title, article count, handle) with search/sort/pagination. |
| get_blog | Fetch one blog by id, including comment policy and SEO title/description. |
| create_blog | Create a blog (article container), optionally setting comment policy and SEO. |
| update_blog | Update a blog's title, handle, comment policy, or SEO title/description. |
| delete_blog | Permanently delete a blog and all its articles. |
| get_articles | List blog articles as a markdown table (title, status, blog, author) with blog filter/search/sort/pagination. |
| get_article | Fetch one article by id, including body (HTML), author, tags, and SEO title/description. |
| create_article | Create an article in a blog (requires blogId + author), optionally setting body, summary, tags, image, and SEO. |
| update_article | Update an article's title, author, body, summary, tags, visibility, blog, or SEO title/description. |
| delete_article | Permanently delete an article. |
| manage_tags | Add or remove tags on any taggable resource (product, order, customer, …) by GID. |
Tools are annotated with readOnly / destructive hints, and the server ships
instructions telling the model to render products as a table, confirm before writes, ask for
missing fields, and treat deletes as destructive.
Status — orders: The order tools (
get_orders,get_order,update_order,cancel_order,manage_order_status) compile but have not yet been tested against a live store. They are not needed right now; testing is required before relying on them — verify the GraphQL (notablyorderCanceland the shipping-address shape) and the destructive-confirmation flow forcancel_order. The product and collection tools are unaffected.
Prerequisites
- A Shopify app installed on your store — either a custom app (which issues an Admin API access token) or a Dev Dashboard app (which issues a Client ID + Client Secret).
- The app must be granted these access scopes:
read_productswrite_productsread_orderswrite_ordersread_contentwrite_content(pages, blogs, articles; SEO title/description are written asglobal.*metafields)
- Node.js 18+ (developed on Node 22).
Install & build
npm install
npm run buildConfigure in Claude
Each user supplies their own store domain and credentials. CLI flags take precedence; environment
variables (SHOPIFY_ACCESS_TOKEN, or SHOPIFY_CLIENT_ID + SHOPIFY_CLIENT_SECRET, plus
SHOPIFY_DOMAIN and SHOPIFY_API_VERSION) are a fallback.
The examples below use client credentials; to use a custom-app token instead, replace the
--clientId / --clientSecret pair with a single --accessToken "<shpat_…>".
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) and add:
{
"mcpServers": {
"shopify": {
"command": "node",
"args": [
"/ABSOLUTE/PATH/TO/shopify-mcp/dist/index.js",
"--clientId", "<YOUR_CLIENT_ID>",
"--clientSecret", "<YOUR_CLIENT_SECRET>",
"--domain", "<YOUR_SHOP>.myshopify.com"
]
}
}
}This package is published to npm as shopify-claude-mcp, so the same config works with
npx and no local build:
{
"mcpServers": {
"shopify": {
"command": "npx",
"args": [
"shopify-claude-mcp",
"--clientId", "<YOUR_CLIENT_ID>",
"--clientSecret", "<YOUR_CLIENT_SECRET>",
"--domain", "<YOUR_SHOP>.myshopify.com"
]
}
}
}Or install it globally (npm i -g shopify-claude-mcp) and use the shopify-claude-mcp command in
place of the npx invocation.
Restart Claude Desktop after editing. The shopify tools appear in the tools menu.
Claude Code
One line, no local build (custom-app token shown; swap in --clientId/--clientSecret if you
prefer client credentials):
claude mcp add shopify -- npx shopify-claude-mcp \
--accessToken <shpat_...> --domain <YOUR_SHOP>.myshopify.comFlags
--accessToken <shpat_...>— Admin API access token from a custom app. or--clientId <id> --clientSecret <secret>— Dev Dashboard app client credentials.--domain <shop>.myshopify.com— your store (required).--apiVersion <YYYY-MM>— Admin API version. Defaults to2026-01.
Verify it works (smoke test)
Before wiring into Claude you can confirm credentials and scopes with a one-shot test:
npm run smoke -- --clientId <ID> --clientSecret <SECRET> --domain <SHOP>.myshopify.comIt performs the token exchange and runs a real products query, printing a sample of titles.
How it's built
src/
index.ts # entry: load config, build server, serve over stdio
config.ts # CLI flags + env fallback, validation
shopify/
auth.ts # client-credentials token exchange + cache/refresh
client.ts # Admin GraphQL client (token header, 401 retry, error surfacing)
graphql/
products.ts # product queries/mutations + result types (validated vs 2026-01 schema)
collections.ts # collection queries/mutations + result types
orders.ts # order queries/mutations + result types
content.ts # page, blog & article queries/mutations + result types
metafields.ts # metafieldsSet (page/article SEO via global.* metafields; general metafields later)
tags.ts # cross-resource tag mutations
tools/
shared.ts # cross-domain helpers (results, GID normalization, setSeoMetafields)
index.ts # registerAllTools() — register each domain here
manageTags.ts # cross-resource tool (not product-specific)
products/ # product-domain tools, registered via registerProductTools()
index.ts getProducts.ts getProduct.ts createProduct.ts updateProduct.ts
deleteProduct.ts manageVariants.ts deleteVariants.ts manageOptions.ts
collections/ # collection-domain tools, registered via registerCollectionTools()
index.ts getCollections.ts getCollection.ts createCollection.ts
updateCollection.ts deleteCollection.ts manageCollectionProducts.ts
orders/ # order-domain tools, registered via registerOrderTools()
index.ts getOrders.ts getOrder.ts updateOrder.ts
cancelOrder.ts manageOrderStatus.ts
content/ # content-domain tools (pages, blogs, articles), via registerContentTools()
index.ts
getPages.ts getPage.ts createPage.ts updatePage.ts deletePage.ts
getBlogs.ts getBlog.ts createBlog.ts updateBlog.ts deleteBlog.ts
getArticles.ts getArticle.ts createArticle.ts updateArticle.ts deleteArticle.tsAdding a new domain later (orders, customers, inventory) means a tools/<domain>/ folder, a
graphql/<domain>.ts, and one line in tools/index.ts.
- Transport: stdio (the standard for local MCP servers). All logs go to stderr so they never corrupt the protocol stream on stdout.
- API: Shopify Admin GraphQL API. Product variant SKU is set via
inventoryItem.sku, and the default variant's price is applied withproductVariantsBulkUpdateafterproductCreate.
Troubleshooting
- "Failed to obtain an access token (HTTP 401/403)" — check the client id/secret and that the
app is installed on the store named in
--domain. - "Shopify GraphQL error: Access denied ... requires
write_products" — add the missing scope to the app and reinstall. - Tools don't appear in Claude — confirm the path to
dist/index.jsis absolute and that you rannpm run build; then fully restart Claude.
Roadmap
Customers, inventory, and metafields, plus deeper order operations (fulfillment and refunds).
Auth is isolated in shopify/auth.ts, so adding a full 3-legged OAuth flow for multi-merchant
distribution later is contained.
License
MIT
