Shopify MCP Manager
An MCP (Model Context Protocol) server for fully managing a Shopify store through AI assistants like Cursor or Claude Desktop.
Architecture
┌─────────────────┐ stdio ┌──────────────────┐ GraphQL ┌──────────────┐
│ Cursor / Claude │◄──────────────►│ MCP Server │◄────────────►│ Shopify API │
│ (MCP Client) │ │ (Node.js) │ │ Admin API │
└─────────────────┘ └──────────────────┘ └──────────────┘
│
▼
┌──────────────────┐
│ token-store.json │
│ (Access Token) │
└──────────────────┘
OAuth Flow
┌──────────┐ 1. /auth/start ┌──────────────────┐
│ Browser │◄────────────────────►│ OAuth Server │
│ │ │ (localhost:3847) │
└─────┬─────┘ └──────────────────┘
│ ▲
│ 2. Redirect to Shopify │ 5. Save token
▼ │
┌──────────────┐ 3. Authorize ┌──────────────────────────────┐
│ Shopify │───────────────►│ Cloudflare Worker │
│ Grant Screen│ 4. Callback │ (your-oauth-callback. │
└──────────────┘ + Auth Code │ workers.dev) │
│ │ │
│ Redirect to localhost:3847 │
│ /callback │
└──────────────────────────────┘
Prerequisites
- Node.js >= 18
- A Shopify App (created in the Dev Dashboard)
- A Cloudflare Worker for URL redirect (OAuth callback)
Quick Start
1. Install dependencies
npm install
2. Configuration
Copy .env.example to .env and fill in your values:
cp .env.example .env
Required values from the Shopify Dev Dashboard:
- SHOPIFY_API_KEY → Client ID of your app
- SHOPIFY_API_SECRET → Client Secret of your app
- SHOPIFY_DOMAIN → Your myshopify.com domain
- SHOPIFY_REDIRECT_URL → Your Cloudflare Worker callback URL
3. Configure Shopify App
In the Shopify Dev Dashboard under your app:
- Set App URL to your Cloudflare Worker domain (e.g.
https://your-oauth-callback.workers.dev) - Add Allowed redirection URLs:
https://your-oauth-callback.workers.dev/callback
4. Configure Cloudflare Worker
Your Cloudflare Worker must redirect OAuth callbacks from Shopify to your local server.
Example Worker:
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// OAuth callback from Shopify → Redirect to local server
if (url.pathname === "/callback") {
const localUrl = `http://localhost:3847/callback${url.search}`;
return Response.redirect(localUrl, 302);
}
// App URL request from Shopify → Redirect to local server
if (url.searchParams.has("shop")) {
const localUrl = `http://localhost:3847${url.pathname}${url.search}`;
return Response.redirect(localUrl, 302);
}
return new Response("Shopify OAuth Endpoint active.", { status: 200 });
},
};
5. Run OAuth
npm run oauth
This starts a local server and opens the browser. Log in to Shopify and grant the permissions. The access token is automatically saved to token-store.json.
6. Configure MCP Server in Cursor
Add the following to your Cursor configuration (~/.cursor/mcp.json):
{
"mcpServers": {
"shopify-manager": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/src/mcp-server.js"],
"env": {
"SHOPIFY_DOMAIN": "your-store.myshopify.com",
"SHOPIFY_API_VERSION": "2026-01"
}
}
}
}
Available Tools (30+)
Shop Management
| Tool | Description | |------|-------------| | shop_info | Shop basics (name, domain, plan, currency) | | shop_locales | Configured languages | | shop_policies | Privacy, terms of service, refund policies | | available_shipping_countries | Shipping destinations |
Products
| Tool | Description | |------|-------------| | list_products | List products with filtering & pagination | | get_product | Product details with variants & images | | create_product | Create a new product | | update_product | Update a product | | delete_product | Delete a product | | list_collections | List collections |
Orders
| Tool | Description | |------|-------------| | list_orders | List orders with filtering | | get_order | Order details | | update_order | Update an order | | cancel_order | Cancel an order | | create_draft_order | Create a draft order |
Customers
| Tool | Description | |------|-------------| | list_customers | List customers | | get_customer | Customer details | | create_customer | Create a new customer | | update_customer | Update a customer | | delete_customer | Delete a customer |
Inventory
| Tool | Description | |------|-------------| | list_locations | List locations | | get_inventory_levels | Show inventory levels | | adjust_inventory | Adjust inventory | | get_product_inventory | Full product inventory |
Discounts
| Tool | Description | |------|-------------| | list_discount_codes | List discount codes | | create_basic_discount | Create a discount code | | list_automatic_discounts | List automatic discounts |
Analytics
| Tool | Description | |------|-------------| | get_order_count | Count orders | | get_product_count | Count products | | get_customer_count | Count customers | | shop_dashboard_summary | Dashboard overview | | graphql_query | Run arbitrary GraphQL queries |
OAuth Flow Details
The OAuth 2.0 Authorization Code Grant flow works as follows:
- Initiation: User starts the OAuth flow via
http://localhost:3847/auth/start - Redirect to Shopify: The app redirects the user to Shopify's authorization page with:
client_id(App API Key)scope(requested permissions)redirect_uri(Cloudflare Worker URL)state(nonce for CSRF protection)
- User authorizes: The store owner grants the requested permissions
- Callback: Shopify sends an authorization code to the redirect_uri
- Cloudflare Worker: Redirects the callback to the local OAuth server
- Security checks:
- HMAC verification (message authenticity from Shopify)
- State/nonce comparison (CSRF protection)
- Shop domain validation
- Token exchange: The authorization code is exchanged for an access token via
POST https://{shop}/admin/oauth/access_token - Persistence: The token is saved to
token-store.json
Security Notes
- Never commit
token-store.jsonor.env(both are in.gitignore) - The
SHOPIFY_API_SECRETis confidential - Access tokens have the permissions of the configured scopes
- If you suspect token compromise: rotate the token via the Shopify Dev Dashboard
License
MIT












