@shoppexio/mcp-commerce-server 0.2.0 → 0.4.0
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 +1 -101
- package/package.json +1 -1
- package/src/server.mjs +39 -18
package/README.md
CHANGED
|
@@ -1,103 +1,3 @@
|
|
|
1
1
|
# @shoppexio/mcp-commerce-server
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Connect Claude Desktop, Claude Code, Cursor, Windsurf, or Codex to your Shoppex store. Read products, orders, customers, and analytics, create payment links, manage coupons, and create or update products — directly from chat.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install -g @shoppexio/mcp-commerce-server
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Or run without installing:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npx -y @shoppexio/mcp-commerce-server
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Claude Desktop
|
|
20
|
-
|
|
21
|
-
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
22
|
-
|
|
23
|
-
```json
|
|
24
|
-
{
|
|
25
|
-
"mcpServers": {
|
|
26
|
-
"shoppex-commerce": {
|
|
27
|
-
"command": "npx",
|
|
28
|
-
"args": ["-y", "@shoppexio/mcp-commerce-server"],
|
|
29
|
-
"env": {
|
|
30
|
-
"SHOPPEX_SHOP_API_KEY": "shx_your_dev_api_key"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Restart Claude Desktop. Tools accept a `shop_api_key` argument on each call; the env var is available for clients that forward env to tool arguments.
|
|
38
|
-
|
|
39
|
-
## Cursor / Windsurf / Other
|
|
40
|
-
|
|
41
|
-
Any MCP client with stdio transport works. Set the same env var and point to `shoppex-mcp-commerce-server` as the command.
|
|
42
|
-
|
|
43
|
-
## Tools (12)
|
|
44
|
-
|
|
45
|
-
### Read
|
|
46
|
-
|
|
47
|
-
| Tool | Purpose |
|
|
48
|
-
|------|---------|
|
|
49
|
-
| `products.list` | Search or list products |
|
|
50
|
-
| `products.get` | Fetch one product by id or uniqid |
|
|
51
|
-
| `orders.list` | List recent orders, optionally filtered |
|
|
52
|
-
| `orders.get` | Fetch one order with line items |
|
|
53
|
-
| `customers.get` | Fetch a customer by id or email |
|
|
54
|
-
| `coupons.list` | List active coupons |
|
|
55
|
-
| `analytics.revenue` | Revenue totals for a date range |
|
|
56
|
-
|
|
57
|
-
### Write
|
|
58
|
-
|
|
59
|
-
| Tool | Purpose |
|
|
60
|
-
|------|---------|
|
|
61
|
-
| `products.create` | Create a product (service, serials, dynamic, file) |
|
|
62
|
-
| `products.update` | Update a product's price, title, gateways, stock, visibility |
|
|
63
|
-
| `coupons.create` | Create a coupon (percentage or fixed discount) |
|
|
64
|
-
| `coupons.update` | Update an existing coupon |
|
|
65
|
-
| `payment_links.create` | Create a payment link |
|
|
66
|
-
|
|
67
|
-
## Required Scopes
|
|
68
|
-
|
|
69
|
-
Your Shoppex Dev API key needs the scopes matching the tools you use (e.g. `products.read`, `products.write`, `orders.read`, `coupons.write`, `analytics.read`, `payment_links.write`).
|
|
70
|
-
|
|
71
|
-
Create one at [dashboard.shoppex.io/developer/api](https://dashboard.shoppex.io/developer/api).
|
|
72
|
-
|
|
73
|
-
## Environment Variables
|
|
74
|
-
|
|
75
|
-
| Variable | Required | Default |
|
|
76
|
-
|----------|----------|---------|
|
|
77
|
-
| `SHOPPEX_SHOP_API_KEY` | passed per call, or set here | — |
|
|
78
|
-
| `SHOPPEX_API_BASE_URL` | no | `https://api.shoppex.io` |
|
|
79
|
-
| `SHOPPEX_DEV_API_TIMEOUT_MS` | no | `10000` |
|
|
80
|
-
|
|
81
|
-
## Example Prompts
|
|
82
|
-
|
|
83
|
-
Once connected in Claude Desktop:
|
|
84
|
-
|
|
85
|
-
- "Create a Discord Nitro 3-month product for $14.99 paid in crypto."
|
|
86
|
-
- "Show me this month's top 10 customers by revenue."
|
|
87
|
-
- "Generate a 20% off coupon for my Discord members, valid until end of month."
|
|
88
|
-
- "Update the price of product `prd_abc123` to $12.99."
|
|
89
|
-
- "Make a payment link for a $50 USDT one-time purchase."
|
|
90
|
-
|
|
91
|
-
## Companion
|
|
92
|
-
|
|
93
|
-
Pair with [`@shoppexio/mcp-theme-server`](https://www.npmjs.com/package/@shoppexio/mcp-theme-server) for storefront theme operations.
|
|
94
|
-
|
|
95
|
-
## Docs
|
|
96
|
-
|
|
97
|
-
- [Developer API Reference](https://docs.shoppex.io/api-reference/introduction)
|
|
98
|
-
- [Quickstart](https://docs.shoppex.io/api-reference/quickstart)
|
|
99
|
-
- [Authentication](https://docs.shoppex.io/api-reference/authentication)
|
|
100
|
-
|
|
101
|
-
## License
|
|
102
|
-
|
|
103
|
-
Proprietary. © Shoppex.
|
|
3
|
+
Shoppex MCP server that exposes commerce tools over the Shoppex Dev API.
|
package/package.json
CHANGED
package/src/server.mjs
CHANGED
|
@@ -257,13 +257,29 @@ export class ShoppexCommerceDevApiClient {
|
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
const BaseToolSchema = {
|
|
260
|
-
shop_api_key: z.string().trim().min(1),
|
|
260
|
+
shop_api_key: z.string().trim().min(1).optional(),
|
|
261
261
|
api_base_url: z.string().trim().url().optional(),
|
|
262
262
|
};
|
|
263
263
|
|
|
264
|
+
function resolveShopApiKey(explicitValue) {
|
|
265
|
+
if (typeof explicitValue === 'string' && explicitValue.trim()) {
|
|
266
|
+
return explicitValue.trim();
|
|
267
|
+
}
|
|
268
|
+
const fromEnv = process.env.SHOPPEX_SHOP_API_KEY?.trim()
|
|
269
|
+
|| process.env.SHOPPEX_API_KEY?.trim()
|
|
270
|
+
|| process.env.SHOP_API_KEY?.trim();
|
|
271
|
+
if (!fromEnv) {
|
|
272
|
+
throw new ShoppexCommerceDevApiError(
|
|
273
|
+
'Missing Shoppex shop API key. Set SHOPPEX_SHOP_API_KEY in the MCP server env, or pass shop_api_key to the tool.',
|
|
274
|
+
{ code: 'auth_error', retryable: false },
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
return fromEnv;
|
|
278
|
+
}
|
|
279
|
+
|
|
264
280
|
function createClient(args) {
|
|
265
281
|
return new ShoppexCommerceDevApiClient({
|
|
266
|
-
shopApiKey: args.shop_api_key,
|
|
282
|
+
shopApiKey: resolveShopApiKey(args.shop_api_key),
|
|
267
283
|
apiBaseUrl: args.api_base_url,
|
|
268
284
|
});
|
|
269
285
|
}
|
|
@@ -271,7 +287,7 @@ function createClient(args) {
|
|
|
271
287
|
export function createCommerceToolCatalog() {
|
|
272
288
|
return [
|
|
273
289
|
{
|
|
274
|
-
name: '
|
|
290
|
+
name: 'products_list',
|
|
275
291
|
description: 'Search or list products for one Shoppex shop.',
|
|
276
292
|
inputSchema: {
|
|
277
293
|
...BaseToolSchema,
|
|
@@ -286,7 +302,7 @@ export function createCommerceToolCatalog() {
|
|
|
286
302
|
}),
|
|
287
303
|
},
|
|
288
304
|
{
|
|
289
|
-
name: '
|
|
305
|
+
name: 'products_get',
|
|
290
306
|
description: 'Fetch one product by Shoppex product id or uniqid.',
|
|
291
307
|
inputSchema: {
|
|
292
308
|
...BaseToolSchema,
|
|
@@ -295,7 +311,7 @@ export function createCommerceToolCatalog() {
|
|
|
295
311
|
execute: async (args) => createClient(args).productsGet(args.product_id),
|
|
296
312
|
},
|
|
297
313
|
{
|
|
298
|
-
name: '
|
|
314
|
+
name: 'orders_list',
|
|
299
315
|
description: 'List recent orders. Optionally filter by status or customer email.',
|
|
300
316
|
inputSchema: {
|
|
301
317
|
...BaseToolSchema,
|
|
@@ -310,7 +326,7 @@ export function createCommerceToolCatalog() {
|
|
|
310
326
|
}),
|
|
311
327
|
},
|
|
312
328
|
{
|
|
313
|
-
name: '
|
|
329
|
+
name: 'orders_get',
|
|
314
330
|
description: 'Fetch one order with line items by id or uniqid.',
|
|
315
331
|
inputSchema: {
|
|
316
332
|
...BaseToolSchema,
|
|
@@ -319,7 +335,7 @@ export function createCommerceToolCatalog() {
|
|
|
319
335
|
execute: async (args) => createClient(args).ordersGet(args.order_id),
|
|
320
336
|
},
|
|
321
337
|
{
|
|
322
|
-
name: '
|
|
338
|
+
name: 'customers_get',
|
|
323
339
|
description: 'Fetch one customer by Shoppex customer id or email.',
|
|
324
340
|
inputSchema: {
|
|
325
341
|
...BaseToolSchema,
|
|
@@ -332,7 +348,7 @@ export function createCommerceToolCatalog() {
|
|
|
332
348
|
}),
|
|
333
349
|
},
|
|
334
350
|
{
|
|
335
|
-
name: '
|
|
351
|
+
name: 'payment_links_create',
|
|
336
352
|
description: 'Create a Shoppex payment link.',
|
|
337
353
|
inputSchema: {
|
|
338
354
|
...BaseToolSchema,
|
|
@@ -369,7 +385,7 @@ export function createCommerceToolCatalog() {
|
|
|
369
385
|
}),
|
|
370
386
|
},
|
|
371
387
|
{
|
|
372
|
-
name: '
|
|
388
|
+
name: 'analytics_revenue',
|
|
373
389
|
description: 'Fetch revenue totals for a date range.',
|
|
374
390
|
inputSchema: {
|
|
375
391
|
...BaseToolSchema,
|
|
@@ -384,7 +400,7 @@ export function createCommerceToolCatalog() {
|
|
|
384
400
|
}),
|
|
385
401
|
},
|
|
386
402
|
{
|
|
387
|
-
name: '
|
|
403
|
+
name: 'coupons_list',
|
|
388
404
|
description: 'List active coupons for a shop.',
|
|
389
405
|
inputSchema: {
|
|
390
406
|
...BaseToolSchema,
|
|
@@ -395,7 +411,7 @@ export function createCommerceToolCatalog() {
|
|
|
395
411
|
}),
|
|
396
412
|
},
|
|
397
413
|
{
|
|
398
|
-
name: '
|
|
414
|
+
name: 'coupons_create',
|
|
399
415
|
description: 'Create a coupon in Shoppex.',
|
|
400
416
|
inputSchema: {
|
|
401
417
|
...BaseToolSchema,
|
|
@@ -422,8 +438,8 @@ export function createCommerceToolCatalog() {
|
|
|
422
438
|
}),
|
|
423
439
|
},
|
|
424
440
|
{
|
|
425
|
-
name: '
|
|
426
|
-
description: 'Update an existing coupon by uniqid. Only provided fields
|
|
441
|
+
name: 'coupons_update',
|
|
442
|
+
description: 'Update an existing coupon by uniqid. Only provided fields change.',
|
|
427
443
|
inputSchema: {
|
|
428
444
|
...BaseToolSchema,
|
|
429
445
|
coupon_id: z.string().trim().min(1),
|
|
@@ -450,8 +466,8 @@ export function createCommerceToolCatalog() {
|
|
|
450
466
|
},
|
|
451
467
|
},
|
|
452
468
|
{
|
|
453
|
-
name: '
|
|
454
|
-
description: 'Create a product. Defaults to a simple digital/service product. For key-based products pass type="SERIALS" and
|
|
469
|
+
name: 'products_create',
|
|
470
|
+
description: 'Create a product. Defaults to a simple digital/service product. For key-based products pass type="SERIALS" and a serials array.',
|
|
455
471
|
inputSchema: {
|
|
456
472
|
...BaseToolSchema,
|
|
457
473
|
title: z.string().trim().min(1).max(128),
|
|
@@ -488,8 +504,8 @@ export function createCommerceToolCatalog() {
|
|
|
488
504
|
},
|
|
489
505
|
},
|
|
490
506
|
{
|
|
491
|
-
name: '
|
|
492
|
-
description: 'Update an existing product by uniqid. Only provided fields
|
|
507
|
+
name: 'products_update',
|
|
508
|
+
description: 'Update an existing product by uniqid. Only provided fields change.',
|
|
493
509
|
inputSchema: {
|
|
494
510
|
...BaseToolSchema,
|
|
495
511
|
product_id: z.string().trim().min(1),
|
|
@@ -522,8 +538,13 @@ export function createCommerceToolCatalog() {
|
|
|
522
538
|
];
|
|
523
539
|
}
|
|
524
540
|
|
|
541
|
+
function normalizeToolName(name) {
|
|
542
|
+
return typeof name === 'string' ? name.replace(/\./g, '_') : name;
|
|
543
|
+
}
|
|
544
|
+
|
|
525
545
|
export async function executeCommerceTool(toolName, args) {
|
|
526
|
-
const
|
|
546
|
+
const normalized = normalizeToolName(toolName);
|
|
547
|
+
const tool = createCommerceToolCatalog().find((entry) => entry.name === normalized);
|
|
527
548
|
if (!tool) {
|
|
528
549
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
529
550
|
}
|