Shopify Enterprise MCP Server
Provides tools for searching and retrieving product details from a Shopify store, including variants, pricing, SKUs, stock levels, and collections.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Shopify Enterprise MCP ServerHow many Nike shoes are in stock?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Shopify Enterprise MCP Server
Production-grade Model Context Protocol server that exposes live Shopify Admin GraphQL data to Microsoft Copilot Studio agents.
Every business question is answered by querying Shopify at request time. The server never returns cached figures and instructs the connected agent never to answer from prior knowledge — inventory, orders and sales change continuously, so a remembered number is a wrong number.
Status
Complete. Twenty-one tools — seventeen read-only, four that change the store — implemented, unit tested and verified against a live Shopify store.
Area | State |
Build, TypeScript strict mode, ESLint, Prettier | ✅ Complete |
Configuration + fail-fast environment validation | ✅ Complete |
Shopify authentication (client credentials + renewal) | ✅ Complete |
Error hierarchy + RFC 9457 global handler | ✅ Complete |
Structured logging + correlation context | ✅ Complete |
Application Insights telemetry | ✅ Complete |
Shopify GraphQL client (retry, cost, throttle, paging) | ✅ Complete |
MCP registry, server factory, Streamable HTTP transport | ✅ Complete |
Health / readiness / version endpoints | ✅ Complete |
All 21 MCP tools | ✅ Complete |
Store-changing tools, gated and confirmed | ✅ Complete |
Test suite | ✅ 446 passing |
Related MCP server: Clind MCP Server
Available MCP tools
Catalogue
Tool | Answers |
| "How many Nike shoes are in stock?", "Find products under 50", "What perfumes do we sell?" |
| Full record for one product: every variant, price, SKU, stock level, options and collections. |
| "What else would go with this?" — catalogue similarity, not purchase behaviour. |
| "What collections do we have?", "Is that collection rule-based or curated?" |
Orders, fulfilment and customers
Tool | Answers |
| "How many orders this week?", "Show unfulfilled orders", "Any refunds?" |
| Everything about one order: line items, addresses, fulfilment, refunds. |
| "What has shipped?", "How long are we taking to despatch?", "No tracking?" |
| "How much have we refunded?", "What came back, and was it restocked?" |
| "Who are our customers?", "Find customers tagged VIP", "Customers in India" |
| One customer's full profile, addresses and lifetime value. |
| "What has this person bought?", "When did they last order?" |
Inventory
Tool | Answers |
| "What's in stock?", "Stock level for SKU X", "Anything oversold?" |
| "What's running low?", "What do we need to reorder?" |
Commercial
Tool | Answers |
| "How much did we sell last month?", "What's our average order value?" |
| "What are our top sellers?", "Which product made the most revenue?" |
| "What promotions are running?", "Is the free shipping offer still active?" |
| "How many abandoned carts?", "What revenue are we losing at checkout?" |
Every list tool filters and paginates server-side in Shopify. A price filter applied locally could only narrow the page that happened to be fetched, so "products under 50" would silently come to mean "products under 50 among the 20 that came back".
Tools that change the store
Tool | Effect |
| Adds a product. Created as DRAFT unless |
| Changes title, description, vendor, type, tags or status. |
| Sets or adjusts stock on hand, which decides what customers can buy. |
| Returns real money to a customer. Cannot be undone. |
Three independent controls stand in front of them:
Registration gate.
MCP_ENABLE_WRITE_TOOLS=falsewithholds all four fromtools/listentirely — an agent cannot call what was never published. It is a single App Service setting, so the capability can be withdrawn during an incident without a redeploy.Explicit confirmation. Every one requires
confirm: true. Called without it they change nothing and instead report exactly what would change — for stock, after reading the live level, so the user approves real before-and-after figures rather than an intention.userErrorsenforcement. Shopify rejects a mutation with HTTP 200, a null payload and the reason inuserErrors. Every mutation response is checked, so a write that did not happen is never reported as one that did.
create_refund adds two more: the amount is always computed by Shopify's own suggestedRefund
rather than by this server, and MCP_MAX_REFUND_AMOUNT can cap any single refund.
Every completed change writes an audit line carrying the correlation ID; refunds log at warn.
Documentation
Document | Covers |
Layering, request flow, and the reasoning behind each design decision | |
Every environment variable, production invariants, common misconfigurations | |
Full Azure App Service procedure, slots, scaling, rollback, checklist | |
Connector import, agent wiring, grounding instructions, troubleshooting | |
Power Platform custom connector definition | |
Each tool with real request/response examples | |
Runbook: KQL queries, alerts, incident diagnosis, rotation |
Architecture
┌──────────────────────┐ Streamable HTTP (JSON-RPC 2.0) ┌────────────────────────────┐
│ Copilot Studio │ ─────────────────────────────────► │ Azure App Service (Linux) │
│ custom connector │ HTTPS + x-api-key │ Fastify + MCP SDK │
└──────────────────────┘ └─────────────┬──────────────┘
│
┌─────────────────────────────────────────────────┘
▼
┌───────────────────────────┐ Correlation context (AsyncLocalStorage)
│ MCP transport │ flows through every layer below
│ (stateless per request) │
└─────────────┬─────────────┘
▼
┌───────────────────────────┐ Cross-cutting: validation, timing,
│ Tool executor │ envelope, error → result, telemetry
└─────────────┬─────────────┘
▼
┌───────────────────────────┐ Business logic only
│ Service layer │
└─────────────┬─────────────┘
▼
┌───────────────────────────┐ Retry · cost governor · pagination
│ ShopifyGraphQLClient │ error mapping · dependency telemetry
└─────────────┬─────────────┘
▼
Shopify Admin GraphQL APILayer rules
Tools contain no business logic. They validate input, call a service, and return a summary plus structured data.
Services contain no MCP or HTTP concepts. They accept typed arguments and return domain objects.
The Shopify client is the only egress point. Nothing else issues an outbound request.
Configuration is read once, validated, frozen. No module touches
process.envdirectly.
Project structure
src/
app/ Fastify composition root, plugins, routes, error handler
config/ Environment schema, validated + frozen configuration
mcp/
registry/ Tool definitions and the process-wide tool catalogue
server/ McpServer factory and the tool execution wrapper
transport/ Streamable HTTP transport management
tools/ MCP tool definitions (composition root)
services/ Domain services (product, order, inventory, customer, …)
shopify/
graphql-client.ts Retry, cost governance, error mapping, telemetry
cost-governor.ts Client-side model of Shopify's leaky bucket
error-mapper.ts HTTP + GraphQL failure classification
pagination.ts Bounded cursor pagination
queries/ Reusable GraphQL documents
types/ Connection, money and cost types
middleware/
auth/ API key authentication
logging/ Pino logger and AsyncLocalStorage request context
telemetry/ Application Insights behind a vendor-neutral port
errors/ Error hierarchy, codes, normaliser
schemas/ Shared Zod schemas
utils/ Identifiers, timing, backoff
types/ Shared type declarations
tests/
unit/ integration/ mocks/ helpers/
docs/Getting started
Prerequisites
Node.js 22 LTS (the toolchain also runs on Node 24)
npm 10+
A Shopify app created in the Dev Dashboard, installed on your store
Install and run
npm install
cp .env.example .env # then fill in the Shopify values
npm run dev # watch modenpm run build && npm start # production buildVerify
npm run verify # typecheck + lint + tests
npm run test:coverage # coverage reportcurl http://localhost:8080/health
curl http://localhost:8080/ready
curl http://localhost:8080/versionMCP handshake:
curl -X POST http://localhost:8080/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
"protocolVersion":"2025-06-18","capabilities":{},
"clientInfo":{"name":"curl","version":"1.0"}}}'Getting the Shopify credentials
Shopify has retired legacy custom apps. The store admin no longer offers "Create an app", and there is no long-lived Admin API token to copy anywhere. Apps are now created in the Shopify Dev Dashboard, and credentials are exchanged for a short-lived access token through the OAuth client credentials grant.
Create an app in the Dev Dashboard and install it on your store.
Open your app → Settings → Credentials and copy the Client ID and Secret (
shpss_…).Set them as
SHOPIFY_CLIENT_IDandSHOPIFY_CLIENT_SECRET.
The server exchanges them for a token at startup and renews it automatically. Verify manually with:
curl -X POST https://<store>.myshopify.com/admin/oauth/access_token \
-d grant_type=client_credentials \
-d client_id=<CLIENT_ID> -d client_secret=<CLIENT_SECRET>
# -> {"access_token":"shpat_…","scope":"…","expires_in":86399}
expires_inis 24 hours. This is why a pastedSHOPIFY_ADMIN_ACCESS_TOKENis rejected in production: it works the day it is set and starts returning HTTP 401 the next.
The grant requires the app and the store to be in the same Shopify organization. If they are not, Shopify answers
invalid_client— which looks identical to a wrong secret.
Required read scopes: read_products, read_inventory, read_locations, read_orders,
read_all_orders, read_customers, read_discounts, read_price_rules, read_analytics,
read_marketing_events.
Grant read scopes only. This server is read-only and advertises
readOnlyHint: true, but the credential itself is not constrained by that — an app grantedwrite_productsholds the ability to delete a catalogue, on a connection whose other end is an LLM.
Configuration
Every variable is validated at startup. A misconfigured deployment fails immediately with every offending variable listed at once, rather than failing on the first one or booting half-configured.
See .env.example for the full annotated contract. The essentials:
Variable | Required | Default | Purpose |
| Yes | — | Store handle or |
| Yes¹ | — | Dev Dashboard app client ID |
| Yes¹ | — | Dev Dashboard app secret ( |
| Local dev only¹ | — | Pre-minted token; expires in 24h |
| No |
| Quarterly Admin API version |
| No |
| Injected by App Service |
| No |
| Must match the connector's declared path |
| In production | — | Shared secret for the connector |
| In production | — | DNS-rebinding protection allowlist |
| In production | — | Application Insights |
| Must be |
| Human-readable logs (local only) |
¹ Supply either the client credentials pair or a static token. Startup fails if neither is
present. When both are given, client credentials win — they are the only renewable option — and the
active mode is stated in the startup log and on GET /version.
Production invariants
The server refuses to start in NODE_ENV=production when any of these hold:
no
MCP_API_KEY— an unauthenticated MCP endpoint exposes the store's entire order and customer dataset to anonymous callers;no
APPINSIGHTS_CONNECTION_STRING;no
MCP_ALLOWED_HOSTS;LOG_PRETTY=true;a static
SHOPIFY_ADMIN_ACCESS_TOKENinstead of client credentials — it would expire within 24 hours with no way to renew itself.
These are configuration errors, not warnings.
Operational endpoints
Endpoint | Question answered | Behaviour |
| Is the process alive? | Always 200 while running. No I/O. |
| Can this instance serve a request? | 200 / 503 based on a cached, 1-cost-point Shopify probe. |
| Which build, store, API version, tools? | Build identity and the published tool catalogue. |
Configure the App Service health check against
/health, not/ready. Pointing the platform probe at a dependency-aware endpoint makes App Service recycle healthy workers during a Shopify incident, turning a degraded service into an outage. Use/readyfor deployment gates and load balancer decisions.
Design decisions worth knowing
Stateless MCP sessions by default. A fresh McpServer is built per request, so any App Service
instance can serve any request and scale-out needs no ARR affinity. MCP_SESSION_MODE=stateful is
available but requires session affinity.
Tokens are minted and renewed by the server. Shopify's client credentials grant issues 24-hour tokens. The provider caches one in memory, renews it 5 minutes before expiry, and collapses concurrent callers onto a single in-flight mint so a burst of tool calls on a cold instance does not trigger a token request each. If Shopify rejects a token early — after a credential rotation — the client discards it and retries exactly once, outside the retry budget, so recovery also works for callers that disable retries (such as the readiness probe).
Client-side cost governance. Shopify meters GraphQL by query cost against a leaky bucket
(1000 points refilling at 50/s on standard plans; the live test store reported 4000 at 200/s). The
client reads extensions.cost from every response, adopts whatever limits the store actually
reports, and waits for headroom before dispatching — rather than absorbing a THROTTLED error and
retrying into an empty bucket.
Search filters come from an allowlist. Shopify silently ignores filter fields it does not
recognise: price:<50 filters correctly, while variants.price:<50 is dropped and returns
unfiltered products with HTTP 200 and no error at all. An agent would then relay those results as
though they satisfied the filter. Every field name the query builder emits is drawn from a fixed
list verified against the live API, and values are escaped and quoted.
Stock figures are reported honestly. Shopify returns totalInventory: null for untracked
products, which is not the same as zero in stock, so the domain model keeps a separate
inventoryTracked flag. Live data also showed a product reporting totalInventory: 0 while its
variants stood at -31, -19 and -23; the summary states the oversell rather than repeating the zero.
Throttling arrives as HTTP 200. The Admin API reports throttling as a successful HTTP response
with errors[].extensions.code === "THROTTLED". The client checks the GraphQL error array and the
HTTP status, and classifies each failure mode for retryability independently.
Tool failures are returned, not thrown. A thrown error becomes a JSON-RPC protocol error, which
Copilot Studio surfaces as an opaque connector failure the agent cannot reason about. Tool failures
are returned as isError: true results carrying the reason, retryability, remediation and
correlation ID, so the agent can explain the problem to the user.
Uniform response envelope. Every tool returns { summary, resultCount, truncated, data }.
summary gives the agent a grounded sentence it can relay verbatim; truncated lets it state
honestly that a figure is a bounded sample rather than a store-wide total.
Correlation without plumbing. Correlation IDs propagate through AsyncLocalStorage, so the
domain layer carries no context parameters, yet every log line, telemetry item and Shopify call is
attributable to the originating request.
Copilot Studio compatibility
Streamable HTTP only. Copilot Studio dropped SSE transport support in August 2025.
Custom connector with
x-ms-agentic-protocol: mcp-streamable-1.0on a POST operation.HTTPS, terminated by App Service.
Accept header shim. The MCP specification requires clients to accept both
application/jsonandtext/event-stream. Power Platform connectors may forward onlyapplication/json, which the SDK rejects with HTTP 406 — surfacing in Copilot Studio as an unexplained connector failure. The MCP route widens the header (onrawHeaders, which is what the transport actually reads).Tool metadata is validated at registration:
snake_casenames and descriptions long enough to drive orchestrator routing. Both input and output schemas are published.
Connector setup, the OpenAPI schema and Azure deployment steps are documented in a later milestone.
Testing
npm test # all suites
npm run test:unit
npm run test:integration
npm run test:coverageIntegration tests drive the real Fastify instance via app.inject() — correlation hooks, security
plugins, error handler, route wiring and the MCP SDK transport all execute; only the network is
absent. Shopify is substituted at the transport seam, so retry sequencing, cost accounting and error
mapping are exercised for real.
Scripts
Script | Purpose |
| Watch mode via tsx |
| Clean + compile to |
| Run the compiled server |
| Typecheck + lint + test |
|
|
| ESLint, zero warnings tolerated |
| Prettier |
Troubleshooting
Symptom | Cause and fix |
Startup fails listing environment variables | Working as designed. Fix every listed variable; all problems are reported at once. |
| Wrong client credentials, app and store in different Shopify organizations, or a missing read scope. |
|
|
HTTP 406 from | The client sent a narrow |
HTTP 401 from |
|
Frequent | The store's cost budget is under pressure. Raise |
Logs are unreadable JSON locally | Set |
Every error response and tool failure carries a correlation ID. Search Application Insights on
customDimensions.correlationId to retrieve the full request trace, including each Shopify call,
its cost and its outcome.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceThis MCP server connects clients with Shopify store data, enabling retrieval of product and customer information via exposed tools.Last updated6MIT
- Flicense-quality-maintenanceA Shopify-focused MCP server that enables AI agents to manage store operations like order tracking, product discovery, and checkout link generation. It facilitates customer-facing interactions including shipping estimates and real-time inventory searches.Last updated
- Alicense-qualityFmaintenanceA comprehensive MCP server for Shopify Admin API integration, enabling AI assistants to manage products, orders, customers, inventory, analytics, and more through natural language.Last updated3218MIT
- Alicense-qualityDmaintenanceProduction-grade MCP server for the Shopify Admin GraphQL API, exposing typed tools for AI agents to manage products, orders, customers, and more.Last updated16MIT
Related MCP Connectors
Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.
Shopify MCP Pack — wraps the Shopify Admin REST API (2024-01)
Hosted Amazon Seller Central and Amazon Ads MCP server for Claude, ChatGPT, Cursor, and agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/aakarsh1t/ShopifyMCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server