@open-loyalty/mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +654 -0
  3. package/dist/client/http.d.ts +8 -0
  4. package/dist/client/http.js +69 -0
  5. package/dist/config.d.ts +17 -0
  6. package/dist/config.js +40 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +20 -0
  9. package/dist/server.d.ts +4 -0
  10. package/dist/server.js +334 -0
  11. package/dist/tools/achievement.d.ts +983 -0
  12. package/dist/tools/achievement.js +311 -0
  13. package/dist/tools/admin.d.ts +153 -0
  14. package/dist/tools/admin.js +193 -0
  15. package/dist/tools/analytics.d.ts +162 -0
  16. package/dist/tools/analytics.js +245 -0
  17. package/dist/tools/apikey.d.ts +72 -0
  18. package/dist/tools/apikey.js +78 -0
  19. package/dist/tools/audit.d.ts +107 -0
  20. package/dist/tools/audit.js +90 -0
  21. package/dist/tools/badge.d.ts +135 -0
  22. package/dist/tools/badge.js +165 -0
  23. package/dist/tools/campaign.d.ts +1775 -0
  24. package/dist/tools/campaign.js +724 -0
  25. package/dist/tools/export.d.ts +110 -0
  26. package/dist/tools/export.js +147 -0
  27. package/dist/tools/import.d.ts +110 -0
  28. package/dist/tools/import.js +126 -0
  29. package/dist/tools/index.d.ts +22 -0
  30. package/dist/tools/index.js +527 -0
  31. package/dist/tools/member.d.ts +345 -0
  32. package/dist/tools/member.js +358 -0
  33. package/dist/tools/member.test.d.ts +1 -0
  34. package/dist/tools/member.test.js +213 -0
  35. package/dist/tools/points.d.ts +188 -0
  36. package/dist/tools/points.js +306 -0
  37. package/dist/tools/points.test.d.ts +1 -0
  38. package/dist/tools/points.test.js +292 -0
  39. package/dist/tools/reward.d.ts +261 -0
  40. package/dist/tools/reward.js +371 -0
  41. package/dist/tools/reward.test.d.ts +1 -0
  42. package/dist/tools/reward.test.js +240 -0
  43. package/dist/tools/role.d.ts +161 -0
  44. package/dist/tools/role.js +160 -0
  45. package/dist/tools/segment.d.ts +797 -0
  46. package/dist/tools/segment.js +299 -0
  47. package/dist/tools/store.d.ts +101 -0
  48. package/dist/tools/store.js +117 -0
  49. package/dist/tools/tierset.d.ts +288 -0
  50. package/dist/tools/tierset.js +244 -0
  51. package/dist/tools/transaction.d.ts +357 -0
  52. package/dist/tools/transaction.js +242 -0
  53. package/dist/tools/transaction.test.d.ts +1 -0
  54. package/dist/tools/transaction.test.js +235 -0
  55. package/dist/tools/wallet-type.d.ts +32 -0
  56. package/dist/tools/wallet-type.js +58 -0
  57. package/dist/tools/webhook.d.ts +179 -0
  58. package/dist/tools/webhook.js +171 -0
  59. package/dist/types/schemas/achievement.d.ts +1116 -0
  60. package/dist/types/schemas/achievement.js +172 -0
  61. package/dist/types/schemas/admin.d.ts +263 -0
  62. package/dist/types/schemas/admin.js +99 -0
  63. package/dist/types/schemas/analytics.d.ts +542 -0
  64. package/dist/types/schemas/analytics.js +130 -0
  65. package/dist/types/schemas/badge.d.ts +131 -0
  66. package/dist/types/schemas/badge.js +48 -0
  67. package/dist/types/schemas/campaign.d.ts +2005 -0
  68. package/dist/types/schemas/campaign.js +189 -0
  69. package/dist/types/schemas/common.d.ts +52 -0
  70. package/dist/types/schemas/common.js +26 -0
  71. package/dist/types/schemas/export.d.ts +127 -0
  72. package/dist/types/schemas/export.js +43 -0
  73. package/dist/types/schemas/import.d.ts +344 -0
  74. package/dist/types/schemas/import.js +68 -0
  75. package/dist/types/schemas/member.d.ts +443 -0
  76. package/dist/types/schemas/member.js +92 -0
  77. package/dist/types/schemas/points.d.ts +188 -0
  78. package/dist/types/schemas/points.js +54 -0
  79. package/dist/types/schemas/reward.d.ts +278 -0
  80. package/dist/types/schemas/reward.js +69 -0
  81. package/dist/types/schemas/role.d.ts +260 -0
  82. package/dist/types/schemas/role.js +75 -0
  83. package/dist/types/schemas/segment.d.ts +592 -0
  84. package/dist/types/schemas/segment.js +114 -0
  85. package/dist/types/schemas/tierset.d.ts +552 -0
  86. package/dist/types/schemas/tierset.js +87 -0
  87. package/dist/types/schemas/transaction.d.ts +1022 -0
  88. package/dist/types/schemas/transaction.js +63 -0
  89. package/dist/types/schemas/wallet-type.d.ts +99 -0
  90. package/dist/types/schemas/wallet-type.js +17 -0
  91. package/dist/types/schemas/webhook.d.ts +195 -0
  92. package/dist/types/schemas/webhook.js +39 -0
  93. package/dist/utils/cursor.d.ts +84 -0
  94. package/dist/utils/cursor.js +117 -0
  95. package/dist/utils/errors.d.ts +12 -0
  96. package/dist/utils/errors.js +69 -0
  97. package/dist/utils/pagination.d.ts +39 -0
  98. package/dist/utils/pagination.js +77 -0
  99. package/package.json +65 -0
