@anton.andrusenko/shopify-mcp-admin 0.6.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.
- package/README.md +84 -4
- package/dist/index.js +1143 -59
- package/package.json +2 -2
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 ??
|
|
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"
|
|
1570
|
+
},
|
|
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",
|
|
1605
|
+
{
|
|
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
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
);
|
|
1640
|
+
server.resource(
|
|
1641
|
+
"store-policies",
|
|
1642
|
+
"shopify://store/policies",
|
|
1643
|
+
{
|
|
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.",
|
|
1645
|
+
mimeType: "application/json"
|
|
1014
1646
|
},
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1647
|
+
async () => {
|
|
1648
|
+
try {
|
|
1649
|
+
const policies = await getStorePolicies();
|
|
1650
|
+
return {
|
|
1651
|
+
contents: [
|
|
1652
|
+
{
|
|
1653
|
+
uri: "shopify://store/policies",
|
|
1654
|
+
mimeType: "application/json",
|
|
1655
|
+
text: JSON.stringify(policies, null, 2)
|
|
1656
|
+
}
|
|
1657
|
+
]
|
|
1658
|
+
};
|
|
1659
|
+
} catch (error) {
|
|
1660
|
+
log.error("Failed to fetch store policies", error instanceof Error ? error : void 0);
|
|
1661
|
+
return {
|
|
1662
|
+
contents: [
|
|
1663
|
+
{
|
|
1664
|
+
uri: "shopify://store/policies",
|
|
1665
|
+
mimeType: "application/json",
|
|
1666
|
+
text: JSON.stringify({
|
|
1667
|
+
error: "Failed to fetch store policies",
|
|
1668
|
+
message: sanitizeLogMessage(
|
|
1669
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
1670
|
+
)
|
|
1671
|
+
})
|
|
1672
|
+
}
|
|
1673
|
+
]
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1027
1676
|
}
|
|
1028
1677
|
);
|
|
1029
|
-
return server;
|
|
1030
|
-
}
|
|
1031
|
-
function registerResources(server) {
|
|
1032
1678
|
server.resource(
|
|
1033
|
-
"store-
|
|
1034
|
-
"shopify://store/
|
|
1679
|
+
"store-alerts",
|
|
1680
|
+
"shopify://store/alerts",
|
|
1035
1681
|
{
|
|
1036
|
-
description: "
|
|
1682
|
+
description: "Active admin alerts and setup requirements for the Shopify store. Use this to proactively identify issues needing merchant attention.",
|
|
1037
1683
|
mimeType: "application/json"
|
|
1038
1684
|
},
|
|
1039
1685
|
async () => {
|
|
1040
1686
|
try {
|
|
1041
|
-
const
|
|
1687
|
+
const alerts = await getStoreAlerts();
|
|
1042
1688
|
return {
|
|
1043
1689
|
contents: [
|
|
1044
1690
|
{
|
|
1045
|
-
uri: "shopify://store/
|
|
1691
|
+
uri: "shopify://store/alerts",
|
|
1046
1692
|
mimeType: "application/json",
|
|
1047
|
-
text: JSON.stringify(
|
|
1693
|
+
text: JSON.stringify(alerts, null, 2)
|
|
1048
1694
|
}
|
|
1049
1695
|
]
|
|
1050
1696
|
};
|
|
1051
1697
|
} catch (error) {
|
|
1052
|
-
log.error("Failed to fetch store
|
|
1698
|
+
log.error("Failed to fetch store alerts", error instanceof Error ? error : void 0);
|
|
1053
1699
|
return {
|
|
1054
1700
|
contents: [
|
|
1055
1701
|
{
|
|
1056
|
-
uri: "shopify://store/
|
|
1702
|
+
uri: "shopify://store/alerts",
|
|
1057
1703
|
mimeType: "application/json",
|
|
1058
1704
|
text: JSON.stringify({
|
|
1059
|
-
error: "Failed to fetch store
|
|
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:
|
|
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(
|
|
2463
|
-
const wrappedHandler = wrapToolHandler(name,
|
|
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:
|
|
3121
|
+
zodSchema: inputSchema80,
|
|
2476
3122
|
handler: wrappedHandler,
|
|
2477
3123
|
annotations: finalAnnotations
|
|
2478
3124
|
};
|
|
@@ -2648,6 +3294,28 @@ var PRODUCT_VARIANTS_BULK_UPDATE_MUTATION = `
|
|
|
2648
3294
|
}
|
|
2649
3295
|
}
|
|
2650
3296
|
`;
|
|
3297
|
+
var PRODUCT_VARIANTS_BULK_CREATE_MUTATION = `
|
|
3298
|
+
mutation ProductVariantsBulkCreate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
|
|
3299
|
+
productVariantsBulkCreate(productId: $productId, variants: $variants) {
|
|
3300
|
+
product {
|
|
3301
|
+
id
|
|
3302
|
+
}
|
|
3303
|
+
productVariants {
|
|
3304
|
+
id
|
|
3305
|
+
title
|
|
3306
|
+
price
|
|
3307
|
+
compareAtPrice
|
|
3308
|
+
sku
|
|
3309
|
+
barcode
|
|
3310
|
+
inventoryQuantity
|
|
3311
|
+
}
|
|
3312
|
+
userErrors {
|
|
3313
|
+
field
|
|
3314
|
+
message
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
`;
|
|
2651
3319
|
var PRODUCT_SET_MEDIA_MUTATION = `
|
|
2652
3320
|
mutation ProductSetMedia($input: ProductSetInput!) {
|
|
2653
3321
|
productSet(input: $input) {
|
|
@@ -2781,26 +3449,6 @@ function buildProductCreateVariables(input) {
|
|
|
2781
3449
|
if (input.handle !== void 0) {
|
|
2782
3450
|
productData.handle = input.handle;
|
|
2783
3451
|
}
|
|
2784
|
-
if (input.variants && input.variants.length > 0) {
|
|
2785
|
-
productData.variants = input.variants.map((variant) => {
|
|
2786
|
-
const variantInput = {
|
|
2787
|
-
price: variant.price
|
|
2788
|
-
};
|
|
2789
|
-
if (variant.compareAtPrice !== void 0) {
|
|
2790
|
-
variantInput.compareAtPrice = variant.compareAtPrice;
|
|
2791
|
-
}
|
|
2792
|
-
if (variant.sku !== void 0) {
|
|
2793
|
-
variantInput.sku = variant.sku;
|
|
2794
|
-
}
|
|
2795
|
-
if (variant.barcode !== void 0) {
|
|
2796
|
-
variantInput.barcode = variant.barcode;
|
|
2797
|
-
}
|
|
2798
|
-
if (variant.options !== void 0 && variant.options.length > 0) {
|
|
2799
|
-
variantInput.options = variant.options;
|
|
2800
|
-
}
|
|
2801
|
-
return variantInput;
|
|
2802
|
-
});
|
|
2803
|
-
}
|
|
2804
3452
|
let media;
|
|
2805
3453
|
if (input.images && input.images.length > 0) {
|
|
2806
3454
|
media = input.images.map((image) => ({
|
|
@@ -2811,6 +3459,65 @@ function buildProductCreateVariables(input) {
|
|
|
2811
3459
|
}
|
|
2812
3460
|
return { product: productData, media };
|
|
2813
3461
|
}
|
|
3462
|
+
async function createProductVariants(productId, variants) {
|
|
3463
|
+
const client = await getShopifyClient();
|
|
3464
|
+
const variantInputs = variants.map((variant) => {
|
|
3465
|
+
const variantInput = {
|
|
3466
|
+
price: variant.price
|
|
3467
|
+
};
|
|
3468
|
+
if (variant.compareAtPrice !== void 0) {
|
|
3469
|
+
variantInput.compareAtPrice = variant.compareAtPrice;
|
|
3470
|
+
}
|
|
3471
|
+
if (variant.sku !== void 0) {
|
|
3472
|
+
variantInput.sku = variant.sku;
|
|
3473
|
+
}
|
|
3474
|
+
if (variant.barcode !== void 0) {
|
|
3475
|
+
variantInput.barcode = variant.barcode;
|
|
3476
|
+
}
|
|
3477
|
+
if (variant.options !== void 0 && variant.options.length > 0) {
|
|
3478
|
+
variantInput.optionValues = variant.options.map((optionValue) => ({
|
|
3479
|
+
name: optionValue,
|
|
3480
|
+
optionName: optionValue
|
|
3481
|
+
// Use the option value as the option name for simple cases
|
|
3482
|
+
}));
|
|
3483
|
+
}
|
|
3484
|
+
return variantInput;
|
|
3485
|
+
});
|
|
3486
|
+
log.debug(`Creating ${variants.length} variants for product: ${productId}`);
|
|
3487
|
+
const response = await withRateLimit(
|
|
3488
|
+
() => client.graphql.request(
|
|
3489
|
+
PRODUCT_VARIANTS_BULK_CREATE_MUTATION,
|
|
3490
|
+
{
|
|
3491
|
+
variables: { productId, variants: variantInputs }
|
|
3492
|
+
}
|
|
3493
|
+
),
|
|
3494
|
+
"create-product-variants"
|
|
3495
|
+
);
|
|
3496
|
+
if (response.errors && response.errors.length > 0) {
|
|
3497
|
+
const errorMessage = response.errors.map((e) => e.message).join(", ");
|
|
3498
|
+
throw new Error(`GraphQL error: ${errorMessage}`);
|
|
3499
|
+
}
|
|
3500
|
+
const result = response.data?.productVariantsBulkCreate;
|
|
3501
|
+
if (!result) {
|
|
3502
|
+
throw new Error("No response data from productVariantsBulkCreate mutation");
|
|
3503
|
+
}
|
|
3504
|
+
if (result.userErrors && result.userErrors.length > 0) {
|
|
3505
|
+
throw new ShopifyUserErrorException(result.userErrors);
|
|
3506
|
+
}
|
|
3507
|
+
if (!result.productVariants || result.productVariants.length === 0) {
|
|
3508
|
+
throw new Error("No variants were created");
|
|
3509
|
+
}
|
|
3510
|
+
log.debug(`Created ${result.productVariants.length} variants`);
|
|
3511
|
+
return result.productVariants.map((variant) => ({
|
|
3512
|
+
id: variant.id,
|
|
3513
|
+
title: variant.title,
|
|
3514
|
+
price: variant.price,
|
|
3515
|
+
compareAtPrice: variant.compareAtPrice,
|
|
3516
|
+
sku: variant.sku,
|
|
3517
|
+
barcode: variant.barcode,
|
|
3518
|
+
inventoryQuantity: variant.inventoryQuantity
|
|
3519
|
+
}));
|
|
3520
|
+
}
|
|
2814
3521
|
async function createProduct(input) {
|
|
2815
3522
|
const client = await getShopifyClient();
|
|
2816
3523
|
const variables = buildProductCreateVariables(input);
|
|
@@ -2836,7 +3543,23 @@ async function createProduct(input) {
|
|
|
2836
3543
|
throw new Error("Product was not created (no product in response)");
|
|
2837
3544
|
}
|
|
2838
3545
|
log.debug(`Created product: ${result.product.id}`);
|
|
2839
|
-
|
|
3546
|
+
let productOutput = transformProductToOutput(result.product);
|
|
3547
|
+
if (input.variants && input.variants.length > 0) {
|
|
3548
|
+
try {
|
|
3549
|
+
const createdVariants = await createProductVariants(result.product.id, input.variants);
|
|
3550
|
+
productOutput = {
|
|
3551
|
+
...productOutput,
|
|
3552
|
+
variants: createdVariants
|
|
3553
|
+
};
|
|
3554
|
+
log.debug(`Created ${createdVariants.length} variants for product: ${result.product.id}`);
|
|
3555
|
+
} catch (variantError) {
|
|
3556
|
+
log.warn(
|
|
3557
|
+
`Product created but variant creation failed: ${variantError instanceof Error ? variantError.message : "Unknown error"}`
|
|
3558
|
+
);
|
|
3559
|
+
log.warn("Variants can be added using update-product-variant tool");
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
return productOutput;
|
|
2840
3563
|
}
|
|
2841
3564
|
async function getProduct(id) {
|
|
2842
3565
|
const client = await getShopifyClient();
|
|
@@ -5540,10 +6263,10 @@ var inputSchema8 = z10.object({
|
|
|
5540
6263
|
// Variants
|
|
5541
6264
|
variants: z10.array(
|
|
5542
6265
|
z10.object({
|
|
5543
|
-
price: z10.string().describe('Variant price as decimal string. Example: "29.99"'),
|
|
5544
|
-
compareAtPrice: z10.string().optional().describe('Original price for sale display. Example: "39.99"'),
|
|
6266
|
+
price: z10.union([z10.string(), z10.number()]).transform((val) => typeof val === "number" ? String(val) : val).describe('Variant price as decimal string. Example: "29.99"'),
|
|
6267
|
+
compareAtPrice: z10.union([z10.string(), z10.number()]).optional().transform((val) => typeof val === "number" ? String(val) : val).describe('Original price for sale display. Example: "39.99"'),
|
|
5545
6268
|
sku: z10.string().optional().describe('Stock keeping unit. Example: "SHIRT-001-RED-M"'),
|
|
5546
|
-
barcode: z10.string().optional().describe("Barcode (UPC, EAN, etc.)"),
|
|
6269
|
+
barcode: z10.union([z10.string(), z10.number()]).optional().transform((val) => typeof val === "number" ? String(val) : val).describe("Barcode (UPC, EAN, etc.)"),
|
|
5547
6270
|
inventoryQuantity: z10.number().int().min(0).optional().describe("Initial inventory quantity (note: may require separate inventory API)"),
|
|
5548
6271
|
options: z10.array(z10.string()).optional().describe('Variant options. Example: ["Red", "Medium"]')
|
|
5549
6272
|
})
|
|
@@ -10300,11 +11023,11 @@ var inputSchema44 = z46.object({
|
|
|
10300
11023
|
id: variantIdSchema.describe(
|
|
10301
11024
|
'Shopify variant GID (e.g., "gid://shopify/ProductVariant/456"). Required. Use get-product to find variant IDs for a product.'
|
|
10302
11025
|
),
|
|
10303
|
-
price: z46.string().optional().describe('New variant price as decimal string (e.g., "29.99")'),
|
|
10304
|
-
compareAtPrice: z46.string().nullable().optional().describe(
|
|
11026
|
+
price: z46.union([z46.string(), z46.number()]).optional().transform((val) => typeof val === "number" ? String(val) : val).describe('New variant price as decimal string (e.g., "29.99")'),
|
|
11027
|
+
compareAtPrice: z46.union([z46.string(), z46.number()]).nullable().optional().transform((val) => typeof val === "number" ? String(val) : val).describe(
|
|
10305
11028
|
'Original price for sale display (e.g., "39.99"). When set higher than price, Shopify shows strikethrough pricing. Set to null to remove the compare at price.'
|
|
10306
11029
|
),
|
|
10307
|
-
barcode: z46.string().nullable().optional().describe("Barcode (UPC, EAN, ISBN, etc.). Set to null to remove.")
|
|
11030
|
+
barcode: z46.union([z46.string(), z46.number()]).nullable().optional().transform((val) => typeof val === "number" ? String(val) : val).describe("Barcode (UPC, EAN, ISBN, etc.). Set to null to remove.")
|
|
10308
11031
|
}).refine(
|
|
10309
11032
|
(data) => {
|
|
10310
11033
|
const { productId: _productId, id: _id, ...updateFields } = data;
|
|
@@ -12483,6 +13206,358 @@ function registerSubmitRedirectImportTool() {
|
|
|
12483
13206
|
);
|
|
12484
13207
|
}
|
|
12485
13208
|
|
|
13209
|
+
// src/tools/get-store-alerts.ts
|
|
13210
|
+
import { z as z73 } from "zod";
|
|
13211
|
+
var inputSchema71 = z73.object({});
|
|
13212
|
+
var outputSchema71 = z73.object({
|
|
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")
|
|
13379
|
+
}).describe("Store plan details"),
|
|
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")
|
|
13383
|
+
});
|
|
13384
|
+
async function handleGetStoreInfo(context, _params) {
|
|
13385
|
+
log.debug(`Getting store info for shop: ${context.shopDomain}`);
|
|
13386
|
+
return await getStoreInfo();
|
|
13387
|
+
}
|
|
13388
|
+
function registerGetStoreInfoTool() {
|
|
13389
|
+
registerContextAwareTool(
|
|
13390
|
+
{
|
|
13391
|
+
name: "get-store-info",
|
|
13392
|
+
title: "Get Store Info",
|
|
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.",
|
|
13394
|
+
inputSchema: inputSchema75,
|
|
13395
|
+
outputSchema: outputSchema75,
|
|
13396
|
+
category: "store",
|
|
13397
|
+
relationships: {
|
|
13398
|
+
relatedTools: [],
|
|
13399
|
+
followUps: ["list-products", "list-collections"]
|
|
13400
|
+
},
|
|
13401
|
+
annotations: {
|
|
13402
|
+
readOnlyHint: true,
|
|
13403
|
+
destructiveHint: false,
|
|
13404
|
+
idempotentHint: true,
|
|
13405
|
+
openWorldHint: true
|
|
13406
|
+
}
|
|
13407
|
+
},
|
|
13408
|
+
handleGetStoreInfo
|
|
13409
|
+
);
|
|
13410
|
+
}
|
|
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
|
+
|
|
12486
13561
|
// src/tools/index.ts
|
|
12487
13562
|
function setupToolHandlers(server) {
|
|
12488
13563
|
server.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -12609,6 +13684,15 @@ function registerAllTools(server) {
|
|
|
12609
13684
|
registerBulkDeleteRedirectsBySearchTool();
|
|
12610
13685
|
registerImportRedirectsTool();
|
|
12611
13686
|
registerSubmitRedirectImportTool();
|
|
13687
|
+
registerGetStoreInfoTool();
|
|
13688
|
+
registerGetStoreLimitsTool();
|
|
13689
|
+
registerGetStoreFeaturesTool();
|
|
13690
|
+
registerGetStoreCurrenciesTool();
|
|
13691
|
+
registerGetStoreShippingTool();
|
|
13692
|
+
registerGetStoreDomainTool();
|
|
13693
|
+
registerGetStoreTaxesTool();
|
|
13694
|
+
registerGetStorePoliciesTool();
|
|
13695
|
+
registerGetStoreAlertsTool();
|
|
12612
13696
|
const toolCount = getRegisteredTools().length;
|
|
12613
13697
|
log.debug(`Tool registration complete: ${toolCount} tools registered`);
|
|
12614
13698
|
}
|