shopify-store-mcp 1.0.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.
Files changed (88) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +172 -0
  3. package/dist/config.d.ts +10 -0
  4. package/dist/config.js +65 -0
  5. package/dist/db.d.ts +19 -0
  6. package/dist/db.js +161 -0
  7. package/dist/errors.d.ts +36 -0
  8. package/dist/errors.js +93 -0
  9. package/dist/graphql/admin/common/collections.d.ts +8 -0
  10. package/dist/graphql/admin/common/collections.js +44 -0
  11. package/dist/graphql/admin/common/customers.d.ts +13 -0
  12. package/dist/graphql/admin/common/customers.js +112 -0
  13. package/dist/graphql/admin/common/orders.d.ts +13 -0
  14. package/dist/graphql/admin/common/orders.js +142 -0
  15. package/dist/graphql/admin/common/products.d.ts +23 -0
  16. package/dist/graphql/admin/common/products.js +159 -0
  17. package/dist/graphql/admin/common/shop.d.ts +7 -0
  18. package/dist/graphql/admin/common/shop.js +38 -0
  19. package/dist/graphql/admin/index.d.ts +15 -0
  20. package/dist/graphql/admin/index.js +18 -0
  21. package/dist/graphql/admin/specialized/bulk.d.ts +33 -0
  22. package/dist/graphql/admin/specialized/bulk.js +132 -0
  23. package/dist/graphql/admin/specialized/files.d.ts +22 -0
  24. package/dist/graphql/admin/specialized/files.js +170 -0
  25. package/dist/graphql/admin/specialized/inventory.d.ts +13 -0
  26. package/dist/graphql/admin/specialized/inventory.js +78 -0
  27. package/dist/graphql/admin/specialized/metafields.d.ts +22 -0
  28. package/dist/graphql/admin/specialized/metafields.js +100 -0
  29. package/dist/graphql/admin/specialized/metaobjects.d.ts +36 -0
  30. package/dist/graphql/admin/specialized/metaobjects.js +239 -0
  31. package/dist/graphql/admin/specialized/search.d.ts +21 -0
  32. package/dist/graphql/admin/specialized/search.js +100 -0
  33. package/dist/graphql/collections.d.ts +1 -0
  34. package/dist/graphql/collections.js +37 -0
  35. package/dist/graphql/customers.d.ts +2 -0
  36. package/dist/graphql/customers.js +98 -0
  37. package/dist/graphql/inventory.d.ts +2 -0
  38. package/dist/graphql/inventory.js +67 -0
  39. package/dist/graphql/metafields.d.ts +2 -0
  40. package/dist/graphql/metafields.js +43 -0
  41. package/dist/graphql/orders.d.ts +2 -0
  42. package/dist/graphql/orders.js +116 -0
  43. package/dist/graphql/products.d.ts +4 -0
  44. package/dist/graphql/products.js +140 -0
  45. package/dist/graphql/shop.d.ts +1 -0
  46. package/dist/graphql/shop.js +32 -0
  47. package/dist/graphql/storefront/common/cart.d.ts +23 -0
  48. package/dist/graphql/storefront/common/cart.js +210 -0
  49. package/dist/graphql/storefront/common/collections.d.ts +11 -0
  50. package/dist/graphql/storefront/common/collections.js +114 -0
  51. package/dist/graphql/storefront/common/products.d.ts +14 -0
  52. package/dist/graphql/storefront/common/products.js +155 -0
  53. package/dist/graphql/storefront/index.d.ts +7 -0
  54. package/dist/graphql/storefront/index.js +8 -0
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.js +97 -0
  57. package/dist/logger.d.ts +58 -0
  58. package/dist/logger.js +165 -0
  59. package/dist/prompts/index.d.ts +2 -0
  60. package/dist/prompts/index.js +169 -0
  61. package/dist/queue.d.ts +73 -0
  62. package/dist/queue.js +120 -0
  63. package/dist/resources/index.d.ts +3 -0
  64. package/dist/resources/index.js +180 -0
  65. package/dist/shopify-client.d.ts +16 -0
  66. package/dist/shopify-client.js +39 -0
  67. package/dist/tools/graphql.d.ts +3 -0
  68. package/dist/tools/graphql.js +41 -0
  69. package/dist/tools/index.d.ts +3 -0
  70. package/dist/tools/index.js +23 -0
  71. package/dist/tools/infrastructure.d.ts +6 -0
  72. package/dist/tools/infrastructure.js +215 -0
  73. package/dist/tools/shop.d.ts +3 -0
  74. package/dist/tools/shop.js +28 -0
  75. package/dist/tools/smart-bulk.d.ts +7 -0
  76. package/dist/tools/smart-bulk.js +286 -0
  77. package/dist/tools/smart-files.d.ts +7 -0
  78. package/dist/tools/smart-files.js +169 -0
  79. package/dist/tools/smart-metaobjects.d.ts +7 -0
  80. package/dist/tools/smart-metaobjects.js +186 -0
  81. package/dist/tools/smart-schema.d.ts +7 -0
  82. package/dist/tools/smart-schema.js +138 -0
  83. package/dist/types.d.ts +19 -0
  84. package/dist/types.js +2 -0
  85. package/dist/utils/polling.d.ts +53 -0
  86. package/dist/utils/polling.js +77 -0
  87. package/package.json +83 -0
  88. package/prisma/schema.prisma +82 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Operation logger for tracking all GraphQL calls
