shopify-store-mcp 1.0.2 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +233 -50
- package/dist/config.js +1 -1
- package/dist/errors.js +1 -1
- package/dist/graphql/admin/specialized/bulk.d.ts +13 -3
- package/dist/graphql/admin/specialized/bulk.js +43 -3
- package/dist/resources/index.js +128 -0
- package/dist/tools/graphql.d.ts +1 -1
- package/dist/tools/graphql.js +34 -3
- package/dist/tools/index.js +2 -2
- package/dist/tools/infrastructure.js +32 -2
- package/dist/tools/shop.d.ts +1 -1
- package/dist/tools/shop.js +29 -2
- package/dist/tools/smart-bulk.js +16 -8
- package/dist/tools/smart-files.d.ts +1 -0
- package/dist/tools/smart-files.js +180 -31
- package/dist/tools/smart-metaobjects.js +118 -1
- package/dist/types.d.ts +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,44 +6,99 @@
|
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
|
|
9
|
-
A Model Context Protocol (MCP) server that connects to **live Shopify stores** via the Admin and Storefront APIs. Unlike documentation-only MCPs, this server enables AI agents to perform real operations on your store.
|
|
9
|
+
A Model Context Protocol (MCP) server that connects to **live Shopify stores** via the Admin and Storefront APIs. Unlike documentation-only MCPs, this server enables AI agents to perform **real operations** on your store.
|
|
10
|
+
|
|
11
|
+
## Why This MCP?
|
|
12
|
+
|
|
13
|
+
| Feature | Shopify Store MCP | [Shopify Dev MCP](https://shopify.dev/docs/apps/build/devmcp) |
|
|
14
|
+
|---------|-------------------|---------------------------------------------------------------|
|
|
15
|
+
| Execute GraphQL queries | ✅ Real API calls | ❌ Documentation only |
|
|
16
|
+
| Modify store data | ✅ Full CRUD | ❌ No |
|
|
17
|
+
| Upload files | ✅ Yes | ❌ No |
|
|
18
|
+
| Bulk operations | ✅ Yes | ❌ No |
|
|
19
|
+
| API documentation | ❌ No | ✅ Yes |
|
|
20
|
+
| Schema introspection | ❌ No | ✅ Yes |
|
|
21
|
+
|
|
22
|
+
> **Important:** For the best experience, use **both** this MCP and the official [Shopify Dev MCP](https://shopify.dev/docs/apps/build/devmcp) together. The Dev MCP helps your AI agent understand Shopify's API schemas and documentation, while this MCP executes the actual operations on your store.
|
|
10
23
|
|
|
11
24
|
## Features
|
|
12
25
|
|
|
13
|
-
- **Universal GraphQL Access**
|
|
14
|
-
- **Smart Multi-Step Tools**
|
|
15
|
-
- **Rate Limiting**
|
|
16
|
-
- **Operation Logging**
|
|
17
|
-
- **Schema Discovery**
|
|
26
|
+
- **Universal GraphQL Access** — Execute any Admin API query or mutation via `run_graphql_query`
|
|
27
|
+
- **Smart Multi-Step Tools** — File uploads, bulk operations, metaobject upserts with automatic polling
|
|
28
|
+
- **Rate Limiting** — Respects Shopify's plan-based rate limits (Standard/Advanced/Plus/Enterprise)
|
|
29
|
+
- **Operation Logging** — SQLite database tracks all operations for debugging and history
|
|
30
|
+
- **Schema Discovery** — Explore your store's metafield definitions and metaobject types
|
|
18
31
|
|
|
19
|
-
##
|
|
32
|
+
## Prerequisites
|
|
20
33
|
|
|
21
|
-
|
|
34
|
+
1. **Node.js 18+**
|
|
35
|
+
2. **Shopify store** with a [custom app](https://help.shopify.com/en/manual/apps/app-types/custom-apps)
|
|
36
|
+
3. **Admin API access token** — Create a custom app in Shopify Admin → Settings → Apps and development channels → Develop apps
|
|
22
37
|
|
|
23
|
-
|
|
24
|
-
2. Admin API access token with required scopes
|
|
25
|
-
3. Node.js 18+
|
|
38
|
+
## Installation
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
<details>
|
|
41
|
+
<summary><strong>Cursor</strong></summary>
|
|
28
42
|
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
### Quick Install
|
|
44
|
+
|
|
45
|
+
[](https://cursor.com/install-mcp?name=shopify-store-mcp&config=eyJtY3BTZXJ2ZXJzIjp7InNob3BpZnktc3RvcmUtbWNwIjp7ImNvbW1hbmQiOiJucHgiLCJhcmdzIjpbIi15Iiwic2hvcGlmeS1zdG9yZS1tY3AiXSwiZW52Ijp7IlNIT1BJRllfU1RPUkVfVVJMIjoieW91ci1zdG9yZS5teXNob3BpZnkuY29tIiwiU0hPUElGWV9BQ0NFU1NfVE9LRU4iOiJzaHBhdF94eHh4eHh4eHh4eHh4eHh4eHh4eHgifX19fQ==)
|
|
46
|
+
|
|
47
|
+
After installing, edit the configuration to add your actual store credentials.
|
|
48
|
+
|
|
49
|
+
### Manual Configuration
|
|
50
|
+
|
|
51
|
+
Add to your Cursor MCP settings (`~/.cursor/mcp.json`):
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"shopify-store-mcp": {
|
|
57
|
+
"command": "npx",
|
|
58
|
+
"args": ["-y", "shopify-store-mcp"],
|
|
59
|
+
"env": {
|
|
60
|
+
"SHOPIFY_STORE_URL": "your-store.myshopify.com",
|
|
61
|
+
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
31
66
|
```
|
|
32
67
|
|
|
33
|
-
|
|
68
|
+
<details>
|
|
69
|
+
<summary>Windows Configuration</summary>
|
|
34
70
|
|
|
35
|
-
```
|
|
36
|
-
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"shopify-store-mcp": {
|
|
75
|
+
"command": "cmd",
|
|
76
|
+
"args": ["/k", "npx", "-y", "shopify-store-mcp"],
|
|
77
|
+
"env": {
|
|
78
|
+
"SHOPIFY_STORE_URL": "your-store.myshopify.com",
|
|
79
|
+
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
37
84
|
```
|
|
38
85
|
|
|
39
|
-
|
|
86
|
+
</details>
|
|
87
|
+
|
|
88
|
+
</details>
|
|
89
|
+
|
|
90
|
+
<details>
|
|
91
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
40
92
|
|
|
41
|
-
Add
|
|
93
|
+
Add to your Claude Desktop config:
|
|
94
|
+
|
|
95
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
96
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
42
97
|
|
|
43
98
|
```json
|
|
44
99
|
{
|
|
45
100
|
"mcpServers": {
|
|
46
|
-
"shopify-store": {
|
|
101
|
+
"shopify-store-mcp": {
|
|
47
102
|
"command": "npx",
|
|
48
103
|
"args": ["-y", "shopify-store-mcp"],
|
|
49
104
|
"env": {
|
|
@@ -55,12 +110,13 @@ Add the following to your MCP configuration:
|
|
|
55
110
|
}
|
|
56
111
|
```
|
|
57
112
|
|
|
58
|
-
|
|
113
|
+
<details>
|
|
114
|
+
<summary>Windows Configuration</summary>
|
|
59
115
|
|
|
60
116
|
```json
|
|
61
117
|
{
|
|
62
118
|
"mcpServers": {
|
|
63
|
-
"shopify-store": {
|
|
119
|
+
"shopify-store-mcp": {
|
|
64
120
|
"command": "cmd",
|
|
65
121
|
"args": ["/k", "npx", "-y", "shopify-store-mcp"],
|
|
66
122
|
"env": {
|
|
@@ -72,15 +128,131 @@ On Windows, use this configuration:
|
|
|
72
128
|
}
|
|
73
129
|
```
|
|
74
130
|
|
|
131
|
+
</details>
|
|
132
|
+
|
|
133
|
+
</details>
|
|
134
|
+
|
|
135
|
+
<details>
|
|
136
|
+
<summary><strong>Claude Code (CLI)</strong></summary>
|
|
137
|
+
|
|
138
|
+
Add to your Claude Code settings (`~/.claude/settings.json`):
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"mcpServers": {
|
|
143
|
+
"shopify-store-mcp": {
|
|
144
|
+
"command": "npx",
|
|
145
|
+
"args": ["-y", "shopify-store-mcp"],
|
|
146
|
+
"env": {
|
|
147
|
+
"SHOPIFY_STORE_URL": "your-store.myshopify.com",
|
|
148
|
+
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
</details>
|
|
156
|
+
|
|
157
|
+
<details>
|
|
158
|
+
<summary><strong>VS Code (Copilot)</strong></summary>
|
|
159
|
+
|
|
160
|
+
Add to your VS Code settings (`settings.json`):
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"mcp.servers": {
|
|
165
|
+
"shopify-store-mcp": {
|
|
166
|
+
"command": "npx",
|
|
167
|
+
"args": ["-y", "shopify-store-mcp"],
|
|
168
|
+
"env": {
|
|
169
|
+
"SHOPIFY_STORE_URL": "your-store.myshopify.com",
|
|
170
|
+
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
</details>
|
|
178
|
+
|
|
179
|
+
<details>
|
|
180
|
+
<summary><strong>Windsurf</strong></summary>
|
|
181
|
+
|
|
182
|
+
Add to your Windsurf MCP config (`~/.windsurf/mcp.json`):
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"mcpServers": {
|
|
187
|
+
"shopify-store-mcp": {
|
|
188
|
+
"command": "npx",
|
|
189
|
+
"args": ["-y", "shopify-store-mcp"],
|
|
190
|
+
"env": {
|
|
191
|
+
"SHOPIFY_STORE_URL": "your-store.myshopify.com",
|
|
192
|
+
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
</details>
|
|
200
|
+
|
|
201
|
+
<details>
|
|
202
|
+
<summary><strong>Other MCP Clients</strong></summary>
|
|
203
|
+
|
|
204
|
+
For any MCP-compatible client, use:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npx -y shopify-store-mcp
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
With environment variables:
|
|
211
|
+
- `SHOPIFY_STORE_URL` — Your store's myshopify.com domain
|
|
212
|
+
- `SHOPIFY_ACCESS_TOKEN` — Admin API access token
|
|
213
|
+
|
|
214
|
+
</details>
|
|
215
|
+
|
|
216
|
+
## Recommended: Add Shopify Dev MCP
|
|
217
|
+
|
|
218
|
+
For the best AI agent experience, also add the official **[Shopify Dev MCP](https://shopify.dev/docs/apps/build/devmcp)**. It provides:
|
|
219
|
+
|
|
220
|
+
- API documentation search
|
|
221
|
+
- GraphQL schema introspection
|
|
222
|
+
- Query validation
|
|
223
|
+
- Up-to-date Shopify API knowledge
|
|
224
|
+
|
|
225
|
+
This helps your AI agent know **what queries to write** before executing them with this MCP.
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"mcpServers": {
|
|
230
|
+
"shopify-store-mcp": {
|
|
231
|
+
"command": "npx",
|
|
232
|
+
"args": ["-y", "shopify-store-mcp"],
|
|
233
|
+
"env": {
|
|
234
|
+
"SHOPIFY_STORE_URL": "your-store.myshopify.com",
|
|
235
|
+
"SHOPIFY_ACCESS_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxxxx"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
"shopify-dev-mcp": {
|
|
239
|
+
"command": "npx",
|
|
240
|
+
"args": ["-y", "@shopify/dev-mcp@latest"]
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
75
246
|
## Environment Variables
|
|
76
247
|
|
|
77
248
|
| Variable | Required | Default | Description |
|
|
78
249
|
|----------|----------|---------|-------------|
|
|
79
|
-
| `SHOPIFY_STORE_URL` | Yes |
|
|
80
|
-
| `SHOPIFY_ACCESS_TOKEN` | Yes |
|
|
81
|
-
| `SHOPIFY_STOREFRONT_ACCESS_TOKEN` | No |
|
|
82
|
-
| `SHOPIFY_API_VERSION` | No | `
|
|
250
|
+
| `SHOPIFY_STORE_URL` | Yes | — | Store's myshopify.com domain |
|
|
251
|
+
| `SHOPIFY_ACCESS_TOKEN` | Yes | — | Admin API access token |
|
|
252
|
+
| `SHOPIFY_STOREFRONT_ACCESS_TOKEN` | No | — | Storefront API token |
|
|
253
|
+
| `SHOPIFY_API_VERSION` | No | `2026-01` | API version (or `unstable` for bleeding edge) |
|
|
83
254
|
| `SHOPIFY_TIER` | No | `STANDARD` | Rate limit tier |
|
|
255
|
+
| `MCP_LOG_OPERATIONS` | No | `true` | Enable operation logging |
|
|
84
256
|
|
|
85
257
|
## Available Tools
|
|
86
258
|
|
|
@@ -88,17 +260,20 @@ On Windows, use this configuration:
|
|
|
88
260
|
|
|
89
261
|
| Tool | Description |
|
|
90
262
|
|------|-------------|
|
|
91
|
-
| `get_shop_info` | Retrieve store configuration and settings |
|
|
92
|
-
| `run_graphql_query` | Execute any GraphQL query or mutation |
|
|
263
|
+
| `get_shop_info` | Retrieve store configuration, plan info, and settings |
|
|
264
|
+
| `run_graphql_query` | **Universal tool** — Execute any GraphQL query or mutation |
|
|
93
265
|
|
|
94
266
|
### Smart Tools
|
|
95
267
|
|
|
268
|
+
Multi-step workflows that handle complexity automatically:
|
|
269
|
+
|
|
96
270
|
| Tool | Description |
|
|
97
271
|
|------|-------------|
|
|
98
|
-
| `upload_file` | Upload file
|
|
99
|
-
| `bulk_export` | Start bulk query
|
|
100
|
-
| `bulk_import` | Staged upload
|
|
272
|
+
| `upload_file` | Upload file (URL, local path, or base64) → poll until ready → return CDN URL |
|
|
273
|
+
| `bulk_export` | Start bulk query → poll completion → return JSONL download URL |
|
|
274
|
+
| `bulk_import` | Staged upload → bulk mutation → poll completion |
|
|
101
275
|
| `upsert_metaobject` | Create or update metaobject by handle (idempotent) |
|
|
276
|
+
| `delete_metaobject` | Delete metaobject by ID or type+handle |
|
|
102
277
|
| `schema_discover` | Discover metafield definitions and metaobject types |
|
|
103
278
|
|
|
104
279
|
### Infrastructure Tools
|
|
@@ -107,20 +282,20 @@ On Windows, use this configuration:
|
|
|
107
282
|
|------|-------------|
|
|
108
283
|
| `configure` | Set rate limit tier (manual or auto-detect from shop plan) |
|
|
109
284
|
| `get_history` | Query past operations for debugging |
|
|
110
|
-
| `get_stats` | Aggregated usage statistics |
|
|
285
|
+
| `get_stats` | Aggregated usage statistics (calls, errors, response times) |
|
|
111
286
|
|
|
112
287
|
## Rate Limiting
|
|
113
288
|
|
|
114
|
-
The server respects Shopify's rate limits based on your shop plan:
|
|
289
|
+
The server automatically respects Shopify's rate limits based on your shop plan:
|
|
115
290
|
|
|
116
291
|
| Tier | Requests/sec | Plans |
|
|
117
292
|
|------|--------------|-------|
|
|
118
|
-
| STANDARD | 1 | Basic, Development, Lite |
|
|
119
|
-
| ADVANCED | 2 | Advanced |
|
|
120
|
-
| PLUS | 5 | Shopify Plus |
|
|
121
|
-
| ENTERPRISE | 10 | Commerce Components |
|
|
293
|
+
| `STANDARD` | 1 | Basic, Development, Lite |
|
|
294
|
+
| `ADVANCED` | 2 | Advanced |
|
|
295
|
+
| `PLUS` | 5 | Shopify Plus |
|
|
296
|
+
| `ENTERPRISE` | 10 | Commerce Components |
|
|
122
297
|
|
|
123
|
-
Use the `configure` tool to set your tier
|
|
298
|
+
Use the `configure` tool to set your tier or auto-detect from your shop plan.
|
|
124
299
|
|
|
125
300
|
## Available Prompts
|
|
126
301
|
|
|
@@ -144,35 +319,43 @@ Use the `configure` tool to set your tier manually or auto-detect from your shop
|
|
|
144
319
|
## Development
|
|
145
320
|
|
|
146
321
|
```bash
|
|
322
|
+
# Clone the repo
|
|
323
|
+
git clone https://github.com/Brahim-Benzarti/Shopify_store-MCP.git
|
|
324
|
+
cd Shopify_store-MCP
|
|
325
|
+
|
|
147
326
|
# Install dependencies
|
|
148
327
|
npm install
|
|
149
328
|
|
|
150
329
|
# Build
|
|
151
330
|
npm run build
|
|
152
331
|
|
|
153
|
-
# Run with
|
|
332
|
+
# Run with MCP Inspector
|
|
154
333
|
npm run inspect
|
|
155
334
|
|
|
156
335
|
# Watch mode
|
|
157
336
|
npm run dev
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Database
|
|
161
337
|
|
|
162
|
-
The server uses SQLite for operation logging and configuration. The database is automatically created at `~/.shopify-mcp/mcp.db`.
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
338
|
# View database
|
|
166
339
|
npm run db:studio
|
|
167
340
|
```
|
|
168
341
|
|
|
342
|
+
### Database
|
|
343
|
+
|
|
344
|
+
The server uses SQLite for operation logging and configuration. Database is automatically created at `~/.shopify-mcp/mcp.db`.
|
|
345
|
+
|
|
169
346
|
## Security
|
|
170
347
|
|
|
171
|
-
- Never commit your `.env` file or access tokens
|
|
172
|
-
- Use environment variables or MCP config for credentials
|
|
173
|
-
- Access tokens should have minimal required scopes
|
|
174
|
-
-
|
|
348
|
+
- **Never commit** your `.env` file or access tokens
|
|
349
|
+
- Use **environment variables** or MCP config for credentials
|
|
350
|
+
- Access tokens should have **minimal required scopes**
|
|
351
|
+
- Operations are logged locally for debugging (disable with `MCP_LOG_OPERATIONS=false`)
|
|
175
352
|
|
|
176
353
|
## License
|
|
177
354
|
|
|
178
|
-
ISC
|
|
355
|
+
[ISC](LICENSE)
|
|
356
|
+
|
|
357
|
+
## Related
|
|
358
|
+
|
|
359
|
+
- [Shopify Dev MCP](https://shopify.dev/docs/apps/build/devmcp) — Official Shopify MCP for API documentation
|
|
360
|
+
- [Shopify Admin API](https://shopify.dev/docs/api/admin-graphql) — GraphQL API reference
|
|
361
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/) — MCP specification
|
package/dist/config.js
CHANGED
|
@@ -16,7 +16,7 @@ export function loadConfig() {
|
|
|
16
16
|
const adminAccessToken = process.env.SHOPIFY_ACCESS_TOKEN;
|
|
17
17
|
const storefrontAccessToken = process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN;
|
|
18
18
|
const customerAccessToken = process.env.SHOPIFY_CUSTOMER_ACCESS_TOKEN;
|
|
19
|
-
const apiVersion = process.env.SHOPIFY_API_VERSION || "
|
|
19
|
+
const apiVersion = process.env.SHOPIFY_API_VERSION || "2026-01";
|
|
20
20
|
const bugReportEnabled = process.env.SHOPIFY_MCP_BUG_REPORTS === "true";
|
|
21
21
|
const bugReportBaseDir = process.env.SHOPIFY_MCP_BUG_REPORT_DIR;
|
|
22
22
|
if (!storeDomain) {
|
package/dist/errors.js
CHANGED
|
@@ -59,7 +59,7 @@ export function formatGraphQLErrors(response) {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
export function formatUserErrors(userErrors) {
|
|
62
|
-
const lines = userErrors.map((e) => `- ${e.field
|
|
62
|
+
const lines = userErrors.map((e) => `- ${e.field?.join(".") || "general"}: ${e.message}`);
|
|
63
63
|
return {
|
|
64
64
|
content: [
|
|
65
65
|
{
|
|
@@ -14,12 +14,22 @@ export declare const BULK_OPERATION_RUN_QUERY = "#graphql\n mutation BulkOperat
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const BULK_OPERATION_RUN_MUTATION = "#graphql\n mutation BulkOperationRunMutation($mutation: String!, $stagedUploadPath: String!) {\n bulkOperationRunMutation(mutation: $mutation, stagedUploadPath: $stagedUploadPath) {\n bulkOperation {\n id\n status\n url\n objectCount\n }\n userErrors {\n field\n message\n }\n }\n }\n";
|
|
16
16
|
/**
|
|
17
|
-
* Get current bulk operation status
|
|
18
|
-
*
|
|
17
|
+
* Get current bulk operation status (for queries)
|
|
18
|
+
* Deprecated in 2026-01, use GET_BULK_OPERATION_BY_ID instead
|
|
19
19
|
*/
|
|
20
20
|
export declare const GET_CURRENT_BULK_OPERATION = "#graphql\n query GetCurrentBulkOperation {\n currentBulkOperation {\n id\n type\n status\n query\n url\n rootObjectCount\n objectCount\n fileSize\n partialDataUrl\n errorCode\n createdAt\n completedAt\n }\n }\n";
|
|
21
21
|
/**
|
|
22
|
-
* Get
|
|
22
|
+
* Get current bulk MUTATION operation status
|
|
23
|
+
* Required for polling mutation status in versions < 2026-01
|
|
24
|
+
*/
|
|
25
|
+
export declare const GET_CURRENT_BULK_MUTATION = "#graphql\n query GetCurrentBulkMutation {\n currentBulkOperation(type: MUTATION) {\n id\n type\n status\n url\n objectCount\n fileSize\n partialDataUrl\n errorCode\n createdAt\n completedAt\n }\n }\n";
|
|
26
|
+
/**
|
|
27
|
+
* Get a specific bulk operation by ID (API version 2026-01+)
|
|
28
|
+
* Use this for polling both queries and mutations
|
|
29
|
+
*/
|
|
30
|
+
export declare const GET_BULK_OPERATION_BY_ID = "#graphql\n query GetBulkOperationById($id: ID!) {\n bulkOperation(id: $id) {\n id\n type\n status\n url\n objectCount\n fileSize\n partialDataUrl\n errorCode\n createdAt\n completedAt\n }\n }\n";
|
|
31
|
+
/**
|
|
32
|
+
* Get a specific bulk operation by ID (legacy node query)
|
|
23
33
|
*/
|
|
24
34
|
export declare const GET_BULK_OPERATION = "#graphql\n query GetBulkOperation($id: ID!) {\n node(id: $id) {\n ... on BulkOperation {\n id\n type\n status\n query\n url\n rootObjectCount\n objectCount\n fileSize\n partialDataUrl\n errorCode\n createdAt\n completedAt\n }\n }\n }\n";
|
|
25
35
|
/**
|
|
@@ -46,8 +46,8 @@ export const BULK_OPERATION_RUN_MUTATION = `#graphql
|
|
|
46
46
|
}
|
|
47
47
|
`;
|
|
48
48
|
/**
|
|
49
|
-
* Get current bulk operation status
|
|
50
|
-
*
|
|
49
|
+
* Get current bulk operation status (for queries)
|
|
50
|
+
* Deprecated in 2026-01, use GET_BULK_OPERATION_BY_ID instead
|
|
51
51
|
*/
|
|
52
52
|
export const GET_CURRENT_BULK_OPERATION = `#graphql
|
|
53
53
|
query GetCurrentBulkOperation {
|
|
@@ -68,7 +68,47 @@ export const GET_CURRENT_BULK_OPERATION = `#graphql
|
|
|
68
68
|
}
|
|
69
69
|
`;
|
|
70
70
|
/**
|
|
71
|
-
* Get
|
|
71
|
+
* Get current bulk MUTATION operation status
|
|
72
|
+
* Required for polling mutation status in versions < 2026-01
|
|
73
|
+
*/
|
|
74
|
+
export const GET_CURRENT_BULK_MUTATION = `#graphql
|
|
75
|
+
query GetCurrentBulkMutation {
|
|
76
|
+
currentBulkOperation(type: MUTATION) {
|
|
77
|
+
id
|
|
78
|
+
type
|
|
79
|
+
status
|
|
80
|
+
url
|
|
81
|
+
objectCount
|
|
82
|
+
fileSize
|
|
83
|
+
partialDataUrl
|
|
84
|
+
errorCode
|
|
85
|
+
createdAt
|
|
86
|
+
completedAt
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
/**
|
|
91
|
+
* Get a specific bulk operation by ID (API version 2026-01+)
|
|
92
|
+
* Use this for polling both queries and mutations
|
|
93
|
+
*/
|
|
94
|
+
export const GET_BULK_OPERATION_BY_ID = `#graphql
|
|
95
|
+
query GetBulkOperationById($id: ID!) {
|
|
96
|
+
bulkOperation(id: $id) {
|
|
97
|
+
id
|
|
98
|
+
type
|
|
99
|
+
status
|
|
100
|
+
url
|
|
101
|
+
objectCount
|
|
102
|
+
fileSize
|
|
103
|
+
partialDataUrl
|
|
104
|
+
errorCode
|
|
105
|
+
createdAt
|
|
106
|
+
completedAt
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
/**
|
|
111
|
+
* Get a specific bulk operation by ID (legacy node query)
|
|
72
112
|
*/
|
|
73
113
|
export const GET_BULK_OPERATION = `#graphql
|
|
74
114
|
query GetBulkOperation($id: ID!) {
|
package/dist/resources/index.js
CHANGED
|
@@ -172,6 +172,134 @@ tag:vip orders_count:>3
|
|
|
172
172
|
If a tool returns a 403 error, it likely means your custom app is missing the required scope. Update your app's API access scopes in:
|
|
173
173
|
|
|
174
174
|
**Shopify Admin → Settings → Apps and sales channels → Develop apps → [Your App] → Configuration**
|
|
175
|
+
`,
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
}));
|
|
179
|
+
// Smart Tools Reference
|
|
180
|
+
server.registerResource("smart-tools", "shopify://docs/smart-tools", {
|
|
181
|
+
title: "Smart Tools Reference",
|
|
182
|
+
description: "Reference guide for smart multi-step tools that handle complex workflows automatically.",
|
|
183
|
+
mimeType: "text/markdown",
|
|
184
|
+
}, async () => ({
|
|
185
|
+
contents: [
|
|
186
|
+
{
|
|
187
|
+
uri: "shopify://docs/smart-tools",
|
|
188
|
+
mimeType: "text/markdown",
|
|
189
|
+
text: `# Smart Tools Reference
|
|
190
|
+
|
|
191
|
+
Smart tools handle complex multi-step workflows automatically, including polling and staged uploads.
|
|
192
|
+
|
|
193
|
+
## upload_file
|
|
194
|
+
|
|
195
|
+
Upload files to Shopify with automatic status polling. Returns the final CDN URL when ready.
|
|
196
|
+
|
|
197
|
+
### Mode 1: External URL
|
|
198
|
+
Shopify fetches the file from a publicly accessible URL.
|
|
199
|
+
|
|
200
|
+
\`\`\`json
|
|
201
|
+
{
|
|
202
|
+
"url": "https://example.com/image.jpg",
|
|
203
|
+
"alt": "Product image"
|
|
204
|
+
}
|
|
205
|
+
\`\`\`
|
|
206
|
+
|
|
207
|
+
### Mode 2: Local File Path (Recommended for large files)
|
|
208
|
+
Read file directly from disk. MIME type is auto-detected.
|
|
209
|
+
|
|
210
|
+
\`\`\`json
|
|
211
|
+
{
|
|
212
|
+
"filePath": "/path/to/document.pdf",
|
|
213
|
+
"alt": "Product manual"
|
|
214
|
+
}
|
|
215
|
+
\`\`\`
|
|
216
|
+
|
|
217
|
+
### Mode 3: Base64 Content (Small files only, < 5MB)
|
|
218
|
+
For small files when you already have the content encoded.
|
|
219
|
+
|
|
220
|
+
\`\`\`json
|
|
221
|
+
{
|
|
222
|
+
"content": "iVBORw0KGgoAAAANSUhEUgAA...",
|
|
223
|
+
"filename": "photo.jpg",
|
|
224
|
+
"mimeType": "image/jpeg"
|
|
225
|
+
}
|
|
226
|
+
\`\`\`
|
|
227
|
+
|
|
228
|
+
**Required for Mode 3:** \`content\`, \`filename\`, \`mimeType\`
|
|
229
|
+
|
|
230
|
+
### Content Types
|
|
231
|
+
- \`IMAGE\` - jpg, png, gif, webp, svg
|
|
232
|
+
- \`VIDEO\` - mp4, mov, webm
|
|
233
|
+
- \`FILE\` - pdf, documents, other files
|
|
234
|
+
|
|
235
|
+
## bulk_export
|
|
236
|
+
|
|
237
|
+
Export large datasets to JSONL format.
|
|
238
|
+
|
|
239
|
+
\`\`\`json
|
|
240
|
+
{
|
|
241
|
+
"query": "{ products { edges { node { id title } } } }"
|
|
242
|
+
}
|
|
243
|
+
\`\`\`
|
|
244
|
+
|
|
245
|
+
Returns a download URL for the JSONL file when complete.
|
|
246
|
+
|
|
247
|
+
## bulk_import
|
|
248
|
+
|
|
249
|
+
Import data via bulk mutations.
|
|
250
|
+
|
|
251
|
+
\`\`\`json
|
|
252
|
+
{
|
|
253
|
+
"mutation": "mutation($input: ProductInput!) { productUpdate(input: $input) { product { id } } }",
|
|
254
|
+
"jsonlUrl": "https://example.com/data.jsonl"
|
|
255
|
+
}
|
|
256
|
+
\`\`\`
|
|
257
|
+
|
|
258
|
+
## upsert_metaobject
|
|
259
|
+
|
|
260
|
+
Create or update a metaobject by handle (idempotent).
|
|
261
|
+
|
|
262
|
+
\`\`\`json
|
|
263
|
+
{
|
|
264
|
+
"type": "color_swatch",
|
|
265
|
+
"handle": "navy-blue",
|
|
266
|
+
"fields": [
|
|
267
|
+
{ "key": "name", "value": "Navy Blue" },
|
|
268
|
+
{ "key": "hex", "value": "#000080" }
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
\`\`\`
|
|
272
|
+
|
|
273
|
+
## delete_metaobject
|
|
274
|
+
|
|
275
|
+
Delete a metaobject by ID or by type+handle.
|
|
276
|
+
|
|
277
|
+
\`\`\`json
|
|
278
|
+
{
|
|
279
|
+
"id": "gid://shopify/Metaobject/123456789"
|
|
280
|
+
}
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
Or by type and handle:
|
|
284
|
+
|
|
285
|
+
\`\`\`json
|
|
286
|
+
{
|
|
287
|
+
"type": "color_swatch",
|
|
288
|
+
"handle": "navy-blue"
|
|
289
|
+
}
|
|
290
|
+
\`\`\`
|
|
291
|
+
|
|
292
|
+
## schema_discover
|
|
293
|
+
|
|
294
|
+
Discover custom schema definitions in the store.
|
|
295
|
+
|
|
296
|
+
\`\`\`json
|
|
297
|
+
{
|
|
298
|
+
"includeMetafields": true,
|
|
299
|
+
"includeMetaobjects": true,
|
|
300
|
+
"metafieldOwnerTypes": ["PRODUCT", "VARIANT"]
|
|
301
|
+
}
|
|
302
|
+
\`\`\`
|
|
175
303
|
`,
|
|
176
304
|
},
|
|
177
305
|
],
|
package/dist/tools/graphql.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { AdminApiClient } from "../shopify-client.js";
|
|
3
|
-
export declare function registerGraphQLTools(server: McpServer, client: AdminApiClient): void;
|
|
3
|
+
export declare function registerGraphQLTools(server: McpServer, client: AdminApiClient, storeDomain: string): void;
|
package/dist/tools/graphql.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { formatSuccessResponse, formatGraphQLErrors, formatErrorResponse, } from "../errors.js";
|
|
3
|
-
|
|
3
|
+
import { enqueue } from "../queue.js";
|
|
4
|
+
import { logOperation } from "../logger.js";
|
|
5
|
+
export function registerGraphQLTools(server, client, storeDomain) {
|
|
4
6
|
server.registerTool("run_graphql_query", {
|
|
5
7
|
title: "Run GraphQL Query",
|
|
6
8
|
description: "Execute any GraphQL query or mutation against the Shopify Admin API. " +
|
|
@@ -24,16 +26,45 @@ export function registerGraphQLTools(server, client) {
|
|
|
24
26
|
openWorldHint: true,
|
|
25
27
|
},
|
|
26
28
|
}, async ({ query, variables }) => {
|
|
29
|
+
const startTime = Date.now();
|
|
27
30
|
try {
|
|
28
|
-
const response = await client.request(query, {
|
|
31
|
+
const response = await enqueue(() => client.request(query, {
|
|
29
32
|
variables: variables,
|
|
30
|
-
});
|
|
33
|
+
}));
|
|
31
34
|
if (response.errors) {
|
|
35
|
+
await logOperation({
|
|
36
|
+
storeDomain,
|
|
37
|
+
toolName: "run_graphql_query",
|
|
38
|
+
query,
|
|
39
|
+
variables,
|
|
40
|
+
response,
|
|
41
|
+
success: false,
|
|
42
|
+
errorMessage: "GraphQL errors",
|
|
43
|
+
durationMs: Date.now() - startTime,
|
|
44
|
+
});
|
|
32
45
|
return formatGraphQLErrors(response);
|
|
33
46
|
}
|
|
47
|
+
await logOperation({
|
|
48
|
+
storeDomain,
|
|
49
|
+
toolName: "run_graphql_query",
|
|
50
|
+
query,
|
|
51
|
+
variables,
|
|
52
|
+
response: response.data,
|
|
53
|
+
success: true,
|
|
54
|
+
durationMs: Date.now() - startTime,
|
|
55
|
+
});
|
|
34
56
|
return formatSuccessResponse(response.data);
|
|
35
57
|
}
|
|
36
58
|
catch (error) {
|
|
59
|
+
await logOperation({
|
|
60
|
+
storeDomain,
|
|
61
|
+
toolName: "run_graphql_query",
|
|
62
|
+
query,
|
|
63
|
+
variables,
|
|
64
|
+
success: false,
|
|
65
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
66
|
+
durationMs: Date.now() - startTime,
|
|
67
|
+
});
|
|
37
68
|
return formatErrorResponse(error);
|
|
38
69
|
}
|
|
39
70
|
});
|