@@ -0,0 +1,288 @@
1
+ import { z } from "zod";
2
+ import { TierSet, TierSetListItem, Tier } from "../types/schemas/tierset.js";
3
+ export declare const TierSetListInputSchema: {
4
+ storeCode: z.ZodOptional<z.ZodString>;
5
+ page: z.ZodOptional<z.ZodNumber>;
6
+ perPage: z.ZodOptional<z.ZodNumber>;
7
+ };
8
+ export declare const TierSetCreateInputSchema: {
9
+ storeCode: z.ZodOptional<z.ZodString>;
10
+ name: z.ZodString;
11
+ description: z.ZodOptional<z.ZodString>;
12
+ conditions: z.ZodArray<z.ZodObject<{
13
+ attribute: z.ZodEnum<["activeUnits", "totalEarnedUnits", "totalSpending", "monthsSinceJoiningProgram", "cumulatedEarnedUnits"]>;
14
+ walletType: z.ZodOptional<z.ZodString>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ attribute: "activeUnits" | "totalEarnedUnits" | "totalSpending" | "monthsSinceJoiningProgram" | "cumulatedEarnedUnits";
17
+ walletType?: string | undefined;
18
+ }, {
19
+ attribute: "activeUnits" | "totalEarnedUnits" | "totalSpending" | "monthsSinceJoiningProgram" | "cumulatedEarnedUnits";
20
+ walletType?: string | undefined;
21
+ }>, "many">;
22
+ downgrade: z.ZodOptional<z.ZodObject<{
23
+ mode: z.ZodEnum<["none", "automatic", "x_days"]>;
24
+ days: z.ZodOptional<z.ZodNumber>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ mode: "none" | "automatic" | "x_days";
27
+ days?: number | undefined;
28
+ }, {
29
+ mode: "none" | "automatic" | "x_days";
30
+ days?: number | undefined;
31
+ }>>;
32
+ active: z.ZodOptional<z.ZodBoolean>;
33
+ };
34
+ export declare const TierSetGetInputSchema: {
35
+ storeCode: z.ZodOptional<z.ZodString>;
36
+ tierSetId: z.ZodString;
37
+ };
38
+ export declare const TierSetUpdateInputSchema: {
39
+ storeCode: z.ZodOptional<z.ZodString>;
40
+ tierSetId: z.ZodString;
41
+ name: z.ZodOptional<z.ZodString>;
42
+ description: z.ZodOptional<z.ZodString>;
43
+ active: z.ZodOptional<z.ZodBoolean>;
44
+ downgrade: z.ZodOptional<z.ZodObject<{
45
+ mode: z.ZodEnum<["none", "automatic", "x_days"]>;
46
+ days: z.ZodOptional<z.ZodNumber>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ mode: "none" | "automatic" | "x_days";
49
+ days?: number | undefined;
50
+ }, {
51
+ mode: "none" | "automatic" | "x_days";
52
+ days?: number | undefined;
53
+ }>>;
54
+ };
55
+ export declare const TierSetUpdateTiersInputSchema: {
56
+ storeCode: z.ZodOptional<z.ZodString>;
57
+ tierSetId: z.ZodString;
58
+ tiers: z.ZodArray<z.ZodObject<{
59
+ levelId: z.ZodOptional<z.ZodString>;
60
+ name: z.ZodString;
61
+ description: z.ZodOptional<z.ZodString>;
62
+ active: z.ZodOptional<z.ZodBoolean>;
63
+ conditions: z.ZodArray<z.ZodObject<{
64
+ conditionId: z.ZodString;
65
+ value: z.ZodNumber;
66
+ }, "strip", z.ZodTypeAny, {
67
+ value: number;
68
+ conditionId: string;
69
+ }, {
70
+ value: number;
71
+ conditionId: string;
72
+ }>, "many">;
73
+ }, "strip", z.ZodTypeAny, {
74
+ name: string;
75
+ conditions: {
76
+ value: number;
77
+ conditionId: string;
78
+ }[];
79
+ active?: boolean | undefined;
80
+ description?: string | undefined;
81
+ levelId?: string | undefined;
82
+ }, {
83
+ name: string;
84
+ conditions: {
85
+ value: number;
86
+ conditionId: string;
87
+ }[];
88
+ active?: boolean | undefined;
89
+ description?: string | undefined;
90
+ levelId?: string | undefined;
91
+ }>, "many">;
92
+ };
93
+ export declare const TierSetGetTiersInputSchema: {
94
+ storeCode: z.ZodOptional<z.ZodString>;
95
+ tierSetId: z.ZodString;
96
+ };
97
+ type TierSetListInput = {
98
+ storeCode?: string;
99
+ page?: number;
100
+ perPage?: number;
101
+ };
102
+ type TierSetCreateInput = {
103
+ storeCode?: string;
104
+ name: string;
105
+ description?: string;
106
+ conditions: {
107
+ attribute: string;
108
+ walletType?: string;
109
+ }[];
110
+ downgrade?: {
111
+ mode: string;
112
+ days?: number;
113
+ };
114
+ active?: boolean;
115
+ };
116
+ type TierSetGetInput = {
117
+ storeCode?: string;
118
+ tierSetId: string;
119
+ };
120
+ type TierSetUpdateInput = {
121
+ storeCode?: string;
122
+ tierSetId: string;
123
+ name?: string;
124
+ description?: string;
125
+ active?: boolean;
126
+ downgrade?: {
127
+ mode: string;
128
+ days?: number;
129
+ };
130
+ };
131
+ type TierSetUpdateTiersInput = {
132
+ storeCode?: string;
133
+ tierSetId: string;
134
+ tiers: {
135
+ levelId?: string;
136
+ name: string;
137
+ description?: string;
138
+ active?: boolean;
139
+ conditions: {
140
+ conditionId: string;
141
+ value: number;
142
+ }[];
143
+ }[];
144
+ };
145
+ export declare function tiersetList(input: TierSetListInput): Promise<{
146
+ items: TierSetListItem[];
147
+ total: {
148
+ all?: number;
149
+ filtered?: number;
150
+ };
151
+ }>;
152
+ export declare function tiersetCreate(input: TierSetCreateInput): Promise<{
153
+ tierSetId: string;
154
+ conditions: {
155
+ conditionId: string;
156
+ attribute: string;
157
+ }[];
158
+ }>;
159
+ export declare function tiersetGet(input: TierSetGetInput): Promise<TierSet>;
160
+ export declare function tiersetUpdate(input: TierSetUpdateInput): Promise<void>;
161
+ export declare function tiersetUpdateTiers(input: TierSetUpdateTiersInput): Promise<void>;
162
+ export declare function tiersetGetTiers(input: TierSetGetInput): Promise<{
163
+ items: Tier[];
164
+ total: {
165
+ all?: number;
166
+ filtered?: number;
167
+ };
168
+ }>;
169
+ export declare const tiersetToolDefinitions: readonly [{
170
+ readonly name: "openloyalty_tierset_list";
171
+ readonly description: "List all tier sets. Use tierset_get to fetch conditions needed for defining tiers. Returns tierSetId, name, active status, and tier count for each tier set.";
172
+ readonly inputSchema: {
173
+ storeCode: z.ZodOptional<z.ZodString>;
174
+ page: z.ZodOptional<z.ZodNumber>;
175
+ perPage: z.ZodOptional<z.ZodNumber>;
176
+ };
177
+ readonly handler: typeof tiersetList;
178
+ }, {
179
+ readonly name: "openloyalty_tierset_create";
180
+ readonly description: "Create a new tier set (loyalty program structure). After creation, call tierset_get to obtain conditionId values, then tierset_update_tiers to define tier thresholds. Conditions define what metrics are used for tier progression (e.g., activeUnits for points balance).";
181
+ readonly inputSchema: {
182
+ storeCode: z.ZodOptional<z.ZodString>;
183
+ name: z.ZodString;
184
+ description: z.ZodOptional<z.ZodString>;
185
+ conditions: z.ZodArray<z.ZodObject<{
186
+ attribute: z.ZodEnum<["activeUnits", "totalEarnedUnits", "totalSpending", "monthsSinceJoiningProgram", "cumulatedEarnedUnits"]>;
187
+ walletType: z.ZodOptional<z.ZodString>;
188
+ }, "strip", z.ZodTypeAny, {
189
+ attribute: "activeUnits" | "totalEarnedUnits" | "totalSpending" | "monthsSinceJoiningProgram" | "cumulatedEarnedUnits";
190
+ walletType?: string | undefined;
191
+ }, {
192
+ attribute: "activeUnits" | "totalEarnedUnits" | "totalSpending" | "monthsSinceJoiningProgram" | "cumulatedEarnedUnits";
193
+ walletType?: string | undefined;
194
+ }>, "many">;
195
+ downgrade: z.ZodOptional<z.ZodObject<{
196
+ mode: z.ZodEnum<["none", "automatic", "x_days"]>;
197
+ days: z.ZodOptional<z.ZodNumber>;
198
+ }, "strip", z.ZodTypeAny, {
199
+ mode: "none" | "automatic" | "x_days";
200
+ days?: number | undefined;
201
+ }, {
202
+ mode: "none" | "automatic" | "x_days";
203
+ days?: number | undefined;
204
+ }>>;
205
+ active: z.ZodOptional<z.ZodBoolean>;
206
+ };
207
+ readonly handler: typeof tiersetCreate;
208
+ }, {
209
+ readonly name: "openloyalty_tierset_get";
210
+ readonly description: "Get tier set details including conditionId values needed for tierset_update_tiers. Returns the full tier set with conditions array containing conditionId for each condition.";
211
+ readonly inputSchema: {
212
+ storeCode: z.ZodOptional<z.ZodString>;
213
+ tierSetId: z.ZodString;
214
+ };
215
+ readonly handler: typeof tiersetGet;
216
+ }, {
217
+ readonly name: "openloyalty_tierset_update";
218
+ readonly description: "Update tier set metadata (name, description, active status, downgrade settings). Does not modify tiers - use tierset_update_tiers for that.";
219
+ readonly inputSchema: {
220
+ storeCode: z.ZodOptional<z.ZodString>;
221
+ tierSetId: z.ZodString;
222
+ name: z.ZodOptional<z.ZodString>;
223
+ description: z.ZodOptional<z.ZodString>;
224
+ active: z.ZodOptional<z.ZodBoolean>;
225
+ downgrade: z.ZodOptional<z.ZodObject<{
226
+ mode: z.ZodEnum<["none", "automatic", "x_days"]>;
227
+ days: z.ZodOptional<z.ZodNumber>;
228
+ }, "strip", z.ZodTypeAny, {
229
+ mode: "none" | "automatic" | "x_days";
230
+ days?: number | undefined;
231
+ }, {
232
+ mode: "none" | "automatic" | "x_days";
233
+ days?: number | undefined;
234
+ }>>;
235
+ };
236
+ readonly handler: typeof tiersetUpdate;
237
+ }, {
238
+ readonly name: "openloyalty_tierset_update_tiers";
239
+ readonly description: "Define tier thresholds for a tier set. PREREQUISITE: Call tierset_get first to obtain conditionId values. Each tier's conditions array uses conditionId from the parent tier set plus a threshold value.\n\nExample for a 3-tier program with points-based progression:\n- Bronze tier: conditions: [{ conditionId: \"xxx\", value: 400 }]\n- Silver tier: conditions: [{ conditionId: \"xxx\", value: 800 }]\n- Gold tier: conditions: [{ conditionId: \"xxx\", value: 1200 }]\n\nThe conditionId must match one from tierset_get response.";
240
+ readonly inputSchema: {
241
+ storeCode: z.ZodOptional<z.ZodString>;
242
+ tierSetId: z.ZodString;
243
+ tiers: z.ZodArray<z.ZodObject<{
244
+ levelId: z.ZodOptional<z.ZodString>;
245
+ name: z.ZodString;
246
+ description: z.ZodOptional<z.ZodString>;
247
+ active: z.ZodOptional<z.ZodBoolean>;
248
+ conditions: z.ZodArray<z.ZodObject<{
249
+ conditionId: z.ZodString;
250
+ value: z.ZodNumber;
251
+ }, "strip", z.ZodTypeAny, {
252
+ value: number;
253
+ conditionId: string;
254
+ }, {
255
+ value: number;
256
+ conditionId: string;
257
+ }>, "many">;
258
+ }, "strip", z.ZodTypeAny, {
259
+ name: string;
260
+ conditions: {
261
+ value: number;
262
+ conditionId: string;
263
+ }[];
264
+ active?: boolean | undefined;
265
+ description?: string | undefined;
266
+ levelId?: string | undefined;
267
+ }, {
268
+ name: string;
269
+ conditions: {
270
+ value: number;
271
+ conditionId: string;
272
+ }[];
273
+ active?: boolean | undefined;
274
+ description?: string | undefined;
275
+ levelId?: string | undefined;
276
+ }>, "many">;
277
+ };
278
+ readonly handler: typeof tiersetUpdateTiers;
279
+ }, {
280
+ readonly name: "openloyalty_tierset_get_tiers";
281
+ readonly description: "Get all tiers in a tier set. Returns levelId values that can be used for campaign targeting. Includes each tier's name and condition thresholds.";
282
+ readonly inputSchema: {
283
+ storeCode: z.ZodOptional<z.ZodString>;
284
+ tierSetId: z.ZodString;
285
+ };
286
+ readonly handler: typeof tiersetGetTiers;
287
+ }];
288
+ export {};
@@ -0,0 +1,244 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPost, apiPut } from "../client/http.js";
3
+ import { TierSetSchema, TierSetListResponseSchema, TierListResponseSchema, TierSetAttributeEnum, DowngradeModeEnum, } from "../types/schemas/tierset.js";
4
+ import { formatApiError } from "../utils/errors.js";
5
+ import { getConfig } from "../config.js";
6
+ import { buildPaginationQuery } from "../utils/pagination.js";
7
+ export const TierSetListInputSchema = {
8
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
9
+ page: z.number().optional().describe("Page number for pagination (starts at 1)."),
10
+ perPage: z.number().optional().describe("Number of items per page."),
11
+ };
12
+ export const TierSetCreateInputSchema = {
13
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
14
+ name: z.string().describe("Name of the tier set."),
15
+ description: z.string().optional().describe("Description of the tier set."),
16
+ conditions: z.array(z.object({
17
+ attribute: TierSetAttributeEnum.describe("The attribute to use for this condition."),
18
+ walletType: z.string().optional().describe("Wallet type code (required for unit-based attributes like activeUnits). Get this from wallet_type_list."),
19
+ })).describe("Array of conditions that define tier progression criteria."),
20
+ downgrade: z.object({
21
+ mode: DowngradeModeEnum.describe("Downgrade mode."),
22
+ days: z.number().optional().describe("Number of days for x_days mode (required if mode is x_days)."),
23
+ }).optional().describe("Downgrade configuration for the tier set."),
24
+ active: z.boolean().optional().describe("Whether the tier set is active. Defaults to true."),
25
+ };
26
+ export const TierSetGetInputSchema = {
27
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
28
+ tierSetId: z.string().describe("The tier set ID to retrieve."),
29
+ };
30
+ export const TierSetUpdateInputSchema = {
31
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
32
+ tierSetId: z.string().describe("The tier set ID to update."),
33
+ name: z.string().optional().describe("New name for the tier set."),
34
+ description: z.string().optional().describe("New description for the tier set."),
35
+ active: z.boolean().optional().describe("Whether the tier set is active."),
36
+ downgrade: z.object({
37
+ mode: DowngradeModeEnum.describe("Downgrade mode."),
38
+ days: z.number().optional().describe("Number of days for x_days mode."),
39
+ }).optional().describe("Downgrade configuration."),
40
+ };
41
+ export const TierSetUpdateTiersInputSchema = {
42
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
43
+ tierSetId: z.string().describe("The tier set ID to update tiers for."),
44
+ tiers: z.array(z.object({
45
+ levelId: z.string().optional().describe("Existing level ID (for updates). Omit for new tiers."),
46
+ name: z.string().describe("Name of the tier (e.g., Bronze, Silver, Gold)."),
47
+ description: z.string().optional().describe("Description of the tier."),
48
+ active: z.boolean().optional().describe("Whether the tier is active. Defaults to true."),
49
+ conditions: z.array(z.object({
50
+ conditionId: z.string().describe("Condition ID from tierset_get response."),
51
+ value: z.number().describe("Threshold value for this condition (e.g., 400 points for Bronze)."),
52
+ })).describe("Array of condition thresholds. Each uses conditionId from tierset_get."),
53
+ })).describe("Array of tier definitions."),
54
+ };
55
+ export const TierSetGetTiersInputSchema = {
56
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
57
+ tierSetId: z.string().describe("The tier set ID to get tiers for."),
58
+ };
59
+ export async function tiersetList(input) {
60
+ const config = getConfig();
61
+ const storeCode = input.storeCode || config.defaultStoreCode;
62
+ const query = buildPaginationQuery({
63
+ page: input.page,
64
+ perPage: input.perPage,
65
+ });
66
+ try {
67
+ const response = await apiGet(`/${storeCode}/tierSet${query}`);
68
+ const validated = TierSetListResponseSchema.parse(response);
69
+ return {
70
+ items: validated.items.map((ts) => ({
71
+ tierSetId: ts.tierSetId,
72
+ name: ts.name,
73
+ active: ts.active,
74
+ tiersCount: ts.tiersCount,
75
+ })),
76
+ total: {
77
+ all: typeof validated.total.all === 'number' ? validated.total.all : undefined,
78
+ filtered: typeof validated.total.filtered === 'number' ? validated.total.filtered : undefined,
79
+ },
80
+ };
81
+ }
82
+ catch (error) {
83
+ throw formatApiError(error, "openloyalty_tierset_list");
84
+ }
85
+ }
86
+ export async function tiersetCreate(input) {
87
+ const config = getConfig();
88
+ const storeCode = input.storeCode || config.defaultStoreCode;
89
+ // API requires tierSet wrapper with translations (at least en is required)
90
+ const payload = {
91
+ tierSet: {
92
+ translations: {
93
+ en: {
94
+ name: input.name,
95
+ description: input.description || "",
96
+ },
97
+ },
98
+ conditions: input.conditions,
99
+ downgrade: input.downgrade,
100
+ active: input.active ?? true,
101
+ },
102
+ };
103
+ try {
104
+ const response = await apiPost(`/${storeCode}/tierSet`, payload);
105
+ const validated = TierSetSchema.parse(response);
106
+ return {
107
+ tierSetId: validated.tierSetId,
108
+ conditions: validated.conditions.map((c) => ({
109
+ conditionId: c.id,
110
+ attribute: c.attribute,
111
+ })),
112
+ };
113
+ }
114
+ catch (error) {
115
+ throw formatApiError(error, "openloyalty_tierset_create");
116
+ }
117
+ }
118
+ export async function tiersetGet(input) {
119
+ const config = getConfig();
120
+ const storeCode = input.storeCode || config.defaultStoreCode;
121
+ try {
122
+ const response = await apiGet(`/${storeCode}/tierSet/${input.tierSetId}`);
123
+ const validated = TierSetSchema.parse(response);
124
+ return validated;
125
+ }
126
+ catch (error) {
127
+ throw formatApiError(error, "openloyalty_tierset_get");
128
+ }
129
+ }
130
+ export async function tiersetUpdate(input) {
131
+ const config = getConfig();
132
+ const storeCode = input.storeCode || config.defaultStoreCode;
133
+ // API requires tierSet wrapper with translations (at least en is required)
134
+ const tierSetPayload = {};
135
+ // If name or description is provided, wrap in translations
136
+ if (input.name !== undefined || input.description !== undefined) {
137
+ tierSetPayload.translations = {
138
+ en: {
139
+ name: input.name || "",
140
+ description: input.description || "",
141
+ },
142
+ };
143
+ }
144
+ if (input.active !== undefined)
145
+ tierSetPayload.active = input.active;
146
+ if (input.downgrade !== undefined)
147
+ tierSetPayload.downgrade = input.downgrade;
148
+ try {
149
+ await apiPut(`/${storeCode}/tierSet/${input.tierSetId}`, { tierSet: tierSetPayload });
150
+ }
151
+ catch (error) {
152
+ throw formatApiError(error, "openloyalty_tierset_update");
153
+ }
154
+ }
155
+ export async function tiersetUpdateTiers(input) {
156
+ const config = getConfig();
157
+ const storeCode = input.storeCode || config.defaultStoreCode;
158
+ // API requires translations (at least en is required)
159
+ const payload = {
160
+ tiers: input.tiers.map((tier) => ({
161
+ levelId: tier.levelId,
162
+ active: tier.active ?? true,
163
+ conditions: tier.conditions.map((c) => ({
164
+ conditionId: c.conditionId,
165
+ value: c.value,
166
+ })),
167
+ translations: {
168
+ en: {
169
+ name: tier.name,
170
+ description: tier.description || "",
171
+ },
172
+ },
173
+ })),
174
+ };
175
+ try {
176
+ await apiPut(`/${storeCode}/tierSet/${input.tierSetId}/tiers`, payload);
177
+ }
178
+ catch (error) {
179
+ throw formatApiError(error, "openloyalty_tierset_update_tiers");
180
+ }
181
+ }
182
+ export async function tiersetGetTiers(input) {
183
+ const config = getConfig();
184
+ const storeCode = input.storeCode || config.defaultStoreCode;
185
+ try {
186
+ const response = await apiGet(`/${storeCode}/tierSet/${input.tierSetId}/tiers`);
187
+ const validated = TierListResponseSchema.parse(response);
188
+ return {
189
+ items: validated.items,
190
+ total: {
191
+ all: typeof validated.total.all === 'number' ? validated.total.all : undefined,
192
+ filtered: typeof validated.total.filtered === 'number' ? validated.total.filtered : undefined,
193
+ },
194
+ };
195
+ }
196
+ catch (error) {
197
+ throw formatApiError(error, "openloyalty_tierset_get_tiers");
198
+ }
199
+ }
200
+ export const tiersetToolDefinitions = [
201
+ {
202
+ name: "openloyalty_tierset_list",
203
+ description: "List all tier sets. Use tierset_get to fetch conditions needed for defining tiers. Returns tierSetId, name, active status, and tier count for each tier set.",
204
+ inputSchema: TierSetListInputSchema,
205
+ handler: tiersetList,
206
+ },
207
+ {
208
+ name: "openloyalty_tierset_create",
209
+ description: "Create a new tier set (loyalty program structure). After creation, call tierset_get to obtain conditionId values, then tierset_update_tiers to define tier thresholds. Conditions define what metrics are used for tier progression (e.g., activeUnits for points balance).",
210
+ inputSchema: TierSetCreateInputSchema,
211
+ handler: tiersetCreate,
212
+ },
213
+ {
214
+ name: "openloyalty_tierset_get",
215
+ description: "Get tier set details including conditionId values needed for tierset_update_tiers. Returns the full tier set with conditions array containing conditionId for each condition.",
216
+ inputSchema: TierSetGetInputSchema,
217
+ handler: tiersetGet,
218
+ },
219
+ {
220
+ name: "openloyalty_tierset_update",
221
+ description: "Update tier set metadata (name, description, active status, downgrade settings). Does not modify tiers - use tierset_update_tiers for that.",
222
+ inputSchema: TierSetUpdateInputSchema,
223
+ handler: tiersetUpdate,
224
+ },
225
+ {
226
+ name: "openloyalty_tierset_update_tiers",
227
+ description: `Define tier thresholds for a tier set. PREREQUISITE: Call tierset_get first to obtain conditionId values. Each tier's conditions array uses conditionId from the parent tier set plus a threshold value.
228
+
229
+ Example for a 3-tier program with points-based progression:
230
+ - Bronze tier: conditions: [{ conditionId: "xxx", value: 400 }]
231
+ - Silver tier: conditions: [{ conditionId: "xxx", value: 800 }]
232
+ - Gold tier: conditions: [{ conditionId: "xxx", value: 1200 }]
233
+
234
+ The conditionId must match one from tierset_get response.`,
235
+ inputSchema: TierSetUpdateTiersInputSchema,
236
+ handler: tiersetUpdateTiers,
237
+ },
238
+ {
239
+ name: "openloyalty_tierset_get_tiers",
240
+ description: "Get all tiers in a tier set. Returns levelId values that can be used for campaign targeting. Includes each tier's name and condition thresholds.",
241
+ inputSchema: TierSetGetTiersInputSchema,
242
+ handler: tiersetGetTiers,
243
+ },
244
+ ];