Skip to content
Conduit

mcp server

shopify-admin-mcp

MCP server for the Shopify Admin GraphQL API (2026-10) with live schema introspection

acoderacom/shopify-admin-mcpcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "acoderacom-shopify-admin-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@acodera/shopify-admin-mcp"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 26, 2026

shopify-admin-mcp

npm CI License: MIT

MCP server for Shopify's Admin GraphQL API: typed tools for common store tasks, raw GraphQL for everything else, and live schema search so your AI assistant works against the exact API your store serves. Targets API version 2026-10.

Features

  • 59 convenience tools for products, collections, publishing, metafields, metaobjects, customers, orders, inventory, discounts, files, themes, and markets
  • Raw GraphQL and live schema search for anything the tools don't cover
  • Theme files from a local folder: with --theme-dir, theme writes send files by filename and a pull tool copies them back, so file content never has to pass through the conversation
  • Setup wizard that writes .mcp.json for you
  • Safety controls: read-only mode, toolsets, a live-theme guard, confined local uploads, and read-only or destructive annotations on every tool
  • Both auth methods: Dev Dashboard client credentials (refreshed automatically) and legacy shpat_ tokens
  • Rate-limit aware: throttled requests wait for the cost bucket to refill, then retry

Quick Start

Run the setup wizard in your project folder:

npx -y @acodera/shopify-admin-mcp@latest setup

It runs on macOS, Linux and Windows. It checks your Node.js version, then asks what to set up:

  • Connect to a store only: asks for your store and credentials, checks them, optionally adds the Shopify Dev MCP server, and creates or updates .mcp.json. Theme edits are turned off (--disable-theme-writes), so the assistant can read themes but not change them; everything else, such as products and metafields, can be changed. Local files, such as product images, are uploaded from ./uploads, which setup creates, unless .mcp.json already sets an upload folder.
  • Full theme design with Horizon: also downloads Shopify's Horizon theme into ./theme and writes CLAUDE.md, THEME.md and customizations.md from acoderacom/claude-horizon, with the store and live theme filled in to CLAUDE.md. It switches on what CLAUDE.md describes: live theme writes, theme files from ./theme, uploads from ./uploads, and the Shopify Dev MCP. The store's live theme must be a Horizon version the template supports (listed in its versions.json), and the project gets that exact version. Otherwise setup says which version to switch to and stops without writing .mcp.json. Since the Shopify theme store only installs the newest Horizon, it offers to save an upload-ready horizon-<version>.zip for Online Store → Themes → Add theme → Upload zip file.
  • Full theme edit live site: for working on a copy of a live store's theme, Horizon or not, without Horizon's checks. First duplicate the live theme in the Shopify admin (Online Store → Themes → ⋯ → Duplicate) and give the copy a name. Setup lists the store's themes and you pick the copy Claude edits; the live theme is listed but can't be picked, and setup stops if the store has no copy. Live theme writes stay off and themes are locked (--lock-themes), so the server refuses any change to the live theme and any theme create, duplicate, rename, delete or publish: you publish the copy yourself. Setup writes CLAUDE.md (no mockup rules) and customizations.md from the template's live-site/ folder with the store and the copy's name, version and ID filled in, a blank THEME.md, and an empty ./theme. Then, by hand: download the copy (⋯ → Download theme file) and unzip it into ./theme, and, when you want, ask Claude to learn the theme: it writes THEME.md from ./theme, which stays blank until then. Store data such as products and menus is shared with the live site, so changes to it still show at once; CLAUDE.md has Claude ask first. Running setup again keeps ./theme, THEME.md and the chosen copy unless you change them.

Current values are prefilled and other servers are kept. Setup doesn't ask about the other options, such as read-only mode, toolsets or raw GraphQL; set them in .mcp.json by hand. Running "Connect to a store only" again keeps them; both theme design modes set the ones CLAUDE.md depends on. The secret is saved in plain text, so the file is added to .gitignore in a git repo and, on macOS and Linux, written readable only by you. Windows has no such file mode, so the file gets its folder's permissions: keep the project inside your user folder, where other users can't read it. Restart Claude Code (or run /mcp) to connect.

Manual setup

With Claude Code:

claude mcp add shopify \
  -e SHOPIFY_STORE=mystore.myshopify.com \
  -e SHOPIFY_CLIENT_ID=your_client_id \
  -e SHOPIFY_CLIENT_SECRET=your_client_secret \
  -- npx -y @acodera/shopify-admin-mcp

Or in .mcp.json, or the Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):

{
  "mcpServers": {
    "shopify": {
      "command": "npx",
      "args": ["-y", "@acodera/shopify-admin-mcp"],
      "env": {
        "SHOPIFY_STORE": "mystore.myshopify.com",
        "SHOPIFY_CLIENT_ID": "${SHOPIFY_CLIENT_ID}",
        "SHOPIFY_CLIENT_SECRET": "${SHOPIFY_CLIENT_SECRET}"
      }
    }
  }
}

