@anton.andrusenko/shopify-mcp-admin 0.7.0 → 0.8.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 (3) hide show
  1. package/README.md +76 -5
  2. package/dist/index.js +1006 -43
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @anton.andrusenko/shopify-mcp-admin
2
2
 
3
- > 🛍️ **MCP Server for Shopify Admin API** — Enable AI agents to manage Shopify stores with 71 powerful tools
3
+ > 🛍️ **MCP Server for Shopify Admin API** — Enable AI agents to manage Shopify stores with 79 powerful tools
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/@anton.andrusenko%2Fshopify-mcp-admin.svg)](https://www.npmjs.com/package/@anton.andrusenko/shopify-mcp-admin)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -11,7 +11,7 @@
11
11
 
12
12
  ## ✨ Features
13
13
 
14
- - 🛠️ **71 MCP Tools** — Complete store management: products, inventory, collections, pages, blogs, redirects, metafields, markets, locales & translations
14
+ - 🛠️ **79 MCP Tools** — Complete store management: products, inventory, collections, pages, blogs, redirects, metafields, markets, locales & translations
15
15
  - 🤖 **AI-Optimized** — Tool descriptions and error messages designed for LLM comprehension
16
16
  - 🔌 **Dual Transport** — STDIO for Claude Desktop, HTTP for ChatGPT/OpenAI
17
17
  - ⚡ **Rate Limiting** — Automatic retry with exponential backoff for Shopify API limits
@@ -250,14 +250,60 @@ Each tool can be converted to OpenAI function format:
250
250
 
251
251
  ## 🛠️ Available Tools
252
252
 
253
- @anton.andrusenko/shopify-mcp-admin provides **71 tools** organized into 16 categories:
253
+ @anton.andrusenko/shopify-mcp-admin provides **79 tools** organized into 16 categories:
254
254
 
255
255
  <details>
256
- <summary><strong>🏪 Store Info (1 tool)</strong></summary>
256
+ <summary><strong>🏪 Store Info (9 tools)</strong></summary>
257
257
 
258
258
  | Tool | Description |
259
259
  |------|-------------|
260
260
  | `get-store-info` | Get basic store information (name, domain, plan, currency, timezone, email) |
261
+ | `get-store-limits` | Get store resource limits (max variants, max options, location limit) |
262
+ | `get-store-features` | Get feature flags (gift cards, reports, storefront, bundles, subscriptions) |
263
+ | `get-store-currencies` | Get multi-currency configuration (base currency, presentment currencies, formats) |
264
+ | `get-store-shipping` | Get shipping configuration (ships-to countries, countries in shipping zones) |
265
+ | `get-store-domain` | Get primary domain configuration (hostname, URL, SSL status) |
266
+ | `get-store-taxes` | Get tax configuration (taxes included in prices, tax shipping) |
267
+ | `get-store-policies` | Get legal policies (privacy, terms of service, refund policy) |
268
+ | `get-store-alerts` | Get admin alerts and setup requirements |
269
+
270
+ #### Example: Get Store Limits
271
+
272
+ ```json
273
+ {
274
+ "maxProductVariants": 2000,
275
+ "maxProductOptions": 3,
276
+ "locationLimit": 1000,
277
+ "redirectLimitReached": false
278
+ }
279
+ ```
280
+
281
+ #### Example: Get Store Features
282
+
283
+ ```json
284
+ {
285
+ "giftCards": true,
286
+ "reports": true,
287
+ "storefront": true,
288
+ "bundles": {
289
+ "eligibleForBundles": true
290
+ },
291
+ "sellsSubscriptions": false
292
+ }
293
+ ```
294
+
295
+ #### Example: Get Store Currencies
296
+
297
+ ```json
298
+ {
299
+ "currencyCode": "USD",
300
+ "enabledPresentmentCurrencies": ["USD", "EUR", "GBP", "CAD"],
301
+ "currencyFormats": {
302
+ "moneyFormat": "${{amount}}",
303
+ "moneyWithCurrencyFormat": "${{amount}} USD"
304
+ }
305
+ }
306
+ ```
261
307
 
262
308
  </details>
263
309
 
@@ -497,13 +543,38 @@ npm run inspect:config
497
543
 
498
544
  MCP Inspector opens a web UI at `http://localhost:6274` where you can:
499
545
 
500
- - 📋 Browse all 71 registered tools with schemas
546
+ - 📋 Browse all 79 registered tools with schemas
547
+ - 📊 Access 9 MCP resources for store context
501
548
  - ▶️ Execute tools interactively and view results
502
549
  - 🔍 Inspect JSON-RPC protocol messages
503
550
  - 📊 Monitor server events in real-time
504
551
 
505
552
  > **Tip:** Use `npm run inspect:dev` during development for instant feedback without rebuilding.
506
553
 
554
+ ---
555
+
556
+ ## 📊 MCP Resources
557
+
558
+ The MCP server exposes comprehensive store context information via MCP resources. These are read-only data sources that AI agents can query for context.
559
+
560
+ ### Extended Store Resources
561
+
562
+ | Resource URI | Description |
563
+ |--------------|-------------|
564
+ | `shopify://store/info` | Basic store info (name, domain, plan, currency, timezone) |
565
+ | `shopify://store/limits` | Resource limits (max variants, max options, location limit) |
566
+ | `shopify://store/features` | Feature flags (gift cards, reports, storefront, bundles) |
567
+ | `shopify://store/currencies` | Multi-currency configuration (base currency, presentment currencies) |
568
+ | `shopify://store/shipping` | Shipping configuration (ships-to countries, shipping zones) |
569
+ | `shopify://store/domain` | Primary domain configuration (hostname, URL, SSL status) |
570
+ | `shopify://store/taxes` | Tax configuration (taxes included, tax shipping) |
571
+ | `shopify://store/policies` | Legal policies (privacy, terms of service, refund) |
572
+ | `shopify://store/alerts` | Admin alerts and setup requirements |
573
+
574
+ > **Note:** For MCP clients that don't support resources (e.g., Claude Desktop), equivalent tools are available. See **Store Info Tools** below.
575
+
576
+ ---
577
+
507
578
  ### FAQ
508
579
 
509
580
  **Q: Can I connect to multiple stores?**
package/dist/index.js CHANGED
@@ -917,9 +917,351 @@ var PRODUCTS_QUERY = `
917
917
  }
918
918
  }
919
919
  `;
920
+ var STORE_LIMITS_QUERY = `
921
+ query ShopResourceLimits {
922
+ shop {
923
+ resourceLimits {
924
+ maxProductVariants
925
+ maxProductOptions
926
+ locationLimit
927
+ redirectLimitReached
928
+ }
929
+ }
930
+ }
931
+ `;
932
+ var STORE_FEATURES_QUERY = `
933
+ query ShopFeatures {
934
+ shop {
935
+ features {
936
+ giftCards
937
+ reports
938
+ storefront
939
+ bundles {
940
+ eligibleForBundles
941
+ }
942
+ sellsSubscriptions
943
+ }
944
+ }
945
+ }
946
+ `;
947
+ var STORE_CURRENCIES_QUERY = `
948
+ query ShopCurrencies {
949
+ shop {
950
+ currencyCode
951
+ enabledPresentmentCurrencies
952
+ currencyFormats {
953
+ moneyFormat
954
+ moneyWithCurrencyFormat
955
+ }
956
+ }
957
+ }
958
+ `;
959
+ var STORE_SHIPPING_QUERY = `
960
+ query ShopShipping {
961
+ shop {
962
+ shipsToCountries
963
+ countriesInShippingZones {
964
+ countryCodes
965
+ }
966
+ }
967
+ }
968
+ `;
969
+ var STORE_DOMAIN_QUERY = `
970
+ query ShopDomain {
971
+ shop {
972
+ primaryDomain {
973
+ host
974
+ url
975
+ sslEnabled
976
+ }
977
+ }
978
+ }
979
+ `;
980
+ var STORE_TAXES_QUERY = `
981
+ query ShopTaxes {
982
+ shop {
983
+ taxesIncluded
984
+ taxShipping
985
+ }
986
+ }
987
+ `;
988
+ var STORE_POLICIES_QUERY = `
989
+ query ShopPolicies {
990
+ shop {
991
+ shopPolicies {
992
+ title
993
+ type
994
+ url
995
+ }
996
+ }
997
+ }
998
+ `;
999
+ var STORE_ALERTS_QUERY = `
1000
+ query ShopAlerts {
1001
+ shop {
1002
+ alerts {
1003
+ action {
1004
+ title
1005
+ url
1006
+ }
1007
+ description
1008
+ }
1009
+ setupRequired
1010
+ }
1011
+ }
1012
+ `;
920
1013
 
921
- // src/shopify/store-info.ts
1014
+ // src/shopify/store-info-extended.ts
922
1015
  var DEFAULT_CACHE_TTL_MS = 5 * 60 * 1e3;
1016
+ var ALERTS_CACHE_TTL_MS = 60 * 1e3;
1017
+ var _cachedStoreLimits = null;
1018
+ var _limitsTimestamp = 0;
1019
+ var _cachedStoreFeatures = null;
1020
+ var _featuresTimestamp = 0;
1021
+ var _cachedStoreCurrencies = null;
1022
+ var _currenciesTimestamp = 0;
1023
+ var _cachedStoreShipping = null;
1024
+ var _shippingTimestamp = 0;
1025
+ var _cachedStoreDomain = null;
1026
+ var _domainTimestamp = 0;
1027
+ var _cachedStoreTaxes = null;
1028
+ var _taxesTimestamp = 0;
1029
+ var _cachedStorePolicies = null;
1030
+ var _policiesTimestamp = 0;
1031
+ var _cachedStoreAlerts = null;
1032
+ var _alertsTimestamp = 0;
1033
+ async function getStoreLimits() {
1034
+ const now = Date.now();
1035
+ const config = getConfig();
1036
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1037
+ if (_cachedStoreLimits && now - _limitsTimestamp < ttl) {
1038
+ log.debug("Returning cached store limits");
1039
+ return _cachedStoreLimits;
1040
+ }
1041
+ log.debug("Fetching fresh store limits from Shopify");
1042
+ const client = await getShopifyClient();
1043
+ const response = await withRateLimit(
1044
+ () => client.graphql.request(STORE_LIMITS_QUERY),
1045
+ "getStoreLimits"
1046
+ );
1047
+ if (response.errors && response.errors.length > 0) {
1048
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1049
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1050
+ }
1051
+ if (!response.data?.shop?.resourceLimits) {
1052
+ throw new Error("Invalid response: missing shop.resourceLimits data");
1053
+ }
1054
+ _cachedStoreLimits = response.data.shop.resourceLimits;
1055
+ _limitsTimestamp = now;
1056
+ return _cachedStoreLimits;
1057
+ }
1058
+ async function getStoreFeatures() {
1059
+ const now = Date.now();
1060
+ const config = getConfig();
1061
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1062
+ if (_cachedStoreFeatures && now - _featuresTimestamp < ttl) {
1063
+ log.debug("Returning cached store features");
1064
+ return _cachedStoreFeatures;
1065
+ }
1066
+ log.debug("Fetching fresh store features from Shopify");
1067
+ const client = await getShopifyClient();
1068
+ const response = await withRateLimit(
1069
+ () => client.graphql.request(STORE_FEATURES_QUERY),
1070
+ "getStoreFeatures"
1071
+ );
1072
+ if (response.errors && response.errors.length > 0) {
1073
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1074
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1075
+ }
1076
+ if (!response.data?.shop?.features) {
1077
+ throw new Error("Invalid response: missing shop.features data");
1078
+ }
1079
+ _cachedStoreFeatures = response.data.shop.features;
1080
+ _featuresTimestamp = now;
1081
+ return _cachedStoreFeatures;
1082
+ }
1083
+ async function getStoreCurrencies() {
1084
+ const now = Date.now();
1085
+ const config = getConfig();
1086
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1087
+ if (_cachedStoreCurrencies && now - _currenciesTimestamp < ttl) {
1088
+ log.debug("Returning cached store currencies");
1089
+ return _cachedStoreCurrencies;
1090
+ }
1091
+ log.debug("Fetching fresh store currencies from Shopify");
1092
+ const client = await getShopifyClient();
1093
+ const response = await withRateLimit(
1094
+ () => client.graphql.request(STORE_CURRENCIES_QUERY),
1095
+ "getStoreCurrencies"
1096
+ );
1097
+ if (response.errors && response.errors.length > 0) {
1098
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1099
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1100
+ }
1101
+ if (!response.data?.shop) {
1102
+ throw new Error("Invalid response: missing shop data");
1103
+ }
1104
+ const { currencyCode, enabledPresentmentCurrencies, currencyFormats } = response.data.shop;
1105
+ _cachedStoreCurrencies = {
1106
+ currencyCode,
1107
+ enabledPresentmentCurrencies,
1108
+ currencyFormats
1109
+ };
1110
+ _currenciesTimestamp = now;
1111
+ return _cachedStoreCurrencies;
1112
+ }
1113
+ async function getStoreShipping() {
1114
+ const now = Date.now();
1115
+ const config = getConfig();
1116
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1117
+ if (_cachedStoreShipping && now - _shippingTimestamp < ttl) {
1118
+ log.debug("Returning cached store shipping");
1119
+ return _cachedStoreShipping;
1120
+ }
1121
+ log.debug("Fetching fresh store shipping from Shopify");
1122
+ const client = await getShopifyClient();
1123
+ const response = await withRateLimit(
1124
+ () => client.graphql.request(STORE_SHIPPING_QUERY),
1125
+ "getStoreShipping"
1126
+ );
1127
+ if (response.errors && response.errors.length > 0) {
1128
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1129
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1130
+ }
1131
+ if (!response.data?.shop) {
1132
+ throw new Error("Invalid response: missing shop data");
1133
+ }
1134
+ _cachedStoreShipping = {
1135
+ shipsToCountries: response.data.shop.shipsToCountries,
1136
+ countriesInShippingZones: response.data.shop.countriesInShippingZones
1137
+ };
1138
+ _shippingTimestamp = now;
1139
+ return _cachedStoreShipping;
1140
+ }
1141
+ async function getStoreDomain() {
1142
+ const now = Date.now();
1143
+ const config = getConfig();
1144
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1145
+ if (_cachedStoreDomain && now - _domainTimestamp < ttl) {
1146
+ log.debug("Returning cached store domain");
1147
+ return _cachedStoreDomain;
1148
+ }
1149
+ log.debug("Fetching fresh store domain from Shopify");
1150
+ const client = await getShopifyClient();
1151
+ const response = await withRateLimit(
1152
+ () => client.graphql.request(STORE_DOMAIN_QUERY),
1153
+ "getStoreDomain"
1154
+ );
1155
+ if (response.errors && response.errors.length > 0) {
1156
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1157
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1158
+ }
1159
+ if (!response.data?.shop?.primaryDomain) {
1160
+ throw new Error("Invalid response: missing shop.primaryDomain data");
1161
+ }
1162
+ _cachedStoreDomain = {
1163
+ primaryDomain: response.data.shop.primaryDomain
1164
+ };
1165
+ _domainTimestamp = now;
1166
+ return _cachedStoreDomain;
1167
+ }
1168
+ async function getStoreTaxes() {
1169
+ const now = Date.now();
1170
+ const config = getConfig();
1171
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1172
+ if (_cachedStoreTaxes && now - _taxesTimestamp < ttl) {
1173
+ log.debug("Returning cached store taxes");
1174
+ return _cachedStoreTaxes;
1175
+ }
1176
+ log.debug("Fetching fresh store taxes from Shopify");
1177
+ const client = await getShopifyClient();
1178
+ const response = await withRateLimit(
1179
+ () => client.graphql.request(STORE_TAXES_QUERY),
1180
+ "getStoreTaxes"
1181
+ );
1182
+ if (response.errors && response.errors.length > 0) {
1183
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1184
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1185
+ }
1186
+ if (response.data?.shop === void 0 || response.data?.shop === null) {
1187
+ throw new Error("Invalid response: missing shop data");
1188
+ }
1189
+ _cachedStoreTaxes = {
1190
+ taxesIncluded: response.data.shop.taxesIncluded,
1191
+ taxShipping: response.data.shop.taxShipping
1192
+ };
1193
+ _taxesTimestamp = now;
1194
+ return _cachedStoreTaxes;
1195
+ }
1196
+ async function getStorePolicies() {
1197
+ const now = Date.now();
1198
+ const config = getConfig();
1199
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1200
+ if (_cachedStorePolicies && now - _policiesTimestamp < ttl) {
1201
+ log.debug("Returning cached store policies");
1202
+ return _cachedStorePolicies;
1203
+ }
1204
+ try {
1205
+ log.debug("Fetching fresh store policies from Shopify");
1206
+ const client = await getShopifyClient();
1207
+ const response = await withRateLimit(
1208
+ () => client.graphql.request(STORE_POLICIES_QUERY),
1209
+ "getStorePolicies"
1210
+ );
1211
+ if (response.errors && response.errors.length > 0) {
1212
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1213
+ if (errorMessages.toLowerCase().includes("access denied") || errorMessages.toLowerCase().includes("unauthorized")) {
1214
+ log.debug("read_legal_policies scope not available, returning empty policies");
1215
+ _cachedStorePolicies = { shopPolicies: [] };
1216
+ _policiesTimestamp = now;
1217
+ return _cachedStorePolicies;
1218
+ }
1219
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1220
+ }
1221
+ const policies = response.data?.shop?.shopPolicies ?? [];
1222
+ _cachedStorePolicies = { shopPolicies: policies };
1223
+ _policiesTimestamp = now;
1224
+ return _cachedStorePolicies;
1225
+ } catch (error) {
1226
+ if (error instanceof Error && (error.message.toLowerCase().includes("access denied") || error.message.toLowerCase().includes("unauthorized"))) {
1227
+ log.debug("read_legal_policies scope not available, returning empty policies");
1228
+ _cachedStorePolicies = { shopPolicies: [] };
1229
+ _policiesTimestamp = now;
1230
+ return _cachedStorePolicies;
1231
+ }
1232
+ throw error;
1233
+ }
1234
+ }
1235
+ async function getStoreAlerts() {
1236
+ const now = Date.now();
1237
+ const ttl = ALERTS_CACHE_TTL_MS;
1238
+ if (_cachedStoreAlerts && now - _alertsTimestamp < ttl) {
1239
+ log.debug("Returning cached store alerts");
1240
+ return _cachedStoreAlerts;
1241
+ }
1242
+ log.debug("Fetching fresh store alerts from Shopify");
1243
+ const client = await getShopifyClient();
1244
+ const response = await withRateLimit(
1245
+ () => client.graphql.request(STORE_ALERTS_QUERY),
1246
+ "getStoreAlerts"
1247
+ );
1248
+ if (response.errors && response.errors.length > 0) {
1249
+ const errorMessages = response.errors.map((e) => e.message).join(", ");
1250
+ throw new Error(`GraphQL errors: ${errorMessages}`);
1251
+ }
1252
+ if (response.data?.shop === void 0 || response.data?.shop === null) {
1253
+ throw new Error("Invalid response: missing shop data");
1254
+ }
1255
+ _cachedStoreAlerts = {
1256
+ alerts: response.data.shop.alerts ?? [],
1257
+ setupRequired: response.data.shop.setupRequired
1258
+ };
1259
+ _alertsTimestamp = now;
1260
+ return _cachedStoreAlerts;
1261
+ }
1262
+
1263
+ // src/shopify/store-info.ts
1264
+ var DEFAULT_CACHE_TTL_MS2 = 5 * 60 * 1e3;
923
1265
  var _cachedStoreInfo = null;
924
1266
  var _cacheTimestamp = 0;
925
1267
  function transformShopResponse(shop) {
@@ -939,7 +1281,7 @@ function transformShopResponse(shop) {
939
1281
  async function getStoreInfo() {
940
1282
  const now = Date.now();
941
1283
  const config = getConfig();
942
- const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS;
1284
+ const ttl = config.STORE_INFO_CACHE_TTL_MS ?? DEFAULT_CACHE_TTL_MS2;
943
1285
  if (_cachedStoreInfo && now - _cacheTimestamp < ttl) {
944
1286
  log.debug("Returning cached store info");
945
1287
  return _cachedStoreInfo;
@@ -1009,54 +1351,358 @@ function createServer() {
1009
1351
  const server = new McpServer(
1010
1352
  // Server info (sent to clients in initialize response)
1011
1353
  {
1012
- name: SERVER_NAME,
1013
- version: getServerVersion()
1354
+ name: SERVER_NAME,
1355
+ version: getServerVersion()
1356
+ },
1357
+ // Server options (capabilities for handler enforcement)
1358
+ {
1359
+ capabilities: {
1360
+ tools: {},
1361
+ // Enable tools capability (AC-2.1.4)
1362
+ resources: {},
1363
+ // Enable resources capability (AC-2.1.4)
1364
+ logging: {}
1365
+ // Enable logging capability (AC-9.5.1.2)
1366
+ },
1367
+ instructions: SERVER_INSTRUCTIONS
1368
+ // Provide Shopify context to AI agents (AC-9.5.1.1)
1369
+ }
1370
+ );
1371
+ return server;
1372
+ }
1373
+ function registerResources(server) {
1374
+ server.resource(
1375
+ "store-info",
1376
+ "shopify://store/info",
1377
+ {
1378
+ description: "Basic information about the connected Shopify store including name, domain, plan, currency, and timezone. Use this to understand the store context before performing operations.",
1379
+ mimeType: "application/json"
1380
+ },
1381
+ async () => {
1382
+ try {
1383
+ const storeInfo = await getStoreInfo();
1384
+ return {
1385
+ contents: [
1386
+ {
1387
+ uri: "shopify://store/info",
1388
+ mimeType: "application/json",
1389
+ text: JSON.stringify(storeInfo, null, 2)
1390
+ }
1391
+ ]
1392
+ };
1393
+ } catch (error) {
1394
+ log.error("Failed to fetch store info", error instanceof Error ? error : void 0);
1395
+ return {
1396
+ contents: [
1397
+ {
1398
+ uri: "shopify://store/info",
1399
+ mimeType: "application/json",
1400
+ text: JSON.stringify({
1401
+ error: "Failed to fetch store information",
1402
+ message: sanitizeLogMessage(
1403
+ error instanceof Error ? error.message : "Unknown error"
1404
+ )
1405
+ })
1406
+ }
1407
+ ]
1408
+ };
1409
+ }
1410
+ }
1411
+ );
1412
+ server.resource(
1413
+ "store-limits",
1414
+ "shopify://store/limits",
1415
+ {
1416
+ description: "Resource limits for the Shopify store including max product variants, max product options, location limit, and redirect limit status. Use this to validate operations against store constraints.",
1417
+ mimeType: "application/json"
1418
+ },
1419
+ async () => {
1420
+ try {
1421
+ const limits = await getStoreLimits();
1422
+ return {
1423
+ contents: [
1424
+ {
1425
+ uri: "shopify://store/limits",
1426
+ mimeType: "application/json",
1427
+ text: JSON.stringify(limits, null, 2)
1428
+ }
1429
+ ]
1430
+ };
1431
+ } catch (error) {
1432
+ log.error("Failed to fetch store limits", error instanceof Error ? error : void 0);
1433
+ return {
1434
+ contents: [
1435
+ {
1436
+ uri: "shopify://store/limits",
1437
+ mimeType: "application/json",
1438
+ text: JSON.stringify({
1439
+ error: "Failed to fetch store limits",
1440
+ message: sanitizeLogMessage(
1441
+ error instanceof Error ? error.message : "Unknown error"
1442
+ )
1443
+ })
1444
+ }
1445
+ ]
1446
+ };
1447
+ }
1448
+ }
1449
+ );
1450
+ server.resource(
1451
+ "store-features",
1452
+ "shopify://store/features",
1453
+ {
1454
+ description: "Feature flags for the Shopify store including gift cards, reports, storefront, bundles eligibility, and subscriptions. Use this to determine available store capabilities.",
1455
+ mimeType: "application/json"
1456
+ },
1457
+ async () => {
1458
+ try {
1459
+ const features = await getStoreFeatures();
1460
+ return {
1461
+ contents: [
1462
+ {
1463
+ uri: "shopify://store/features",
1464
+ mimeType: "application/json",
1465
+ text: JSON.stringify(features, null, 2)
1466
+ }
1467
+ ]
1468
+ };
1469
+ } catch (error) {
1470
+ log.error("Failed to fetch store features", error instanceof Error ? error : void 0);
1471
+ return {
1472
+ contents: [
1473
+ {
1474
+ uri: "shopify://store/features",
1475
+ mimeType: "application/json",
1476
+ text: JSON.stringify({
1477
+ error: "Failed to fetch store features",
1478
+ message: sanitizeLogMessage(
1479
+ error instanceof Error ? error.message : "Unknown error"
1480
+ )
1481
+ })
1482
+ }
1483
+ ]
1484
+ };
1485
+ }
1486
+ }
1487
+ );
1488
+ server.resource(
1489
+ "store-currencies",
1490
+ "shopify://store/currencies",
1491
+ {
1492
+ description: "Currency configuration for the Shopify store including base currency, enabled presentment currencies, and money format patterns. Use this to understand multi-currency setup.",
1493
+ mimeType: "application/json"
1494
+ },
1495
+ async () => {
1496
+ try {
1497
+ const currencies = await getStoreCurrencies();
1498
+ return {
1499
+ contents: [
1500
+ {
1501
+ uri: "shopify://store/currencies",
1502
+ mimeType: "application/json",
1503
+ text: JSON.stringify(currencies, null, 2)
1504
+ }
1505
+ ]
1506
+ };
1507
+ } catch (error) {
1508
+ log.error("Failed to fetch store currencies", error instanceof Error ? error : void 0);
1509
+ return {
1510
+ contents: [
1511
+ {
1512
+ uri: "shopify://store/currencies",
1513
+ mimeType: "application/json",
1514
+ text: JSON.stringify({
1515
+ error: "Failed to fetch store currencies",
1516
+ message: sanitizeLogMessage(
1517
+ error instanceof Error ? error.message : "Unknown error"
1518
+ )
1519
+ })
1520
+ }
1521
+ ]
1522
+ };
1523
+ }
1524
+ }
1525
+ );
1526
+ server.resource(
1527
+ "store-shipping",
1528
+ "shopify://store/shipping",
1529
+ {
1530
+ description: "Shipping configuration for the Shopify store including ships-to countries and countries with configured shipping zones. Use this to understand international shipping capabilities.",
1531
+ mimeType: "application/json"
1532
+ },
1533
+ async () => {
1534
+ try {
1535
+ const shipping = await getStoreShipping();
1536
+ return {
1537
+ contents: [
1538
+ {
1539
+ uri: "shopify://store/shipping",
1540
+ mimeType: "application/json",
1541
+ text: JSON.stringify(shipping, null, 2)
1542
+ }
1543
+ ]
1544
+ };
1545
+ } catch (error) {
1546
+ log.error("Failed to fetch store shipping", error instanceof Error ? error : void 0);
1547
+ return {
1548
+ contents: [
1549
+ {
1550
+ uri: "shopify://store/shipping",
1551
+ mimeType: "application/json",
1552
+ text: JSON.stringify({
1553
+ error: "Failed to fetch store shipping",
1554
+ message: sanitizeLogMessage(
1555
+ error instanceof Error ? error.message : "Unknown error"
1556
+ )
1557
+ })
1558
+ }
1559
+ ]
1560
+ };
1561
+ }
1562
+ }
1563
+ );
1564
+ server.resource(
1565
+ "store-domain",
1566
+ "shopify://store/domain",
1567
+ {
1568
+ description: "Primary domain configuration for the Shopify store including hostname, URL, and SSL status. Use this to construct proper URLs and understand store identity.",
1569
+ mimeType: "application/json"
1014
1570
  },
1015
- // Server options (capabilities for handler enforcement)
1571
+ async () => {
1572
+ try {
1573
+ const domain = await getStoreDomain();
1574
+ return {
1575
+ contents: [
1576
+ {
1577
+ uri: "shopify://store/domain",
1578
+ mimeType: "application/json",
1579
+ text: JSON.stringify(domain, null, 2)
1580
+ }
1581
+ ]
1582
+ };
1583
+ } catch (error) {
1584
+ log.error("Failed to fetch store domain", error instanceof Error ? error : void 0);
1585
+ return {
1586
+ contents: [
1587
+ {
1588
+ uri: "shopify://store/domain",
1589
+ mimeType: "application/json",
1590
+ text: JSON.stringify({
1591
+ error: "Failed to fetch store domain",
1592
+ message: sanitizeLogMessage(
1593
+ error instanceof Error ? error.message : "Unknown error"
1594
+ )
1595
+ })
1596
+ }
1597
+ ]
1598
+ };
1599
+ }
1600
+ }
1601
+ );
1602
+ server.resource(
1603
+ "store-taxes",
1604
+ "shopify://store/taxes",
1016
1605
  {
1017
- capabilities: {
1018
- tools: {},
1019
- // Enable tools capability (AC-2.1.4)
1020
- resources: {},
1021
- // Enable resources capability (AC-2.1.4)
1022
- logging: {}
1023
- // Enable logging capability (AC-9.5.1.2)
1024
- },
1025
- instructions: SERVER_INSTRUCTIONS
1026
- // Provide Shopify context to AI agents (AC-9.5.1.1)
1606
+ description: "Tax configuration for the Shopify store including whether taxes are included in prices and tax shipping settings. Use this to understand pricing structure for tax calculations.",
1607
+ mimeType: "application/json"
1608
+ },
1609
+ async () => {
1610
+ try {
1611
+ const taxes = await getStoreTaxes();
1612
+ return {
1613
+ contents: [
1614
+ {
1615
+ uri: "shopify://store/taxes",
1616
+ mimeType: "application/json",
1617
+ text: JSON.stringify(taxes, null, 2)
1618
+ }
1619
+ ]
1620
+ };
1621
+ } catch (error) {
1622
+ log.error("Failed to fetch store taxes", error instanceof Error ? error : void 0);
1623
+ return {
1624
+ contents: [
1625
+ {
1626
+ uri: "shopify://store/taxes",
1627
+ mimeType: "application/json",
1628
+ text: JSON.stringify({
1629
+ error: "Failed to fetch store taxes",
1630
+ message: sanitizeLogMessage(
1631
+ error instanceof Error ? error.message : "Unknown error"
1632
+ )
1633
+ })
1634
+ }
1635
+ ]
1636
+ };
1637
+ }
1027
1638
  }
1028
1639
  );
1029
- return server;
1030
- }
1031
- function registerResources(server) {
1032
1640
  server.resource(
1033
- "store-info",
1034
- "shopify://store/info",
1641
+ "store-policies",
1642
+ "shopify://store/policies",
1035
1643
  {
1036
- description: "Basic information about the connected Shopify store including name, domain, plan, currency, and timezone. Use this to understand the store context before performing operations.",
1644
+ description: "Legal policies for the Shopify store (privacy policy, terms of service, refund policy). Returns empty array if read_legal_policies scope is not available. Use this to reference store policies in customer communications.",
1037
1645
  mimeType: "application/json"
1038
1646
  },
1039
1647
  async () => {
1040
1648
  try {
1041
- const storeInfo = await getStoreInfo();
1649
+ const policies = await getStorePolicies();
1042
1650
  return {
1043
1651
  contents: [
1044
1652
  {
1045
- uri: "shopify://store/info",
1653
+ uri: "shopify://store/policies",
1046
1654
  mimeType: "application/json",
1047
- text: JSON.stringify(storeInfo, null, 2)
1655
+ text: JSON.stringify(policies, null, 2)
1048
1656
  }
1049
1657
  ]
1050
1658
  };
1051
1659
  } catch (error) {
1052
- log.error("Failed to fetch store info", error instanceof Error ? error : void 0);
1660
+ log.error("Failed to fetch store policies", error instanceof Error ? error : void 0);
1053
1661
  return {
1054
1662
  contents: [
1055
1663
  {
1056
- uri: "shopify://store/info",
1664
+ uri: "shopify://store/policies",
1057
1665
  mimeType: "application/json",
1058
1666
  text: JSON.stringify({
1059
- error: "Failed to fetch store information",
1667
+ error: "Failed to fetch store policies",
1668
+ message: sanitizeLogMessage(
1669
+ error instanceof Error ? error.message : "Unknown error"
1670
+ )
1671
+ })
1672
+ }
1673
+ ]
1674
+ };
1675
+ }
1676
+ }
1677
+ );
1678
+ server.resource(
1679
+ "store-alerts",
1680
+ "shopify://store/alerts",
1681
+ {
1682
+ description: "Active admin alerts and setup requirements for the Shopify store. Use this to proactively identify issues needing merchant attention.",
1683
+ mimeType: "application/json"
1684
+ },
1685
+ async () => {
1686
+ try {
1687
+ const alerts = await getStoreAlerts();
1688
+ return {
1689
+ contents: [
1690
+ {
1691
+ uri: "shopify://store/alerts",
1692
+ mimeType: "application/json",
1693
+ text: JSON.stringify(alerts, null, 2)
1694
+ }
1695
+ ]
1696
+ };
1697
+ } catch (error) {
1698
+ log.error("Failed to fetch store alerts", error instanceof Error ? error : void 0);
1699
+ return {
1700
+ contents: [
1701
+ {
1702
+ uri: "shopify://store/alerts",
1703
+ mimeType: "application/json",
1704
+ text: JSON.stringify({
1705
+ error: "Failed to fetch store alerts",
1060
1706
  message: sanitizeLogMessage(
1061
1707
  error instanceof Error ? error.message : "Unknown error"
1062
1708
  )
@@ -2451,7 +3097,7 @@ function wrapToolHandler(toolName, schema, handler) {
2451
3097
  };
2452
3098
  }
2453
3099
  function registerTool(definition, handler, options = {}) {
2454
- const { name, title, description, inputSchema: inputSchema72, annotations } = definition;
3100
+ const { name, title, description, inputSchema: inputSchema80, annotations } = definition;
2455
3101
  try {
2456
3102
  if (!options.skipNameValidation) {
2457
3103
  validateToolName(name);
@@ -2459,8 +3105,8 @@ function registerTool(definition, handler, options = {}) {
2459
3105
  if (registeredTools.has(name)) {
2460
3106
  throw new Error(`Tool "${name}" is already registered. Tool names must be unique.`);
2461
3107
  }
2462
- const jsonSchema = convertZodToJsonSchema(inputSchema72);
2463
- const wrappedHandler = wrapToolHandler(name, inputSchema72, handler);
3108
+ const jsonSchema = convertZodToJsonSchema(inputSchema80);
3109
+ const wrappedHandler = wrapToolHandler(name, inputSchema80, handler);
2464
3110
  const finalAnnotations = {
2465
3111
  ...deriveDefaultAnnotations(name),
2466
3112
  ...annotations,
@@ -2472,7 +3118,7 @@ function registerTool(definition, handler, options = {}) {
2472
3118
  title,
2473
3119
  description,
2474
3120
  inputSchema: jsonSchema,
2475
- zodSchema: inputSchema72,
3121
+ zodSchema: inputSchema80,
2476
3122
  handler: wrappedHandler,
2477
3123
  annotations: finalAnnotations
2478
3124
  };
@@ -12560,20 +13206,180 @@ function registerSubmitRedirectImportTool() {
12560
13206
  );
12561
13207
  }
12562
13208
 
12563
- // src/tools/get-store-info.ts
13209
+ // src/tools/get-store-alerts.ts
12564
13210
  import { z as z73 } from "zod";
12565
13211
  var inputSchema71 = z73.object({});
12566
13212
  var outputSchema71 = z73.object({
12567
- name: z73.string().describe("Store name"),
12568
- domain: z73.string().describe("Store domain (without .myshopify.com)"),
12569
- myshopifyDomain: z73.string().describe("Full myshopify.com domain"),
12570
- plan: z73.object({
12571
- displayName: z73.string().describe("Current plan name"),
12572
- partnerDevelopment: z73.boolean().describe("Whether partner development store")
13213
+ alerts: z73.array(
13214
+ z73.object({
13215
+ action: z73.object({
13216
+ title: z73.string().describe('The text for the button in the alert (e.g., "Add credit card")'),
13217
+ url: z73.string().describe("The target URL that the button links to")
13218
+ }).describe("Action to resolve the alert"),
13219
+ description: z73.string().describe("Human-readable alert description")
13220
+ })
13221
+ ).describe("Array of active admin alerts"),
13222
+ setupRequired: z73.boolean().describe("Whether store setup is incomplete")
13223
+ });
13224
+ async function handleGetStoreAlerts(context, _params) {
13225
+ log.debug(`Getting store alerts for shop: ${context.shopDomain}`);
13226
+ return await getStoreAlerts();
13227
+ }
13228
+ function registerGetStoreAlertsTool() {
13229
+ registerContextAwareTool(
13230
+ {
13231
+ name: "get-store-alerts",
13232
+ title: "Get Store Alerts",
13233
+ description: "Get active admin alerts and setup requirements for the connected Shopify store. **Prerequisites:** None. **Use this** to proactively identify issues needing merchant attention.",
13234
+ inputSchema: inputSchema71,
13235
+ outputSchema: outputSchema71,
13236
+ category: "store",
13237
+ relationships: {
13238
+ relatedTools: ["get-store-info", "list-low-inventory"],
13239
+ followUps: []
13240
+ },
13241
+ annotations: {
13242
+ readOnlyHint: true,
13243
+ destructiveHint: false,
13244
+ idempotentHint: true,
13245
+ openWorldHint: true
13246
+ }
13247
+ },
13248
+ handleGetStoreAlerts
13249
+ );
13250
+ }
13251
+
13252
+ // src/tools/get-store-currencies.ts
13253
+ import { z as z74 } from "zod";
13254
+ var inputSchema72 = z74.object({});
13255
+ var outputSchema72 = z74.object({
13256
+ currencyCode: z74.string().describe("Base currency code (e.g., USD)"),
13257
+ enabledPresentmentCurrencies: z74.array(z74.string()).describe("Enabled multi-currency codes"),
13258
+ currencyFormats: z74.object({
13259
+ moneyFormat: z74.string().describe("Money format pattern (e.g., ${{amount}})"),
13260
+ moneyWithCurrencyFormat: z74.string().describe("Money with currency format (e.g., ${{amount}} USD)")
13261
+ }).describe("Currency format patterns")
13262
+ });
13263
+ async function handleGetStoreCurrencies(context, _params) {
13264
+ log.debug(`Getting store currencies for shop: ${context.shopDomain}`);
13265
+ return await getStoreCurrencies();
13266
+ }
13267
+ function registerGetStoreCurrenciesTool() {
13268
+ registerContextAwareTool(
13269
+ {
13270
+ name: "get-store-currencies",
13271
+ title: "Get Store Currencies",
13272
+ description: "Get currency configuration for the connected Shopify store including base currency, enabled presentment currencies, and money format patterns. **Prerequisites:** None. **Use this** to understand multi-currency setup.",
13273
+ inputSchema: inputSchema72,
13274
+ outputSchema: outputSchema72,
13275
+ category: "store",
13276
+ relationships: {
13277
+ relatedTools: ["get-store-info", "get-store-limits"],
13278
+ followUps: ["list-markets", "list-products"]
13279
+ },
13280
+ annotations: {
13281
+ readOnlyHint: true,
13282
+ destructiveHint: false,
13283
+ idempotentHint: true,
13284
+ openWorldHint: true
13285
+ }
13286
+ },
13287
+ handleGetStoreCurrencies
13288
+ );
13289
+ }
13290
+
13291
+ // src/tools/get-store-domain.ts
13292
+ import { z as z75 } from "zod";
13293
+ var inputSchema73 = z75.object({});
13294
+ var outputSchema73 = z75.object({
13295
+ primaryDomain: z75.object({
13296
+ host: z75.string().describe('Domain hostname (e.g., "mystore.com")'),
13297
+ url: z75.string().describe('Full domain URL (e.g., "https://mystore.com")'),
13298
+ sslEnabled: z75.boolean().describe("Whether SSL is enabled")
13299
+ })
13300
+ });
13301
+ async function handleGetStoreDomain(context, _params) {
13302
+ log.debug(`Getting store domain for shop: ${context.shopDomain}`);
13303
+ return await getStoreDomain();
13304
+ }
13305
+ function registerGetStoreDomainTool() {
13306
+ registerContextAwareTool(
13307
+ {
13308
+ name: "get-store-domain",
13309
+ title: "Get Store Domain",
13310
+ description: "Get primary domain configuration for the connected Shopify store including hostname, URL, and SSL status. **Prerequisites:** None. **Use this** to construct proper URLs and understand store identity.",
13311
+ inputSchema: inputSchema73,
13312
+ outputSchema: outputSchema73,
13313
+ category: "store",
13314
+ relationships: {
13315
+ relatedTools: ["get-store-info", "get-store-shipping"],
13316
+ followUps: ["create-redirect"]
13317
+ },
13318
+ annotations: {
13319
+ readOnlyHint: true,
13320
+ destructiveHint: false,
13321
+ idempotentHint: true,
13322
+ openWorldHint: true
13323
+ }
13324
+ },
13325
+ handleGetStoreDomain
13326
+ );
13327
+ }
13328
+
13329
+ // src/tools/get-store-features.ts
13330
+ import { z as z76 } from "zod";
13331
+ var inputSchema74 = z76.object({});
13332
+ var outputSchema74 = z76.object({
13333
+ giftCards: z76.boolean().describe("Gift cards enabled"),
13334
+ reports: z76.boolean().describe("Reports enabled"),
13335
+ storefront: z76.boolean().describe("Storefront enabled"),
13336
+ bundles: z76.object({
13337
+ eligibleForBundles: z76.boolean().describe("Whether store is eligible for bundles")
13338
+ }).describe("Bundles feature configuration"),
13339
+ sellsSubscriptions: z76.boolean().describe("Subscriptions enabled")
13340
+ });
13341
+ async function handleGetStoreFeatures(context, _params) {
13342
+ log.debug(`Getting store features for shop: ${context.shopDomain}`);
13343
+ return await getStoreFeatures();
13344
+ }
13345
+ function registerGetStoreFeaturesTool() {
13346
+ registerContextAwareTool(
13347
+ {
13348
+ name: "get-store-features",
13349
+ title: "Get Store Features",
13350
+ description: "Get feature flags for the connected Shopify store including gift cards, reports, storefront, bundles eligibility, and subscriptions. **Prerequisites:** None. **Use this** to determine available store capabilities.",
13351
+ inputSchema: inputSchema74,
13352
+ outputSchema: outputSchema74,
13353
+ category: "store",
13354
+ relationships: {
13355
+ relatedTools: ["get-store-info", "get-store-limits"],
13356
+ followUps: ["list-products", "list-collections"]
13357
+ },
13358
+ annotations: {
13359
+ readOnlyHint: true,
13360
+ destructiveHint: false,
13361
+ idempotentHint: true,
13362
+ openWorldHint: true
13363
+ }
13364
+ },
13365
+ handleGetStoreFeatures
13366
+ );
13367
+ }
13368
+
13369
+ // src/tools/get-store-info.ts
13370
+ import { z as z77 } from "zod";
13371
+ var inputSchema75 = z77.object({});
13372
+ var outputSchema75 = z77.object({
13373
+ name: z77.string().describe("Store name"),
13374
+ domain: z77.string().describe("Store domain (without .myshopify.com)"),
13375
+ myshopifyDomain: z77.string().describe("Full myshopify.com domain"),
13376
+ plan: z77.object({
13377
+ displayName: z77.string().describe("Current plan name"),
13378
+ partnerDevelopment: z77.boolean().describe("Whether partner development store")
12573
13379
  }).describe("Store plan details"),
12574
- currencyCode: z73.string().describe("Store currency code (e.g., USD, EUR)"),
12575
- timezone: z73.string().describe("Store IANA timezone"),
12576
- contactEmail: z73.string().describe("Store contact email")
13380
+ currencyCode: z77.string().describe("Store currency code (e.g., USD, EUR)"),
13381
+ timezone: z77.string().describe("Store IANA timezone"),
13382
+ contactEmail: z77.string().describe("Store contact email")
12577
13383
  });
12578
13384
  async function handleGetStoreInfo(context, _params) {
12579
13385
  log.debug(`Getting store info for shop: ${context.shopDomain}`);
@@ -12585,8 +13391,8 @@ function registerGetStoreInfoTool() {
12585
13391
  name: "get-store-info",
12586
13392
  title: "Get Store Info",
12587
13393
  description: "Get basic information about the connected Shopify store including name, domain, plan, currency, timezone, and contact email. **Prerequisites:** None. **Use this** to understand store context before performing operations.",
12588
- inputSchema: inputSchema71,
12589
- outputSchema: outputSchema71,
13394
+ inputSchema: inputSchema75,
13395
+ outputSchema: outputSchema75,
12590
13396
  category: "store",
12591
13397
  relationships: {
12592
13398
  relatedTools: [],
@@ -12603,6 +13409,155 @@ function registerGetStoreInfoTool() {
12603
13409
  );
12604
13410
  }
12605
13411
 
13412
+ // src/tools/get-store-limits.ts
13413
+ import { z as z78 } from "zod";
13414
+ var inputSchema76 = z78.object({});
13415
+ var outputSchema76 = z78.object({
13416
+ maxProductVariants: z78.number().describe("Maximum variants per product"),
13417
+ maxProductOptions: z78.number().describe("Maximum product options"),
13418
+ locationLimit: z78.number().describe("Maximum locations"),
13419
+ redirectLimitReached: z78.boolean().describe("Whether redirect limit is reached")
13420
+ });
13421
+ async function handleGetStoreLimits(context, _params) {
13422
+ log.debug(`Getting store limits for shop: ${context.shopDomain}`);
13423
+ return await getStoreLimits();
13424
+ }
13425
+ function registerGetStoreLimitsTool() {
13426
+ registerContextAwareTool(
13427
+ {
13428
+ name: "get-store-limits",
13429
+ title: "Get Store Limits",
13430
+ description: "Get resource limits for the connected Shopify store including max product variants, max product options, location limit, and redirect limit status. **Prerequisites:** None. **Use this** to validate operations against store constraints.",
13431
+ inputSchema: inputSchema76,
13432
+ outputSchema: outputSchema76,
13433
+ category: "store",
13434
+ relationships: {
13435
+ relatedTools: ["get-store-info", "get-store-features"],
13436
+ followUps: ["list-products", "create-product"]
13437
+ },
13438
+ annotations: {
13439
+ readOnlyHint: true,
13440
+ destructiveHint: false,
13441
+ idempotentHint: true,
13442
+ openWorldHint: true
13443
+ }
13444
+ },
13445
+ handleGetStoreLimits
13446
+ );
13447
+ }
13448
+
13449
+ // src/tools/get-store-policies.ts
13450
+ import { z as z79 } from "zod";
13451
+ var inputSchema77 = z79.object({});
13452
+ var outputSchema77 = z79.object({
13453
+ shopPolicies: z79.array(
13454
+ z79.object({
13455
+ title: z79.string().describe('Policy title (e.g., "Privacy Policy")'),
13456
+ type: z79.string().describe('Policy type (e.g., "PRIVACY_POLICY")'),
13457
+ url: z79.string().describe("Full URL to the policy page")
13458
+ })
13459
+ ).describe("Array of store policy items (empty if scope unavailable)")
13460
+ });
13461
+ async function handleGetStorePolicies(context, _params) {
13462
+ log.debug(`Getting store policies for shop: ${context.shopDomain}`);
13463
+ return await getStorePolicies();
13464
+ }
13465
+ function registerGetStorePoliciesTool() {
13466
+ registerContextAwareTool(
13467
+ {
13468
+ name: "get-store-policies",
13469
+ title: "Get Store Policies",
13470
+ description: "Get legal policies for the connected Shopify store (privacy policy, terms of service, refund policy). Returns empty array if read_legal_policies scope is not available. **Prerequisites:** None. **Use this** to reference store policies in customer communications.",
13471
+ inputSchema: inputSchema77,
13472
+ outputSchema: outputSchema77,
13473
+ category: "store",
13474
+ relationships: {
13475
+ relatedTools: ["get-store-info", "get-store-domain"],
13476
+ followUps: []
13477
+ },
13478
+ annotations: {
13479
+ readOnlyHint: true,
13480
+ destructiveHint: false,
13481
+ idempotentHint: true,
13482
+ openWorldHint: true
13483
+ }
13484
+ },
13485
+ handleGetStorePolicies
13486
+ );
13487
+ }
13488
+
13489
+ // src/tools/get-store-shipping.ts
13490
+ import { z as z80 } from "zod";
13491
+ var inputSchema78 = z80.object({});
13492
+ var outputSchema78 = z80.object({
13493
+ shipsToCountries: z80.array(z80.string()).describe("Countries the store ships to"),
13494
+ countriesInShippingZones: z80.object({
13495
+ countryCodes: z80.array(z80.string()).describe("Countries with configured shipping zones")
13496
+ })
13497
+ });
13498
+ async function handleGetStoreShipping(context, _params) {
13499
+ log.debug(`Getting store shipping for shop: ${context.shopDomain}`);
13500
+ return await getStoreShipping();
13501
+ }
13502
+ function registerGetStoreShippingTool() {
13503
+ registerContextAwareTool(
13504
+ {
13505
+ name: "get-store-shipping",
13506
+ title: "Get Store Shipping",
13507
+ description: "Get shipping configuration for the connected Shopify store including ships-to countries and countries with configured shipping zones. **Prerequisites:** None. **Use this** to understand international shipping capabilities.",
13508
+ inputSchema: inputSchema78,
13509
+ outputSchema: outputSchema78,
13510
+ category: "store",
13511
+ relationships: {
13512
+ relatedTools: ["get-store-info", "get-store-domain", "list-markets"],
13513
+ followUps: ["get-store-domain"]
13514
+ },
13515
+ annotations: {
13516
+ readOnlyHint: true,
13517
+ destructiveHint: false,
13518
+ idempotentHint: true,
13519
+ openWorldHint: true
13520
+ }
13521
+ },
13522
+ handleGetStoreShipping
13523
+ );
13524
+ }
13525
+
13526
+ // src/tools/get-store-taxes.ts
13527
+ import { z as z81 } from "zod";
13528
+ var inputSchema79 = z81.object({});
13529
+ var outputSchema79 = z81.object({
13530
+ taxesIncluded: z81.boolean().describe("Whether taxes are included in product prices"),
13531
+ taxShipping: z81.boolean().describe("Whether shipping is taxed")
13532
+ });
13533
+ async function handleGetStoreTaxes(context, _params) {
13534
+ log.debug(`Getting store taxes for shop: ${context.shopDomain}`);
13535
+ return await getStoreTaxes();
13536
+ }
13537
+ function registerGetStoreTaxesTool() {
13538
+ registerContextAwareTool(
13539
+ {
13540
+ name: "get-store-taxes",
13541
+ title: "Get Store Taxes",
13542
+ description: "Get tax configuration for the connected Shopify store including whether taxes are included in prices and tax shipping settings. **Prerequisites:** None. **Use this** to understand pricing structure for tax calculations.",
13543
+ inputSchema: inputSchema79,
13544
+ outputSchema: outputSchema79,
13545
+ category: "store",
13546
+ relationships: {
13547
+ relatedTools: ["get-store-info", "get-store-currencies"],
13548
+ followUps: []
13549
+ },
13550
+ annotations: {
13551
+ readOnlyHint: true,
13552
+ destructiveHint: false,
13553
+ idempotentHint: true,
13554
+ openWorldHint: true
13555
+ }
13556
+ },
13557
+ handleGetStoreTaxes
13558
+ );
13559
+ }
13560
+
12606
13561
  // src/tools/index.ts
12607
13562
  function setupToolHandlers(server) {
12608
13563
  server.server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -12730,6 +13685,14 @@ function registerAllTools(server) {
12730
13685
  registerImportRedirectsTool();
12731
13686
  registerSubmitRedirectImportTool();
12732
13687
  registerGetStoreInfoTool();
13688
+ registerGetStoreLimitsTool();
13689
+ registerGetStoreFeaturesTool();
13690
+ registerGetStoreCurrenciesTool();
13691
+ registerGetStoreShippingTool();
13692
+ registerGetStoreDomainTool();
13693
+ registerGetStoreTaxesTool();
13694
+ registerGetStorePoliciesTool();
13695
+ registerGetStoreAlertsTool();
12733
13696
  const toolCount = getRegisteredTools().length;
12734
13697
  log.debug(`Tool registration complete: ${toolCount} tools registered`);
12735
13698
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anton.andrusenko/shopify-mcp-admin",
3
- "version": "0.7.0",
3
+ "version": "0.8.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",