Server data from the Official MCP Registry
Read-only MCP for the Shopify Admin GraphQL API. 6 tools, full read surface, multi-store.
Read-only MCP for the Shopify Admin GraphQL API. 6 tools, full read surface, multi-store.
A well-architected read-only Shopify MCP with strong security controls. The parser-level read-only enforcement is properly implemented, domain validation prevents SSRF, and credentials are handled safely (env vars, token caching in memory, redaction in logs). Minor code quality observations around broad exception handling and input validation don't materially impact security posture. Permissions align with stated purpose. Supply chain analysis found 5 known vulnerabilities in dependencies (0 critical, 3 high severity).
4 files analyzed · 9 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Set these up before or after installing:
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-pavle-scalably-shopify-mcp": {
"env": {
"SHOPIFY_DOMAIN": "your-shopify-domain-here",
"SHOPIFY_ACCESS_TOKEN": "your-shopify-access-token-here"
},
"args": [
"-y",
"github:scalably-io/shopify-mcp"
],
"command": "npx"
}
}
}From the project's GitHub README.
A single MCP server exposing 100% of the Shopify Admin GraphQL API read surface (version 2026-04) through 6 universal tools. Read-only is enforced at the query-parser level — mutations are rejected before they ever reach Shopify, not merely discouraged. Multi-store by design: one server instance can serve many shops.
Built and maintained by Scalably. Runs on the Model Context Protocol. License: MIT.
Why read-only at the parser level? Giving an AI agent write access to a live store is how you end up with a deleted product or a wrong-priced variant. This server enforces read-only by parsing every query and rejecting mutations before they leave the process — not by trusting the model to behave, and not by relying on Shopify-side scopes alone. It's the safety boundary an agent in production actually needs. (more on the pattern)
pip install -r requirements.txt
# Single store (simplest)
export SHOPIFY_DOMAIN="my-store.myshopify.com"
export SHOPIFY_ACCESS_TOKEN="shpat_..." # or SHOPIFY_CLIENT_ID + SHOPIFY_CLIENT_SECRET
python server.py
Then point any MCP client at the server. See Authentication below for multi-store and OAuth client-credentials setup.
| Tool | Description |
|---|---|
shopify_list_stores | Lists configured stores. Agent calls first. |
shopify_graphql_query | Arbitrary read-only GraphQL. Mutations rejected by the parser. |
shopify_graphql_introspect | Schema introspection — full catalog or single type. |
shopify_bulk_query | Launch async bulk export (JSONL). |
shopify_bulk_poll | Poll bulk operation status + download URL. |
shopify_shopifyql | ShopifyQL analytics (SQL-like; requires read_reports). |
Every non-list tool takes an optional shop argument (alias or domain). Required when >1 store configured; auto-selected when exactly 1.
100% of Admin GraphQL API read surface — any object, field, or connection accessible with the token's scopes is reachable via shopify_graphql_query. Anything large-scale (>10k records) should use shopify_bulk_query. Analytics goes through shopify_shopifyql.
Set SHOPIFY_STORES to a JSON object mapping alias → store config:
{
"main": {"domain": "my-store.myshopify.com", "client_id": "...", "client_secret": "..."},
"outlet": {"domain": "my-store-outlet.myshopify.com", "client_id": "...", "client_secret": "..."},
"legacy": {"domain": "legacy-store.myshopify.com", "access_token": "shpat_..."}
}
client_id+client_secret (Dev Dashboard OAuth, 24h tokens auto-refreshed per store) OR access_token (legacy shpat_).[a-z0-9][a-z0-9_-]{0,63}. Lowercase-normalized on load.If SHOPIFY_STORES is unset, the MCP falls back to single-store env vars:
SHOPIFY_DOMAIN or SHOPIFY_SHOP_DOMAIN — <shop>.myshopify.comSHOPIFY_CLIENT_ID + SHOPIFY_CLIENT_SECRET (Dev Dashboard)SHOPIFY_ACCESS_TOKEN (legacy shpat_)The single store registers under alias default — callers can omit shop argument on tool calls.
Every query is parsed with graphql-core before transmission. The parser rejects:
subscription operations (not supported by Admin API anyway)mutation EXCEPT bulkOperationCancel (cancels an in-flight bulk job, no shop-data write)bulkOperationRunQuery is NOT in the generic parser allowlist. Legitimate bulk exports go through the dedicated shopify_bulk_query tool, which validates the inner query with _assert_read_only BEFORE wrapping it in the bulk mutation. Single source of truth — no reliance on Shopify-side validation.
Per-store cost-based leaky bucket (Shopify's model). Each response includes extensions.cost.throttleStatus. On THROTTLED errors, the MCP sleeps ceil((requestedQueryCost - currentlyAvailable) / restoreRate) seconds (minimum 1s) and retries up to 3 times. Over limit → surfaced to caller.
Buckets are independent per store — throttle on store A doesn't affect store B.
^[a-z0-9][a-z0-9-]*\.myshopify\.com$ (no arbitrary hostnames — defeats SSRF).^[a-z0-9][a-z0-9_-]{0,63}$.allow_redirects=False on both token exchange and GraphQL calls.X-Shopify-Access-Token, client_secret, and all token prefixes (shpua_, shpat_, shpss_, shpca_) redacted from logs and error messages.shopify
Default pin: 2026-04. Callers can override per-tool via api_version="YYYY-MM". Bump the module constant SHOPIFY_API_VERSION quarterly after smoke-testing new versions.
Minimum viable: read_products read_orders read_customers.
Recommended baseline:
read_products read_orders read_customers read_inventory read_locations read_fulfillments read_discounts read_content read_themes read_files read_markets read_metaobjects read_metaobject_definitions read_reports read_translations read_locales read_shipping.
Add read_all_orders for >60-day order history. Enable Protected customer data access in Dev Dashboard → Configuration if the agent needs customer PII.
This connector runs locally, on your own machine, under your own Shopify credentials. It is a thin read-only bridge between your MCP client and Shopify's Admin API.
*.myshopify.com), enforced by a domain allowlist.The canonical hosted version of this policy: https://scalably.io/connector-privacy.html
We write about building production MCP servers and AI agents at scalably.io/blog:
Be the first to review this server!
by Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
by mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.