For a legacy token, set SHOPIFY_ACCESS_TOKEN instead of the client ID and secret. Claude Code expands ${VAR} from your shell, so .mcp.json can be committed without secrets; Claude Desktop doesn't, so write the values there directly.

Authentication

  • Client credentials (recommended): create an app in the Dev Dashboard, configure the scopes below, release a version, install it on your store, and use its client ID and secret. The app and the store must belong to the same Shopify organization. Tokens last 24 hours and are refreshed automatically.
  • Approved in the browser: for an app installed on a store outside the app's organization, such as a client's store or one you reach as a collaborator, where Shopify refuses client credentials with shop_not_permitted. In setup, choose Client ID and secret, approved in the browser. It prints a redirect URL, http://localhost:3457/auth/callback, to add to the app's version in the Dev Dashboard (then release the version), opens Shopify's approval page, and exchanges the approval for an offline access token that lasts until the app is uninstalled or its secret is rotated. The client secret is only used for the approval; .mcp.json gets the access token.
  • Legacy access token: the shpat_ token of an existing custom app.

Grant only the scopes for the tools you use:

ScopesTools
read_products, write_productsProducts, variants, collections
read_publications, write_publicationsPublishing
read_metaobjects, write_metaobjectsMetaobject entries
read_metaobject_definitions, write_metaobject_definitionsMetaobject definitions
Scope of the owning resourceMetafields (e.g. read_products for product metafields)
read_customers, write_customersCustomers
read_orders (+ read_all_orders for orders older than 60 days)Orders
read_inventory, write_inventory, read_locationsInventory
read_discounts, write_discountsDiscounts
read_files, write_filesFiles
read_themes, write_themes (+ theme-code exemption for writes)Themes
read_markets, write_marketsMarkets

Customer names, emails, phone numbers, and addresses are protected customer data, which your app must also be approved for.

Tools

Always available: shopify_graphql (any query or mutation; queries only in read-only mode), shopify_schema_search, and shopify_schema_details. The rest are grouped into toolsets, all registered by default:

ToolsetTools (each prefixed shopify_)
productsproducts_list, product_get, product_create, product_update, product_delete, product_variants_create, product_variants_update
collectionscollections_list, collection_get, collection_create, collection_update, collection_delete
publishingpublications_list, publish, unpublish
metafieldsmetafields_list, metafields_set, metafield_delete, metafield_definitions_list, metafield_definition_create
metaobjectsmetaobject_definitions_list, metaobject_definition_create, metaobjects_list, metaobject_get, metaobject_create, metaobject_update, metaobject_upsert, metaobject_delete
customerscustomers_list, customer_get, customer_update
ordersorders_list, order_get
inventoryinventory_get_levels, inventory_adjust
discountsdiscounts_list, discount_get, discount_amount_off_create, discount_free_shipping_create, discount_bxgy_create, discount_activate, discount_deactivate, discount_delete, discount_codes_add
filesfiles_list, file_upload, file_delete
themesthemes_list, theme_files_list, theme_files_get, theme_files_upsert, theme_files_delete, theme_duplicate, theme_delete; theme_files_pull with --theme-dir
marketsmarkets_list, market_get, market_create, market_update, market_delete

A few inputs follow API 2026-10: collections define their products with sources (see CollectionCreateSourceTargetInput in shopify_schema_details), shopify_inventory_adjust needs the quantity you expect before the change (changeFromQuantity), and a discount takes one kind of eligibility (customerIds, customerSegmentIds, or marketIds) and items by collection or by product, not both.

Theme Files From a Local Folder

