@anton.andrusenko/shopify-mcp-admin 1.0.1 → 1.1.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 CHANGED
@@ -108,7 +108,7 @@ Tokens are automatically refreshed every 24 hours.
108
108
  | `PORT` | No | `3000` | HTTP server port (when `TRANSPORT=http`) |
109
109
  | `DEBUG` | No | — | Enable debug logging (`1` or `true`) |
110
110
  | `LOG_LEVEL` | No | `info` | Log level: `debug`, `info`, `warn`, `error` |
111
- | `SHOPIFY_MCP_LAZY_LOADING` | No | `true` | Enable modular lazy loading (set to `false` for all tools at startup) |
111
+ | `SHOPIFY_MCP_LAZY_LOADING` | No | `false` | Enable modular lazy loading (set to `true` for on-demand module loading) |
112
112
  | `SHOPIFY_MCP_ROLE` | No | — | Role preset for automatic module loading (see [Role Presets](#-role-presets)) |
113
113
 
114
114
  **⚡ Authentication:** Provide EITHER `SHOPIFY_ACCESS_TOKEN` (legacy) OR both `SHOPIFY_CLIENT_ID` and `SHOPIFY_CLIENT_SECRET` (Dev Dashboard).
@@ -832,7 +832,7 @@ export SHOPIFY_MCP_LAZY_LOADING=false
832
832
  |-------|----------|
833
833
  | Tool not found after upgrade | Load the appropriate module: `load-module(module: "collections")` |
834
834
  | "Module not found" error | Use `list-modules` to see valid module names |
835
- | Want all tools at startup | Set `SHOPIFY_MCP_LAZY_LOADING=false` |
835
+ | Want modular lazy loading | Set `SHOPIFY_MCP_LAZY_LOADING=true` (requires MCP client that supports tool list refresh) |
836
836
  | AI agent loading too many modules | Use a role preset instead of on-demand loading |
837
837
 
838
838
  ---
package/dist/index.js CHANGED
@@ -27,9 +27,11 @@ var configSchema = z.object({
27
27
  // Default: 5 minutes (300000ms) - configurable for performance tuning
28
28
  STORE_INFO_CACHE_TTL_MS: z.string().optional().default("300000").transform(Number).describe("Cache TTL for store info in milliseconds (default: 5 minutes)"),
29
29
  // Lazy loading configuration (Epic 12)
30
- // Default: true - enables module-based lazy loading for optimal AI performance
31
- // Set to 'false' or '0' to load all tools at startup (legacy mode)
32
- SHOPIFY_MCP_LAZY_LOADING: z.string().optional().default("true").transform((val) => val === "true" || val === "1").describe("Enable lazy loading of tools via modules (default: true)"),
30
+ // Default: false - loads all tools at startup for maximum compatibility
31
+ // Note: Claude Desktop doesn't support dynamic tool refresh via notifications,
32
+ // so lazy loading is disabled by default. Set to 'true' for clients that
33
+ // properly handle notifications/tools/list_changed.
34
+ SHOPIFY_MCP_LAZY_LOADING: z.string().optional().default("false").transform((val) => val === "true" || val === "1").describe("Enable lazy loading of tools via modules (default: false)"),
33
35
  // Role preset configuration (Story 12.3: Progressive Loading)
34
36
  // Automatically loads appropriate modules at startup based on role
35
37
  // Valid roles: inventory-manager, product-manager, content-manager,
@@ -3199,20 +3201,42 @@ function getRegisteredTools() {
3199
3201
  annotations: tool.annotations
3200
3202
  }));
3201
3203
  }
3204
+ function getAllRegisteredToolNames() {
3205
+ return Array.from(registeredTools.keys());
3206
+ }
3202
3207
  function getToolByName(name) {
3203
3208
  return registeredTools.get(name);
3204
3209
  }
3205
3210
  function getToolNames() {
3206
3211
  return Array.from(registeredTools.keys());
3207
3212
  }
3213
+ var toolListChangedCallback = null;
3214
+ function setToolListChangedCallback(callback) {
3215
+ toolListChangedCallback = callback;
3216
+ log.debug("Tool list changed callback registered");
3217
+ }
3218
+ function notifyToolListChanged() {
3219
+ if (toolListChangedCallback) {
3220
+ log.info("\u{1F514} SENDING tools/list_changed notification to client");
3221
+ toolListChangedCallback();
3222
+ } else {
3223
+ log.warn("\u26A0\uFE0F notifyToolListChanged called but no callback registered!");
3224
+ }
3225
+ }
3208
3226
  function enableTool(name) {
3209
3227
  const tool = registeredTools.get(name);
3210
3228
  if (!tool) {
3211
3229
  log.debug(`Cannot enable tool: ${name} not found`);
3212
3230
  return false;
3213
3231
  }
3232
+ const previousState = toolEnabledState.get(name);
3233
+ const wasEnabled = previousState ?? true;
3214
3234
  toolEnabledState.set(name, true);
3215
- log.debug(`Tool enabled: ${name}`);
3235
+ log.debug(`Tool enabled: ${name} (was: ${previousState}, wasEnabled: ${wasEnabled})`);
3236
+ if (!wasEnabled) {
3237
+ log.info(`\u{1F4E2} Tool ${name} state changed from disabled to enabled, triggering notification`);
3238
+ notifyToolListChanged();
3239
+ }
3216
3240
  return true;
3217
3241
  }
3218
3242
  function disableTool(name) {
@@ -3221,8 +3245,12 @@ function disableTool(name) {
3221
3245
  log.debug(`Cannot disable tool: ${name} not found`);
3222
3246
  return false;
3223
3247
  }
3248
+ const wasEnabled = toolEnabledState.get(name) ?? true;
3224
3249
  toolEnabledState.set(name, false);
3225
3250
  log.debug(`Tool disabled: ${name}`);
3251
+ if (wasEnabled) {
3252
+ notifyToolListChanged();
3253
+ }
3226
3254
  return true;
3227
3255
  }
3228
3256
  function isToolEnabled(name) {
@@ -14185,6 +14213,10 @@ function getSuggestionsForTool(toolName) {
14185
14213
 
14186
14214
  // src/tools/index.ts
14187
14215
  function setupToolHandlers(server) {
14216
+ setToolListChangedCallback(() => {
14217
+ server.sendToolListChanged();
14218
+ log.debug("Sent tools/list_changed notification to clients");
14219
+ });
14188
14220
  server.server.setRequestHandler(ListToolsRequestSchema, async () => {
14189
14221
  const tools = getRegisteredTools();
14190
14222
  log.debug(`tools/list returning ${tools.length} tools`);
@@ -14208,16 +14240,35 @@ function setupToolHandlers(server) {
14208
14240
  }
14209
14241
  const tool = getToolByName(name);
14210
14242
  if (!tool) {
14211
- const availableTools = getRegisteredTools();
14212
- const toolList = availableTools.length > 0 ? `Available tools: ${availableTools.map((t) => t.name).join(", ")}` : "No tools are currently registered.";
14213
- log.warn(`Tool not found: ${name}${name !== rawName ? ` (received as "${rawName}")` : ""}`);
14243
+ const allTools = getAllRegisteredToolNames();
14244
+ const enabledTools = getRegisteredTools();
14245
+ const totalRegistered = allTools.length;
14246
+ const totalEnabled = enabledTools.length;
14247
+ const similarTools = allTools.filter(
14248
+ (t) => t.toLowerCase().includes(name.toLowerCase()) || name.toLowerCase().includes(t.toLowerCase())
14249
+ );
14250
+ let diagnosticInfo = `
14251
+
14252
+ Diagnostics:
14253
+ - Total tools registered: ${totalRegistered}
14254
+ - Tools currently enabled: ${totalEnabled}`;
14255
+ if (similarTools.length > 0) {
14256
+ diagnosticInfo += `
14257
+ - Similar tool names found: ${similarTools.join(", ")}`;
14258
+ }
14259
+ const toolList = enabledTools.length > 0 ? `
14260
+
14261
+ Enabled tools: ${enabledTools.map((t) => t.name).join(", ")}` : "\n\nNo tools are currently enabled. Try restarting your MCP client.";
14262
+ log.warn(
14263
+ `Tool not found: ${name}${name !== rawName ? ` (received as "${rawName}")` : ""}. Registered: ${totalRegistered}, Enabled: ${totalEnabled}`
14264
+ );
14214
14265
  return {
14215
14266
  content: [
14216
14267
  {
14217
14268
  type: "text",
14218
- text: `Error: Tool "${name}" not found${name !== rawName ? ` (received as "${rawName}")` : ""}.
14269
+ text: `Error: Tool "${name}" not found${name !== rawName ? ` (received as "${rawName}")` : ""}.${diagnosticInfo}
14219
14270
 
14220
- Suggestion: Use tools/list to see available tools. ${toolList}`
14271
+ Suggestion: Use tools/list to refresh available tools. If this tool should exist, try restarting your MCP client (Claude Desktop).${toolList}`
14221
14272
  }
14222
14273
  ],
14223
14274
  isError: true
@@ -14375,8 +14426,12 @@ function registerAllTools(server) {
14375
14426
  `Lazy loading enabled: ${enabledCount} core tools active, ${totalToolCount - enabledCount} tools available via modules`
14376
14427
  );
14377
14428
  }
14429
+ log.debug(
14430
+ `Enabled tools: ${getRegisteredTools().map((t) => t.name).join(", ")}`
14431
+ );
14378
14432
  } else {
14379
14433
  log.info(`Lazy loading disabled (legacy mode): ${totalToolCount} tools registered`);
14434
+ log.debug(`All tools: ${getToolNames().join(", ")}`);
14380
14435
  }
14381
14436
  }
14382
14437
  function applyLazyLoading() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anton.andrusenko/shopify-mcp-admin",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "MCP server for Shopify Admin API - enables AI agents to manage Shopify stores with 71 tools for products, inventory, collections, content, SEO, metafields, markets & translations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,6 +24,10 @@
24
24
  "inspect": "npx @modelcontextprotocol/inspector node dist/index.js",
25
25
  "inspect:dev": "npx @modelcontextprotocol/inspector npx tsx src/index.ts",
26
26
  "inspect:config": "npx @modelcontextprotocol/inspector --config mcp-inspector.json",
27
+ "fast-agent": "fast-agent",
28
+ "fast-agent:check": "fast-agent check",
29
+ "fast-agent:chat": "fast-agent go --servers shopify-mcp-admin",
30
+ "fast-agent:dev": "fast-agent go --servers shopify-mcp-admin-dev",
27
31
  "ci": "npm run lint && npm run typecheck && npm run test && npm run build",
28
32
  "version:patch": "npm version patch --no-git-tag-version",
29
33
  "version:minor": "npm version minor --no-git-tag-version",