3
+ * Logs to SQLite database for debugging and history
4
+ */
5
+ /**
6
+ * Get the current session ID
7
+ */
8
+ export declare function getSessionId(): string;
9
+ /**
10
+ * Log a GraphQL operation
11
+ */
12
+ export declare function logOperation(params: {
13
+ storeDomain: string;
14
+ toolName: string;
15
+ query: string;
16
+ variables?: Record<string, unknown>;
17
+ response?: unknown;
18
+ success: boolean;
19
+ errorMessage?: string;
20
+ durationMs: number;
21
+ }): Promise<void>;
22
+ /**
23
+ * Query operation history
24
+ */
25
+ export declare function getOperationHistory(params: {
26
+ storeDomain: string;
27
+ toolName?: string;
28
+ operationType?: "query" | "mutation";
29
+ success?: boolean;
30
+ since?: Date;
31
+ limit?: number;
32
+ }): Promise<Array<{
33
+ id: string;
34
+ toolName: string;
35
+ operationType: string;
36
+ query: string;
37
+ success: boolean;
38
+ errorMessage: string | null;
39
+ durationMs: number;
40
+ createdAt: Date;
41
+ }>>;
42
+ /**
43
+ * Get aggregated statistics
44
+ */
45
+ export declare function getOperationStats(params: {
46
+ storeDomain: string;
47
+ since: Date;
48
+ }): Promise<{
49
+ totalCalls: number;
50
+ successCount: number;
51
+ errorCount: number;
52
+ avgDurationMs: number;
53
+ byTool: Record<string, {
54
+ calls: number;
55
+ successRate: number;
56
+ avgDuration: number;
57
+ }>;
58
+ }>;
package/dist/logger.js ADDED
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Operation logger for tracking all GraphQL calls
3
+ * Logs to SQLite database for debugging and history
4
+ */
5
+ import prisma from "./db.js";
6
+ import { randomUUID } from "crypto";
7
+ // Session ID for this MCP process instance
8
+ const sessionId = randomUUID();
9
+ // Check if logging is enabled (default: true)
10
+ const isLoggingEnabled = process.env.MCP_LOG_OPERATIONS !== "false";
11
+ // Max length for query/response strings in DB
12
+ const MAX_QUERY_LENGTH = 10000;
13
+ const MAX_RESPONSE_LENGTH = 50000;
14
+ /**
15
+ * Get the current session ID
16
+ */
17
+ export function getSessionId() {
18
+ return sessionId;
19
+ }
20
+ /**
21
+ * Truncate a string to a maximum length
22
+ */
23
+ function truncate(str, maxLength) {
24
+ if (str.length <= maxLength) {
25
+ return str;
26
+ }
27
+ return str.slice(0, maxLength) + "... [truncated]";
28
+ }
29
+ /**
30
+ * Detect if a GraphQL operation is a query or mutation
31
+ */
32
+ function detectOperationType(query) {
33
+ const trimmed = query.trim().toLowerCase();
34
+ if (trimmed.startsWith("mutation")) {
35
+ return "mutation";
36
+ }
37
+ return "query";
38
+ }
39
+ /**
40
+ * Log a GraphQL operation
41
+ */
42
+ export async function logOperation(params) {
43
+ if (!isLoggingEnabled) {
44
+ return;
45
+ }
46
+ try {
47
+ await prisma.operationLog.create({
48
+ data: {
49
+ storeDomain: params.storeDomain,
50
+ sessionId,
51
+ toolName: params.toolName,
52
+ operationType: detectOperationType(params.query),
53
+ query: truncate(params.query, MAX_QUERY_LENGTH),
54
+ variables: params.variables
55
+ ? truncate(JSON.stringify(params.variables), MAX_QUERY_LENGTH)
56
+ : null,
57
+ response: params.response
58
+ ? truncate(JSON.stringify(params.response), MAX_RESPONSE_LENGTH)
59
+ : null,
60
+ success: params.success,
61
+ errorMessage: params.errorMessage || null,
62
+ durationMs: params.durationMs,
63
+ },
64
+ });
65
+ }
66
+ catch (error) {
67
+ // Don't fail the operation if logging fails
68
+ console.error("[shopify-store-mcp] Failed to log operation:", error);
69
+ }
70
+ }
71
+ /**
72
+ * Query operation history
73
+ */
74
+ export async function getOperationHistory(params) {
75
+ const where = {
76
+ storeDomain: params.storeDomain,
77
+ };
78
+ if (params.toolName) {
79
+ where.toolName = params.toolName;
80
+ }
81
+ if (params.operationType) {
82
+ where.operationType = params.operationType;
83
+ }
84
+ if (params.success !== undefined) {
85
+ where.success = params.success;
86
+ }
87
+ if (params.since) {
88
+ where.createdAt = { gte: params.since };
89
+ }
90
+ return prisma.operationLog.findMany({
91
+ where,
92
+ orderBy: { createdAt: "desc" },
93
+ take: params.limit || 50,
94
+ select: {
95
+ id: true,
96
+ toolName: true,
97
+ operationType: true,
98
+ query: true,
99
+ success: true,
100
+ errorMessage: true,
101
+ durationMs: true,
102
+ createdAt: true,
103
+ },
104
+ });
105
+ }
106
+ /**
107
+ * Get aggregated statistics
108
+ */
109
+ export async function getOperationStats(params) {
110
+ // Get all operations in the period
111
+ const operations = await prisma.operationLog.findMany({
112
+ where: {
113
+ storeDomain: params.storeDomain,
114
+ createdAt: { gte: params.since },
115
+ },
116
+ select: {
117
+ toolName: true,
118
+ success: true,
119
+ durationMs: true,
120
+ },
121
+ });
122
+ if (operations.length === 0) {
123
+ return {
124
+ totalCalls: 0,
125
+ successCount: 0,
126
+ errorCount: 0,
127
+ avgDurationMs: 0,
128
+ byTool: {},
129
+ };
130
+ }
131
+ const totalCalls = operations.length;
132
+ const successCount = operations.filter((op) => op.success).length;
133
+ const errorCount = totalCalls - successCount;
134
+ const avgDurationMs = operations.reduce((sum, op) => sum + op.durationMs, 0) / totalCalls;
135
+ // Group by tool
136
+ const byTool = {};
137
+ const toolGroups = new Map();
138
+ for (const op of operations) {
139
+ const group = toolGroups.get(op.toolName) || {
140
+ total: 0,
141
+ success: 0,
142
+ duration: 0,
143
+ };
144
+ group.total++;
145
+ if (op.success)
146
+ group.success++;
147
+ group.duration += op.durationMs;
148
+ toolGroups.set(op.toolName, group);
149
+ }
150
+ for (const [toolName, group] of toolGroups) {
151
+ byTool[toolName] = {
152
+ calls: group.total,
153
+ successRate: group.success / group.total,
154
+ avgDuration: group.duration / group.total,
155
+ };
156
+ }
157
+ return {
158
+ totalCalls,
159
+ successCount,
160
+ errorCount,
161
+ avgDurationMs,
162
+ byTool,
163
+ };
164
+ }
165
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerAllPrompts(server: McpServer): void;
@@ -0,0 +1,169 @@
1
+ import { z } from "zod";
2
+ export function registerAllPrompts(server) {
3
+ // Product Analysis Prompt
4
+ server.registerPrompt("analyze-product", {
5
+ title: "Analyze Product",
6
+ description: "Generate a detailed analysis of a product including its variants, pricing, inventory status, and recommendations for optimization.",
7
+ argsSchema: {
8
+ productId: z
9
+ .string()
10
+ .describe("The product ID (GID or numeric) to analyze"),
11
+ },
12
+ }, async ({ productId }) => ({
13
+ messages: [
14
+ {
15
+ role: "user",
16
+ content: {
17
+ type: "text",
18
+ text: `Please analyze the product with ID "${productId}". Use the get_product tool to fetch its details, then provide:
19
+
20
+ 1. **Product Overview**: Title, vendor, type, and current status
21
+ 2. **Pricing Analysis**: Current prices across variants, compare-at prices if set
22
+ 3. **Inventory Status**: Stock levels, which variants are low or out of stock
23
+ 4. **SEO Review**: Handle, title length, description quality
24
+ 5. **Recommendations**: Actionable suggestions to improve the product listing
25
+
26
+ Start by fetching the product data.`,
27
+ },
28
+ },
29
+ ],
30
+ }));
31
+ // Order Summary Prompt
32
+ server.registerPrompt("summarize-orders", {
33
+ title: "Summarize Recent Orders",
34
+ description: "Generate a summary of recent orders including revenue, fulfillment status, and trends.",
35
+ argsSchema: {
36
+ timeframe: z
37
+ .enum(["today", "week", "month"])
38
+ .default("week")
39
+ .describe("The timeframe to analyze"),
40
+ limit: z
41
+ .number()
42
+ .default(50)
43
+ .describe("Number of orders to fetch"),
44
+ },
45
+ }, async ({ timeframe, limit }) => {
46
+ const dateFilter = timeframe === "today"
47
+ ? "created_at:>=today"
48
+ : timeframe === "week"
49
+ ? "created_at:>=7_days_ago"
50
+ : "created_at:>=30_days_ago";
51
+ return {
52
+ messages: [
53
+ {
54
+ role: "user",
55
+ content: {
56
+ type: "text",
57
+ text: `Please provide a summary of orders from the ${timeframe}. Use the get_orders tool with query "${dateFilter}" and first=${limit}.
58
+
59
+ Include in your analysis:
60
+ 1. **Total Orders**: Count and total revenue
61
+ 2. **Fulfillment Status**: Breakdown by unfulfilled, partially fulfilled, fulfilled
62
+ 3. **Payment Status**: Breakdown by paid, pending, refunded
63
+ 4. **Top Products**: Most ordered items
64
+ 5. **Average Order Value**: Calculate and compare to typical benchmarks
65
+
66
+ Start by fetching the order data.`,
67
+ },
68
+ },
69
+ ],
70
+ };
71
+ });
72
+ // Inventory Health Check Prompt
73
+ server.registerPrompt("inventory-health", {
74
+ title: "Inventory Health Check",
75
+ description: "Analyze inventory levels across products and identify items that need attention (low stock, overstock, etc.).",
76
+ argsSchema: {
77
+ threshold: z
78
+ .number()
79
+ .default(10)
80
+ .describe("Low stock threshold to flag items"),
81
+ },
82
+ }, async ({ threshold }) => ({
83
+ messages: [
84
+ {
85
+ role: "user",
86
+ content: {
87
+ type: "text",
88
+ text: `Please perform an inventory health check. Use the get_inventory tool to fetch inventory levels.
89
+
90
+ Analyze and report:
91
+ 1. **Low Stock Items**: Products with inventory below ${threshold} units
92
+ 2. **Out of Stock**: Items with zero inventory
93
+ 3. **Overstock Candidates**: Items with unusually high inventory (if detectable)
94
+ 4. **Inventory Distribution**: Summary by location if multiple locations exist
95
+ 5. **Action Items**: Prioritized list of items needing restocking
96
+
97
+ Start by fetching inventory data.`,
98
+ },
99
+ },
100
+ ],
101
+ }));
102
+ // Customer Insights Prompt
103
+ server.registerPrompt("customer-insights", {
104
+ title: "Customer Insights",
105
+ description: "Analyze customer data to identify patterns, VIP customers, and engagement opportunities.",
106
+ argsSchema: {
107
+ segment: z
108
+ .enum(["all", "repeat", "high-value", "recent"])
109
+ .default("all")
110
+ .describe("Customer segment to analyze"),
111
+ },
112
+ }, async ({ segment }) => {
113
+ const queryMap = {
114
+ all: "",
115
+ repeat: "orders_count:>1",
116
+ "high-value": "total_spent:>500",
117
+ recent: "updated_at:>=30_days_ago",
118
+ };
119
+ return {
120
+ messages: [
121
+ {
122
+ role: "user",
123
+ content: {
124
+ type: "text",
125
+ text: `Please analyze the "${segment}" customer segment. Use the get_customers tool${queryMap[segment] ? ` with query "${queryMap[segment]}"` : ""}.
126
+
127
+ Provide insights on:
128
+ 1. **Customer Count**: Total customers in this segment
129
+ 2. **Engagement Metrics**: Average orders, total spent
130
+ 3. **Geographic Distribution**: Where customers are located
131
+ 4. **VIP Identification**: Top customers by order count or spend
132
+ 5. **Opportunities**: Suggestions for engagement or retention
133
+
134
+ Start by fetching customer data.`,
135
+ },
136
+ },
137
+ ],
138
+ };
139
+ });
140
+ // Custom GraphQL Query Prompt
141
+ server.registerPrompt("custom-query", {
142
+ title: "Custom GraphQL Query",
143
+ description: "Help construct and execute a custom GraphQL query against the Shopify Admin API.",
144
+ argsSchema: {
145
+ intent: z
146
+ .string()
147
+ .describe("What data do you want to fetch or what action do you want to perform?"),
148
+ },
149
+ }, async ({ intent }) => ({
150
+ messages: [
151
+ {
152
+ role: "user",
153
+ content: {
154
+ type: "text",
155
+ text: `I need help with a custom Shopify Admin API query. My goal is: "${intent}"
156
+
157
+ Please:
158
+ 1. Determine if this requires a query (read) or mutation (write)
159
+ 2. Construct the appropriate GraphQL operation
160
+ 3. Use the run_graphql_query tool to execute it
161
+ 4. Explain the results
162
+
163
+ If you're unsure about the exact schema, start with a simpler query and iterate based on what fields are available.`,
164
+ },
165
+ },
166
+ ],
167
+ }));
168
+ }
169
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Rate-limited queue for Shopify API calls
3
+ * Respects Shopify's rate limits based on shop plan tier
4
+ */
5
+ export declare const SHOPIFY_TIER_CONFIGS: {
6
+ readonly STANDARD: {
7
+ readonly name: "Standard Shopify";
8
+ readonly concurrency: 1;
9
+ readonly interval: 1000;
10
+ readonly intervalCap: 1;
11
+ };
12
+ readonly ADVANCED: {
13
+ readonly name: "Advanced Shopify";
14
+ readonly concurrency: 1;
15
+ readonly interval: 1000;
16
+ readonly intervalCap: 2;
17
+ };
18
+ readonly PLUS: {
19
+ readonly name: "Shopify Plus";
20
+ readonly concurrency: 2;
21
+ readonly interval: 1000;
22
+ readonly intervalCap: 5;
23
+ };
24
+ readonly ENTERPRISE: {
25
+ readonly name: "Shopify for Enterprise (Commerce Components)";
26
+ readonly concurrency: 3;
27
+ readonly interval: 1000;
28
+ readonly intervalCap: 10;
29
+ };
30
+ };
31
+ export type ShopifyTier = keyof typeof SHOPIFY_TIER_CONFIGS;
32
+ /**
33
+ * Get the current queue configuration
34
+ */
35
+ export declare function getCurrentTierInfo(): {
36
+ tier: ShopifyTier;
37
+ config: (typeof SHOPIFY_TIER_CONFIGS)[ShopifyTier];
38
+ };
39
+ /**
40
+ * Update the queue to use a different tier's rate limits
41
+ */
42
+ export declare function updateQueue(tier: ShopifyTier): void;
43
+ /**
44
+ * Detect Shopify tier from shop plan information
45
+ */
46
+ export declare function detectTierFromPlan(plan: {
47
+ shopifyPlus?: boolean;
48
+ displayName?: string;
49
+ }): ShopifyTier;
50
+ /**
51
+ * Enqueue a function to be executed with rate limiting
52
+ */
53
+ export declare function enqueue<T>(fn: () => Promise<T>): Promise<T>;
54
+ /**
55
+ * Get queue statistics
56
+ */
57
+ export declare function getQueueStats(): {
58
+ pending: number;
59
+ size: number;
60
+ isPaused: boolean;
61
+ };
62
+ /**
63
+ * Pause the queue (useful for graceful shutdown)
64
+ */
65
+ export declare function pauseQueue(): void;
66
+ /**
67
+ * Resume the queue
68
+ */
69
+ export declare function resumeQueue(): void;
70
+ /**
71
+ * Clear all pending items from the queue
72
+ */
73
+ export declare function clearQueue(): void;
package/dist/queue.js ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Rate-limited queue for Shopify API calls
3
+ * Respects Shopify's rate limits based on shop plan tier
4
+ */
5
+ import PQueue from "p-queue";
6
+ // Shopify Admin API rate limit configurations
7
+ // https://shopify.dev/docs/api/usage/limits#rate-limits
8
+ export const SHOPIFY_TIER_CONFIGS = {
9
+ STANDARD: {
10
+ name: "Standard Shopify",
11
+ // GraphQL Admin API: 100 points/second, bucket size 1000 points
12
+ // Conservative settings: ~1 request/second
13
+ concurrency: 1,
14
+ interval: 1000,
15
+ intervalCap: 1,
16
+ },
17
+ ADVANCED: {
18
+ name: "Advanced Shopify",
19
+ // GraphQL Admin API: 200 points/second
20
+ concurrency: 1,
21
+ interval: 1000,
22
+ intervalCap: 2,
23
+ },
24
+ PLUS: {
25
+ name: "Shopify Plus",
26
+ // GraphQL Admin API: 1000 points/second
27
+ concurrency: 2,
28
+ interval: 1000,
29
+ intervalCap: 5,
30
+ },
31
+ ENTERPRISE: {
32
+ name: "Shopify for Enterprise (Commerce Components)",
33
+ // GraphQL Admin API: 2000 points/second
34
+ concurrency: 3,
35
+ interval: 1000,
36
+ intervalCap: 10,
37
+ },
38
+ };
39
+ // Global queue instance
40
+ let queue = new PQueue(SHOPIFY_TIER_CONFIGS.STANDARD);
41
+ let currentTier = "STANDARD";
42
+ /**
43
+ * Get the current queue configuration
44
+ */
45
+ export function getCurrentTierInfo() {
46
+ return {
47
+ tier: currentTier,
48
+ config: SHOPIFY_TIER_CONFIGS[currentTier],
49
+ };
50
+ }
51
+ /**
52
+ * Update the queue to use a different tier's rate limits
53
+ */
54
+ export function updateQueue(tier) {
55
+ const config = SHOPIFY_TIER_CONFIGS[tier];
56
+ // Clear existing queue and create new one
57
+ queue.clear();
58
+ queue = new PQueue({
59
+ concurrency: config.concurrency,
60
+ interval: config.interval,
61
+ intervalCap: config.intervalCap,
62
+ });
63
+ currentTier = tier;
64
+ console.error(`[shopify-store-mcp] Queue updated to ${config.name} tier (${tier})`);
65
+ }
66
+ /**
67
+ * Detect Shopify tier from shop plan information
68
+ */
69
+ export function detectTierFromPlan(plan) {
70
+ // Check for Shopify Plus first (most specific)
71
+ if (plan.shopifyPlus) {
72
+ return "PLUS";
73
+ }
74
+ // Check display name for other tiers
75
+ const displayName = (plan.displayName || "").toLowerCase();
76
+ if (displayName.includes("advanced")) {
77
+ return "ADVANCED";
78
+ }
79
+ if (displayName.includes("enterprise") ||
80
+ displayName.includes("commerce components")) {
81
+ return "ENTERPRISE";
82
+ }
83
+ // Default to STANDARD for Basic, Development, Grow, Lite, etc.
84
+ return "STANDARD";
85
+ }
86
+ /**
87
+ * Enqueue a function to be executed with rate limiting
88
+ */
89
+ export async function enqueue(fn) {
90
+ return queue.add(fn);
91
+ }
92
+ /**
93
+ * Get queue statistics
94
+ */
95
+ export function getQueueStats() {
96
+ return {
97
+ pending: queue.pending,
98
+ size: queue.size,
99
+ isPaused: queue.isPaused,
100
+ };
101
+ }
102
+ /**
103
+ * Pause the queue (useful for graceful shutdown)
104
+ */
105
+ export function pauseQueue() {
106
+ queue.pause();
107
+ }
108
+ /**
109
+ * Resume the queue
110
+ */
111
+ export function resumeQueue() {
112
+ queue.start();
113
+ }
114
+ /**
115
+ * Clear all pending items from the queue
116
+ */
117
+ export function clearQueue() {
118
+ queue.clear();
119
+ }
120
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ShopifyConfig } from "../config.js";
3
+ export declare function registerAllResources(server: McpServer, config: ShopifyConfig): void;