Theme files are usually edited in a local copy of the theme first. Sending a file's content through shopify_theme_files_upsert makes the assistant write out the whole file, which takes minutes for a large section. With --theme-dir pointing at the local copy:

  • shopify_theme_files_upsert sends a file given only its filename from that folder: text as text, anything else as base64. When Shopify's write job is done, it reports for each file whether Shopify stored it as sent. Shopify regenerates JSON files such as templates (adding its header and reformatting them), so a file it returns changed is replaced in the folder with Shopify's copy.
  • shopify_theme_files_pull copies files or patterns such as sections/* from a theme into the folder, up to 50 per call, and returns only filenames and checksums. Files that already match are left alone.

Files passed with content, contentBase64 or url work as before.

Safety

  • Read-only mode (--read-only) registers only tools that read data and rejects mutations in raw GraphQL. The document is parsed, so comments or extra operations can't slip one through. Use it whenever the assistant doesn't need to change the store: product descriptions and customer notes are written by other people and can carry instructions.
  • Toolsets (--toolsets products,orders) shorten the tool list, but raw GraphQL can still reach anything your scopes allow. Add --disable-raw-graphql to keep the assistant to the selected toolsets. Either way, the app's scopes are the real limit.
  • The live theme is protected: theme file writes and deletes on the published (MAIN) theme are refused, including through raw GraphQL, where themePublish is refused too. Duplicate the theme, edit the copy, and publish it from the Shopify admin, or start with --allow-live-theme-writes.
  • Theme edits can be turned off entirely with --disable-theme-writes: the theme write tools are left out, and raw GraphQL refuses every theme mutation (file writes, themeCreate, themeUpdate, themeDelete, themeDuplicate, themePublish) whichever theme it targets. It overrides --allow-live-theme-writes, and setup's "Connect to a store only" mode turns it on.
  • Themes can be locked with --lock-themes: theme files can still be edited, but shopify_theme_duplicate and shopify_theme_delete are left out, and raw GraphQL refuses themeCreate, themeDuplicate, themeUpdate, themeDelete and themePublish, so copies can't be deleted or renamed and nothing can be published. Setup's "Full theme edit live site" mode turns it on.
  • The theme folder (--theme-dir) is the only place theme files are sent from and pulled into. Paths that lead outside it, symlinks included, and files outside the theme's own folders (assets, blocks, config, layout, locales, sections, snippets, templates) are refused.
  • Local uploads are off until you set --upload-dir (setup sets ./uploads in both modes). shopify_file_upload then accepts files inside that folder (symlinks resolved), as well as public URLs that Shopify fetches itself.
  • Credentials are only ever sent to *.myshopify.com, and the server warns when secrets are passed as flags, since other processes can see them.

Configuration

Every option works as a flag after the package name (in args) or as an environment variable (in env):

FlagEnvironment variableDefaultDescription
--storeSHOPIFY_STORErequiredmystore or mystore.myshopify.com
--access-tokenSHOPIFY_ACCESS_TOKENLegacy shpat_ token
--client-idSHOPIFY_CLIENT_IDClient credentials ID
--client-secretSHOPIFY_CLIENT_SECRETClient credentials secret
--api-versionSHOPIFY_API_VERSION2026-10YYYY-MM or unstable
--toolsetsSHOPIFY_TOOLSETSallComma-separated toolsets to register
--upload-dirSHOPIFY_UPLOAD_DIRoffAbsolute path that local uploads are confined to
--theme-dirSHOPIFY_THEME_DIRoffAbsolute path of a local copy of the theme that theme files are sent from and pulled into
--read-onlySHOPIFY_READ_ONLYoffRead tools only, no mutations
--allow-live-theme-writesSHOPIFY_ALLOW_LIVE_THEME_WRITESoffAllow writing to and publishing the live theme
--disable-theme-writesSHOPIFY_DISABLE_THEME_WRITESoffRefuse every theme change; overrides --allow-live-theme-writes
--lock-themesSHOPIFY_LOCK_THEMESoffKeep theme file edits but refuse creating, duplicating, renaming, deleting and publishing themes
--disable-raw-graphqlSHOPIFY_DISABLE_RAW_GRAPHQLoffLeave out shopify_graphql

For example: "args": ["-y", "@acodera/shopify-admin-mcp", "--read-only", "--toolsets", "products,orders,customers"].

  • On/off variables accept true or 1. When an option is set both ways, the flag wins; for on/off options, either one turns it on.
  • Blank values and unfilled references (${VAR}, $VAR) count as not set, so one config can list both auth methods. If both are filled in, the access token is used.
  • Use an absolute --upload-dir and --theme-dir, since MCP clients start the server from their own working directory.
  • With an older --api-version, raw GraphQL works but some tools may not. The server logs a warning if Shopify serves a different version than the one requested.

Schema Exploration

The server introspects the live schema in the background once it connects. shopify_schema_search finds types, queries, and mutations by keyword, and shopify_schema_details shows a type's fields or an operation's arguments. Deprecated fields are left out, which steers the assistant toward the current API.

Development

git clone https://github.com/acoderacom/shopify-admin-mcp.git
cd shopify-admin-mcp && git checkout dev && npm install
npm run build   # or `npm run dev` to rebuild on change
npm test        # unit tests; live tests skip themselves without credentials
npm run lint    # type-check src and tests

Requires Node.js 22.12 or later. Setting SHOPIFY_STORE and credentials also runs the live tests; adding SHOPIFY_TEST_WRITES=1 runs write tests that create and then delete [MCP test] data, so only use it with a development store.

To contribute, branch from dev, add a changeset with npx changeset (not needed for docs, tests, or CI), and open a pull request into dev. Releases merge dev into main; the workflow then opens a Version Packages pull request, and merging it publishes to npm through trusted publishing with provenance.

License

MIT. See LICENSE.

Originally created by Colby McHenry as shopify-graphql-admin-mcp, and maintained by acoderacom.

↑↓ navigate openesc close