shopify_graphql_schema
Explore the Admin GraphQL schema for this store's API version.
storerequiredtype_namerequired
io.github.alex-brecherPublished by GitHub account alex-brecherv2.0.3Updated Oct 29, 2026
Connect AI agents to multiple Shopify Admin stores for reports, comparisons, and guarded updates.
Connects an AI assistant to one or many Shopify Admin stores to search, compare, report, and make guarded, dry-run-first updates.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
Query, compare, report, and make guarded updates across Shopify stores from Claude, ChatGPT, Codex, Cursor, VS Code, and other MCP clients.
[One MCP server connected to multiple ecommerce stores][CI] [npm version] [npm provenance] [Node.js 20+] [MCP ready] [License: MIT]
Demo · Quick start · Reports · AI clients · Security
Run it locally, or host one server for your team: everyone signs in with their own Shopify staff account and connects from Claude, ChatGPT, Codex or any remote MCP client, with Shopify's own staff permissions deciding what each person can do. Guided Admin workflows, ShopifyQL reports, schema validation, and a generic action surface for any Admin mutation are included. See feature coverage and acceptance requirements. Full Shopify ChatGPT parity is not yet verified.
The demonstration uses sample stores and sample data. The server keeps each real store credential separate.
Install the server, connect your stores, and run the health check:
Claude Code users can add the server with one command:
Each store gets a permanent alias and a separate secure credential. Every store operation requires that alias.
The two servers solve different problems. Use both when an agent needs Shopify reference material and access to your stores.
Shopify Dev MCP helps an agent create and examine Shopify code. This server runs the approved operation against the selected store.
shopify_report runs one read-only report across selected stores. Set report to one of these:
To search products across stores, use shopify_search with resource: "products" and stores.
Try prompts like these:
The server works in clients that support local stdio MCP servers. Agent Skills improve tool selection when the client supports them.
Add the MCP server:
Copy the included skill for personal use:
Add this server to the client's MCP configuration:
Add this server to .vscode/mcp.json:
Use npx as the command and -y shopify-multi-store-mcp-server start as the arguments.
Copy skills/shopify-multi-store/SKILL.md into the client's skills directory when supported. Clients without skill support still get every MCP tool.
Local use on your own computer (above) is the default. Hosting is optional: whoever wants a shared server runs one, and their team connects from the AI app they already use, on any plan: Claude (personal custom connector), ChatGPT, Codex, Claude Code, Cursor, VS Code, Gemini CLI, Windsurf, or any MCP client that supports remote servers.
People sign in with their own Shopify staff account, and every call runs with that person's own Shopify permissions: Shopify decides what they can do, with no roles or policy file on the server. Shopify tokens stay on the server, encrypted. Reconnecting is at most once a day and one click for all stores. Every tool call is audited.
Two ways to host, both self-hosted by whoever wants a shared server:
shopify-multi-store serve (or the included Dockerfile) and share https://<host>/mcp.See Connect from your AI app for per-client steps, docs/HOSTED.md for setup, and docs/ACTIONS.md for per-user access and the generic action tools.
Authorization code setup uses http://127.0.0.1:3456/oauth/callback. Add it as an allowed redirect URL first.
The default authorization code scopes are read-only. Grant only the Admin API scopes required for the task.
Each store needs an alias (lowercase letters, digits and hyphens, such as main) and its permanent *.myshopify.com domain, which the store admin shows under Settings > Domains. The credential depends on how you get Admin API access. Shopify now creates new apps in the Dev Dashboard; custom apps made in the store admin keep working where they already exist.
With a Dev Dashboard app (new setups):
read_products,read_orders,read_inventory,read_locations,read_customers covers the read tools; for everything the tools can do, print the full list with node "$(npm root -g)/shopify-multi-store-mcp-server/scripts/print-scopes.mjs" --full and remove any scope your app is not approved for. For the authorization code method, also add the redirect URL http://127.0.0.1:3456/oauth/callback.shopify-multi-store oauth. Choose client-credentials if the store is in the same Shopify organization as the app, otherwise authorization-code (a browser window opens to approve). Enter the alias, the *.myshopify.com domain, the client ID and the client secret. With client credentials the server gets and refreshes tokens itself.With a custom app created in the store admin:
shpat_; Shopify shows it once).shopify-multi-store setup and enter the alias, the *.myshopify.com domain and the token.Then run shopify-multi-store doctor to check every store, and repeat for each further store. Secrets go to the operating system credential store, never to the configuration file.
The import copies credentials into the operating system credential store and preserves configured stores. Delete the old credential file after checking the import.
The server exposes 29 tools.
Read-only operations can run in parallel. Mutations stay isolated to the selected stores.
Every guided write tool defaults to dryRun: true, which returns a before/after (or would-create) preview without changing anything; pass dryRun: false, after the user authorizes the exact store and change, to apply it. The tool then reads the result back. Tags on products, orders, and customers change with addTags and removeTags; replaceTags replaces every tag and the preview lists the tags it would remove. Write results are never dropped for size: large results are trimmed, keeping status, counts, and every item that did not apply.
shopify_graphql_mutation and shopify_run_action refuse denylisted mutations and need confirm set to the mutation name for destructive ones, including mutations that are destructive only because of their arguments, such as a product status of ARCHIVED.
Three tools reach every Shopify Admin API mutation (514 in API 2026-04), including the 483 without a dedicated tool:
A denylist blocks mutations that mint credentials or change the app's own billing. Request the full scope set with node scripts/print-scopes.mjs --full. See docs/ACTIONS.md for worked examples and what no third-party app can do.
Install Shopify's official shopify skill:
The command installs the skill for every supported agent it detects. Pass --agent <name> to select one agent, for example --agent claude-code.
The shopify skill is one skill with a routing table. Its admin topic searches Shopify documentation and validates custom Admin GraphQL operations. Its shopifyql topic covers sales, revenue, order, conversion, and trend analysis. Shopify's toolkit 2.0.0 merged the former shopify-admin and shopify-shopifyql skills into this one skill, and the toolkit's ucp skill (a shopping CLI) is not part of this install.
If Shopify renames the skill again, the command exits with status 1, prints the skills the toolkit ships, and shows the npx skills add command to install one by name. It never reports success after installing nothing.
This server still controls store selection, credentials, execution, and mutation authorization. Shopify's skill scripts send usage telemetry by default.
Set OPT_OUT_INSTRUMENTATION=true to turn off that telemetry.
This integration uses the official Shopify AI Toolkit. It also reflects useful patterns from Shopify Admin Skills.
Secrets never enter the main configuration file.
The configuration stores aliases, domains, API versions, and non-secret OAuth client IDs. Its default path is ~/.config/codex-shopify-multi-store/stores.json.
The codex-shopify-multi-store name, in that path and as the credential store's service name, is a legacy name from the project's first version. It stays so existing installs keep their stores and credentials; it does not mean the server works only with Codex.
Set SHOPIFY_MULTI_STORE_CONFIG to use another configuration path.
.env files, or credential-bearing configuration files.Linux credential storage requires a Secret Service provider, such as GNOME Keyring or KWallet.
Run a health check without a global install:
Install directly from GitHub (npm runs the prepare script, which builds the server):
The live test uses configured stores and performs read-only Shopify Admin API calls.
MIT
Read the changelog, contribution guide, security policy, and directory submission guide.
Source: README.md at commit 5eabaec
Explore the Admin GraphQL schema for this store's API version.
storerequiredtype_namerequiredValidate Admin GraphQL operations against this store's API version without executing them.
storerequiredcodeblocksrequiredCreate a product with options, variants and images, and optionally add it to a manual collection. Defaults to status DRAFT and to dryRun:true, which previews the input without creating anything.
tagspricestorerequiredtitlerequireddryRunimagesstatusvendoroptionsvariantsproductTypecollectionId+1 moreUpdate product fields, variants, media and tags. dryRun:true (the default) returns the current product and the change without applying it; dryRun:false applies it and returns before and after. Tags: addTags and removeTags change only the named tags; replaceTags replaces all tags. A status of ARCHIVED or DRAFT takes the product off every sales channel.
idrequiredstorerequiredtitledryRunimagesstatusvendoraddTagsvariantsremoveTagsproductTypereplaceTags+2 moreCreate a manual collection (optional productIds) or a smart collection (ruleSet). Pass publicationIds to publish to explicitly selected channels. Defaults to dryRun:true, which previews the input without creating anything.
imagestorerequiredtitlerequireddryRunruleSetsortOrderproductIdspublicationIdsdescriptionHtmlUpdate collection fields, rules or image, and add products to a manual collection (addProductIds). dryRun:true (the default) returns the current collection and the change without applying it; dryRun:false applies it and returns before and after.
idrequiredimagestorerequiredtitledryRunruleSetsortOrderaddProductIdsdescriptionHtmlSet available inventory at one location using compare-and-set protection: compareQuantity must equal the current available quantity. Read inventory first (shopify_get resource inventory). dryRun:true (the default) checks and previews without changing anything.
storerequireddryRunreasonquantityrequiredlocationIdrequiredidempotencyKeycompareQuantityrequiredinventoryItemIdrequiredCreate a percentage discount code with an explicit start date and customer audience. Defaults to dryRun:true, which resolves segments and previews the discount without creating it.
coderequiredstorerequiredtitlerequireddryRunendsAtstartsAtrequiredpercentagerequiredproductIdsusageLimitcollectionIdminimumQuantitycustomerSegments+3 moreUpload a local image file or an HTTPS image to Shopify Files, wait for processing, and return its CDN URL (check it later with shopify_get resource uploaded_image). Defaults to dryRun:true, which previews the upload without sending anything.
altstorerequireddryRunfilenameimageFilesourceUrlSet price, compareAtPrice and/or unit cost for up to 250 SKUs on one store (store) or the same list on several stores in parallel (stores). Resolves each SKU to the variants whose SKU matches exactly (Shopify search is a prefix match) and groups writes by product. A SKU shared by several variants is skipped unless allowDuplicates:true. Duplicate SKU rows with conflicting values are rejected before any write; identical duplicates are collapsed. After a write, verifies each variant with a separate read-back query and reports per-item outcome (applied, applied_unverified, rejected, not_found, ambiguous, unknown, skipped, mismatch) and a store status (ok, unverified, partial, failed, unknown). Large results are trimmed, never dropped: status, counts and every item that did not apply are always returned. Defaults to dryRun:true.
skusrequiredstoredryRunstoresallowDuplicatesSet (metafieldsSet) and/or delete (metafieldsDelete) up to 25 metafields each, for any owner GID. Read them with shopify_get resource metafields. Defaults to dryRun:true.
setstorerequireddeletedryRunCreate and/or delete up to 100 URL redirects each, with a per-redirect outcome (applied, rejected or unknown) and a store status. List them with shopify_search resource redirects. Requires write_online_store_navigation. Defaults to dryRun:true.
storerequiredcreatedeletedryRunUpdate order note, email, shipping address and tags (orderUpdate). dryRun:true (the default) returns the current order and the change without applying it; dryRun:false applies it and returns before and after. Tags: addTags and removeTags change only the named tags; replaceTags replaces all tags. Requires write_orders.
idrequirednoteemailstorerequireddryRunaddTagsremoveTagsreplaceTagsshippingAddressAdd and/or remove tags on a product, order, customer or draft order by GID (tagsAdd/tagsRemove). Defaults to dryRun:true.
addstorerequireddryRunremoveownerIdrequiredUpdate customer note, email and tags (customerUpdate). dryRun:true (the default) returns the current customer and the change without applying it; dryRun:false applies it and returns before and after. Tags: addTags and removeTags change only the named tags; replaceTags replaces all tags. Email marketing consent is out of scope. Requires write_customers.
idrequirednoteemailstorerequireddryRunaddTagsremoveTagsreplaceTagsFulfill the remaining quantities of an order's OPEN and IN_PROGRESS fulfillment orders with optional tracking. notifyCustomer defaults to false. Requires read_merchant_managed_fulfillment_orders and write_merchant_managed_fulfillment_orders (Shopify reports any other missing scope, such as for fulfillment orders assigned to a fulfillment service). Defaults to dryRun:true.
storerequireddryRunorderIdrequiredtrackingUrlnotifyCustomertrackingNumbertrackingCompanyFor one or many stores, report the shop identity and granted Admin API access scopes, compare them against every tool's requirement (see src/scope-requirements.ts; tools with several resources or reports are listed as tool:resource), and report missing scopes and which tools would fail. Omit stores to check every configured store.
storesSearch a Shopify Resource
List or search one kind of record with cursor pagination, on one store (store) or several in parallel (stores; each store returns its own result and cursor). Resources: - products: Products (query: Shopify product search syntax). - collections: Manual and smart collections. - orders: Orders, newest first (query: Shopify order search syntax). - customers: Customers. Protected customer data permissions apply. - publications: Sales channel publication IDs (no query; 100 per page). - redirects: URL redirects. - pages: Online Store pages. - files: Files (images, videos, generic files). - metaobjects: Metaobjects of one type (type required). - markets: Markets (no query). - themes: Themes with their role; MAIN is live (no query). - delivery_profiles: Delivery profiles with zones, methods and flat rates (no query).
typeafterfirstquerystorestoresresourcerequiredGet a Shopify Record
Read one record by GID from one store. Follow each returned cursor independently. Resources: - product: Product details, variants (first/after) and media (mediaAfter). id: Product GID. - collection: Collection details, rules and a page of products. id: Collection GID. - order: Order, shipping, fulfillment, tracking and a page of line items. id: Order GID. - inventory: Inventory by product (id: Product GID) or inventory item (id: InventoryItem GID, pages through locations). - metafields: Metafields of any owner (id: owner GID); optional namespace and key. - theme_files: Theme file contents. id: OnlineStoreTheme GID; optional filenames, else pages through every file. - blog_articles: A blog's articles. id: Blog GID. - uploaded_image: Image processing status and CDN URL. id: MediaImage GID. - bulk_operation: A bulk operation's status and result URLs. id: BulkOperation GID. Partial exports stay marked incomplete.
idrequiredkeyafterfirststorerequiredresourcerequiredfilenamesnamespacemediaAfterRun a Shopify Report
Run one read-only report across selected stores; each store returns its own result and completeness indicators. Reports: - portfolio_snapshot: Shop identity and product, order, customer and location counts. stores optional (all stores). - store_locations: Active, inactive, legacy, fulfillment, inventory and address status of locations. stores optional (all stores). - compare_inventory: Inventory, price, status and catalog details for exact SKUs. Needs skus (1-50). - compare_prices: Price and compare-at price for exact SKUs, with mismatches and missing variants. Needs skus (1-50). - get_product_everywhere: One exact SKU or handle across stores. Needs identifier and matchBy (sku or handle). - compare_catalog: Titles, status, vendor, type and inventory for exact product handles. Needs handles (1-50). - compare_collections: Titles, sort order, product counts, SEO and images for exact collection handles. Needs handles (1-50). - catalog_gap_report: Products missing or with different status across stores. first: products scanned per store (default 250). - catalog_health: Missing vendor, type, SEO, media, alt text, and active products without inventory. first (default 100). - duplicate_sku_report: SKUs repeated inside a store and shared across stores. first: variants scanned per store (default 250). - low_stock_report: Active variants at or below threshold (default 10), separating low, zero and negative. - recent_product_changes: Products updated in the last days (default 7). first (default 100). - list_unfulfilled_orders: Recent open unfulfilled orders. days (default 7), first (default 25). - fulfillment_sla_report: Open unfulfilled orders by age bucket and SLA breaches. lookbackDays (default 90), slaDays (default 2), first (default 100). - order_summary: Order values, discounts, shipping, tax, cancellations and statuses; currencies separate. days (default 30), first (default 100). - customer_growth: New customers in the current and previous period of days (default 30). -
daysskusfirstqueryreportrequiredstoreshandlesmatchByslaDaysthresholdidentifierlookbackDaysSearch Shopify documentation and return source links. No store credentials are sent.
promptrequiredapi_namemax_num_resultsFind Shopify Admin Actions
Search every Shopify Admin API mutation (hundreds of write actions, most without a dedicated tool) by keyword and optional category. Returns each action's name, one-line description, category, whether it is destructive, which dedicated tools already cover it, and a scope hint. Next: shopify_describe_action for the full signature, then shopify_run_action.
limitquerystoreoffsetcategoryapiVersionincludeDeprecatedDescribe a Shopify Admin Action
Full signature of one Admin API mutation: arguments with types, the expanded input object fields (required markers, enum values, descriptions), the payload fields, a ready-to-edit GraphQL document with a default selection, a variables template with the required fields, a scope hint, and whether it is destructive (then shopify_run_action needs confirm set to the mutation name).
depthstoremutationrequiredapiVersionRun a Shopify Admin Action
Run any Shopify Admin API mutation on one to one hundred stores. Give a mutation name (a default document is built) or a full single-mutation document, plus variables shared by every store and/or variablesByStore (IDs differ per store). dryRun (the default) validates the document and variables against each store's API version and looks up every record ID in the variables and the document; nothing is changed. The preview says whether it is complete: targets chosen by a search, saved search, filter, or "all" flag, more than 250 IDs, or IDs that do not resolve make it incomplete, and then applying also needs acknowledgeIncompletePreview: true. dryRun false applies it; every ID is looked up again first, and IDs that do not resolve refuse the apply unless acknowledgeIncompletePreview is true. Destructive actions (delete, cancel, refund and similar) need confirm set to the mutation name. Mutations are never retried automatically. On a hosted server in per-user mode, Shopify limits this to what your own staff account may do.
dryRunstoresrequiredconfirmdocumentmutationvariablesvariablesByStoreacknowledgeIncompletePreviewList Shopify Stores
List every Shopify Admin store that remains connected to this plugin. On a hosted server in per-user mode, lists only the stores you have connected with your own Shopify account and names the others with a link to connect them. This tool does not expose access tokens.
Takes no parameters.
Get Shopify Store Information
Get identity and account information from one named Shopify Admin store. Use this tool before a sensitive change to make sure that the selected store is correct.
storerequiredQuery a Shopify Store
Run one read-only GraphQL Admin API query against one named store. Use cursor pagination and request only necessary fields.
queryrequiredstorerequiredvariablesQuery Multiple Shopify Stores
Run the same read-only GraphQL Admin API query across multiple named stores in parallel. Each store returns its own success or error result.
queryrequiredstoresrequiredvariablesChange a Shopify Store
Run one GraphQL Admin API mutation against one named store. Set confirm to true only after the user authorizes the exact store and change. Destructive mutations (see shopify_describe_action; some are destructive only with certain arguments, such as a product status of ARCHIVED or notifyCustomer true) need confirm set to the mutation name instead, and denylisted mutations are refused, exactly as in shopify_run_action. The result reports each top-level mutation field as applied, rejected, or unknown, and the store as applied, rejected, partial, or unknown; after partial or unknown, retry only the rejected fields in a new document.
storerequiredconfirmrequiredmutationrequiredvariables90% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
npm install --global shopify-multi-store-mcp-servershopify-multi-store setupshopify-multi-store doctorclaude mcp add shopify-multi-store -- npx -y shopify-multi-store-mcp-server startclaude mcp add shopify-multi-store -- npx -y shopify-multi-store-mcp-server startmkdir -p ~/.claude/skills/shopify-multi-storecp skills/shopify-multi-store/SKILL.md ~/.claude/skills/shopify-multi-store/SKILL.md{ "mcpServers": { "shopify-multi-store": { "command": "npx", "args": ["-y", "shopify-multi-store-mcp-server", "start"] } }}{ "servers": { "shopify-multi-store": { "type": "stdio", "command": "npx", "args": ["-y", "shopify-multi-store-mcp-server", "start"] } }}shopify-multi-store listshopify-multi-store doctorshopify-multi-store remove store-aliasshopify-multi-store import /absolute/path/to/stores.jsonshopify-multi-store install-shopify-skillsnpx -y shopify-multi-store-mcp-server doctornpm install --global github:alex-brecher/shopify-multi-storegit clone https://github.com/alex-brecher/shopify-multi-store.gitcd shopify-multi-storenpm cinpm testnpm run test:livenpm pack --dry-run