@open-loyalty/mcp-server 1.3.6 → 1.4.1

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 (42) hide show
  1. package/dist/instructions.d.ts +1 -1
  2. package/dist/instructions.js +18 -5
  3. package/dist/tools/achievement/index.js +10 -10
  4. package/dist/tools/achievement/schemas.js +16 -8
  5. package/dist/tools/reward/handlers.d.ts +3 -3
  6. package/dist/tools/reward/handlers.js +54 -8
  7. package/dist/tools/reward/index.d.ts +4 -8
  8. package/dist/tools/reward/index.js +13 -5
  9. package/dist/tools/reward/schemas.d.ts +3 -7
  10. package/dist/tools/reward/schemas.js +16 -8
  11. package/dist/tools/tierset.d.ts +1 -1
  12. package/dist/tools/tierset.js +49 -25
  13. package/dist/tools/transaction.js +5 -2
  14. package/dist/tools/wallet-type.js +27 -16
  15. package/dist/types/schemas/admin.d.ts +6 -6
  16. package/dist/types/schemas/role.d.ts +4 -4
  17. package/dist/types/schemas/wallet-type.js +7 -5
  18. package/package.json +1 -1
  19. package/dist/prompts/fan-engagement-setup.d.ts +0 -107
  20. package/dist/prompts/fan-engagement-setup.js +0 -492
  21. package/dist/tools/achievement.d.ts +0 -1017
  22. package/dist/tools/achievement.js +0 -354
  23. package/dist/tools/campaign.d.ts +0 -1800
  24. package/dist/tools/campaign.js +0 -737
  25. package/dist/tools/member.d.ts +0 -366
  26. package/dist/tools/member.js +0 -352
  27. package/dist/tools/reward.d.ts +0 -279
  28. package/dist/tools/reward.js +0 -361
  29. package/dist/tools/segment.d.ts +0 -816
  30. package/dist/tools/segment.js +0 -333
  31. package/dist/workflows/app-login-streak.d.ts +0 -39
  32. package/dist/workflows/app-login-streak.js +0 -298
  33. package/dist/workflows/early-arrival.d.ts +0 -33
  34. package/dist/workflows/early-arrival.js +0 -148
  35. package/dist/workflows/index.d.ts +0 -101
  36. package/dist/workflows/index.js +0 -208
  37. package/dist/workflows/match-attendance.d.ts +0 -45
  38. package/dist/workflows/match-attendance.js +0 -308
  39. package/dist/workflows/sportsbar-visit.d.ts +0 -41
  40. package/dist/workflows/sportsbar-visit.js +0 -284
  41. package/dist/workflows/vod-watching.d.ts +0 -43
  42. package/dist/workflows/vod-watching.js +0 -326
@@ -1,361 +0,0 @@
1
- import { z } from "zod";
2
- import { apiGet, apiPost, apiPut } from "../client/http.js";
3
- import { RewardSchema, } from "../types/schemas/reward.js";
4
- import { formatApiError, OpenLoyaltyError } from "../utils/errors.js";
5
- import { getStoreCode } from "../config.js";
6
- import { omitUndefined } from "../utils/payload.js";
7
- // Input Schemas
8
- export const RewardListInputSchema = {
9
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
10
- page: z.number().optional().describe("Page number (default: 1)."),
11
- perPage: z.number().optional().describe("Items per page (default: 10)."),
12
- active: z.boolean().optional().describe("Filter by active status."),
13
- type: z.enum(["static_coupon", "dynamic_coupon", "conversion_coupon", "material", "fortune_wheel"]).optional().describe("Filter by reward type."),
14
- categoryId: z.string().optional().describe("Filter by category ID."),
15
- };
16
- export const RewardCreateInputSchema = {
17
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
18
- name: z.string().describe("Reward name (required, max 255 chars)."),
19
- type: z.enum(["static_coupon", "dynamic_coupon", "conversion_coupon", "material", "fortune_wheel"]).describe("Reward type: static_coupon (fixed discount), dynamic_coupon (variable value), " +
20
- "conversion_coupon (converts points to coupon), material (physical goods), fortune_wheel (gamified)."),
21
- costInPoints: z.number().optional().describe("Points required to redeem this reward."),
22
- description: z.string().optional().describe("Reward description."),
23
- usageInstruction: z.string().optional().describe("Instructions for using the reward."),
24
- active: z.boolean().optional().describe("Whether reward is active (default: false)."),
25
- categories: z.array(z.string()).optional().describe("Array of category UUIDs."),
26
- levels: z.array(z.string()).optional().describe("Array of tier level UUIDs that can see/redeem."),
27
- segments: z.array(z.string()).optional().describe("Array of segment UUIDs that can see/redeem."),
28
- target: z.enum(["level", "segment"]).nullable().optional().describe("Target type for visibility: level (tier-based), segment (segment-based), or null (all)."),
29
- couponValue: z.number().optional().describe("Coupon value (required for static_coupon)."),
30
- couponValueType: z.enum(["Money", "Percentage"]).optional().describe("Coupon value type."),
31
- daysValid: z.number().optional().describe("Days the coupon remains valid after purchase."),
32
- };
33
- export const RewardGetInputSchema = {
34
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
35
- rewardId: z.string().describe("The reward ID (UUID) to retrieve."),
36
- };
37
- export const RewardUpdateInputSchema = {
38
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
39
- rewardId: z.string().describe("The reward ID (UUID) to update."),
40
- name: z.string().optional().describe("Reward name."),
41
- costInPoints: z.number().optional().describe("Points required to redeem."),
42
- description: z.string().optional().describe("Reward description."),
43
- active: z.boolean().optional().describe("Whether reward is active."),
44
- categories: z.array(z.string()).optional().describe("Array of category UUIDs."),
45
- levels: z.array(z.string()).optional().describe("Array of tier level UUIDs."),
46
- segments: z.array(z.string()).optional().describe("Array of segment UUIDs."),
47
- };
48
- export const RewardIdInputSchema = {
49
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
50
- rewardId: z.string().describe("The reward ID (UUID)."),
51
- };
52
- export const RewardBuyInputSchema = {
53
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
54
- rewardId: z.string().describe("The reward ID (UUID) to purchase."),
55
- memberId: z.string().describe("The member ID (UUID) purchasing the reward."),
56
- quantity: z.number().optional().describe("Number of rewards to purchase (1-32, default: 1)."),
57
- couponValue: z.number().optional().describe("Coupon value (for dynamic coupons)."),
58
- withoutPoints: z.boolean().optional().describe("Admin only: skip points deduction."),
59
- };
60
- export const RewardRedeemInputSchema = {
61
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
62
- memberId: z.string().describe("The member ID (UUID) redeeming the coupon."),
63
- couponCode: z.string().describe("The coupon code to redeem."),
64
- };
65
- export const RewardCategoryListInputSchema = {
66
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
67
- page: z.number().optional().describe("Page number (default: 1)."),
68
- perPage: z.number().optional().describe("Items per page (default: 10)."),
69
- active: z.boolean().optional().describe("Filter by active status."),
70
- };
71
- // Handler functions
72
- export async function rewardList(input) {
73
- const storeCode = getStoreCode(input.storeCode);
74
- const params = new URLSearchParams();
75
- if (input.page)
76
- params.append("_page", String(input.page));
77
- if (input.perPage)
78
- params.append("_itemsOnPage", String(input.perPage));
79
- if (input.active !== undefined)
80
- params.append("active", String(input.active));
81
- if (input.type)
82
- params.append("reward", input.type);
83
- if (input.categoryId)
84
- params.append("categoryId", input.categoryId);
85
- const queryString = params.toString();
86
- const url = `/${storeCode}/reward${queryString ? `?${queryString}` : ""}`;
87
- try {
88
- const response = await apiGet(url);
89
- const items = response.items || [];
90
- const rewards = items.map((r) => {
91
- const reward = r;
92
- return {
93
- rewardId: reward.rewardId,
94
- name: reward.name,
95
- type: (reward.reward || reward.type),
96
- costInPoints: reward.costInPoints,
97
- active: (reward.active ?? false),
98
- };
99
- });
100
- const total = response.total || {};
101
- return {
102
- rewards,
103
- total: {
104
- all: typeof total.all === 'number' ? total.all : undefined,
105
- filtered: typeof total.filtered === 'number' ? total.filtered : undefined,
106
- }
107
- };
108
- }
109
- catch (error) {
110
- throw formatApiError(error, "openloyalty_reward_list");
111
- }
112
- }
113
- export async function rewardCreate(input) {
114
- const storeCode = getStoreCode(input.storeCode);
115
- const payload = omitUndefined({
116
- name: input.name,
117
- type: input.type,
118
- costInPoints: input.costInPoints,
119
- description: input.description,
120
- usageInstruction: input.usageInstruction,
121
- active: input.active,
122
- categories: input.categories,
123
- levels: input.levels,
124
- segments: input.segments,
125
- target: input.target,
126
- couponValue: input.couponValue,
127
- couponValueType: input.couponValueType,
128
- daysValid: input.daysValid,
129
- });
130
- try {
131
- const response = await apiPost(`/${storeCode}/reward`, { reward: payload });
132
- return {
133
- rewardId: response.rewardId,
134
- name: input.name,
135
- costInPoints: input.costInPoints,
136
- };
137
- }
138
- catch (error) {
139
- throw formatApiError(error, "openloyalty_reward_create");
140
- }
141
- }
142
- export async function rewardGet(input) {
143
- const storeCode = getStoreCode(input.storeCode);
144
- try {
145
- const response = await apiGet(`/${storeCode}/reward/${input.rewardId}`);
146
- return RewardSchema.parse(response);
147
- }
148
- catch (error) {
149
- throw formatApiError(error, "openloyalty_reward_get");
150
- }
151
- }
152
- export async function rewardUpdate(input) {
153
- const storeCode = getStoreCode(input.storeCode);
154
- const payload = omitUndefined({
155
- name: input.name,
156
- costInPoints: input.costInPoints,
157
- description: input.description,
158
- active: input.active,
159
- categories: input.categories,
160
- levels: input.levels,
161
- segments: input.segments,
162
- });
163
- try {
164
- await apiPut(`/${storeCode}/reward/${input.rewardId}`, { reward: payload });
165
- }
166
- catch (error) {
167
- throw formatApiError(error, "openloyalty_reward_update");
168
- }
169
- }
170
- export async function rewardActivate(input) {
171
- const storeCode = getStoreCode(input.storeCode);
172
- try {
173
- await apiPost(`/${storeCode}/reward/${input.rewardId}/activate`);
174
- }
175
- catch (error) {
176
- throw formatApiError(error, "openloyalty_reward_activate");
177
- }
178
- }
179
- export async function rewardDeactivate(input) {
180
- const storeCode = getStoreCode(input.storeCode);
181
- try {
182
- await apiPost(`/${storeCode}/reward/${input.rewardId}/deactivate`);
183
- }
184
- catch (error) {
185
- throw formatApiError(error, "openloyalty_reward_deactivate");
186
- }
187
- }
188
- export async function rewardBuy(input) {
189
- const storeCode = getStoreCode(input.storeCode);
190
- const payload = omitUndefined({
191
- customerId: input.memberId,
192
- quantity: input.quantity,
193
- couponValue: input.couponValue,
194
- withoutPoints: input.withoutPoints,
195
- });
196
- try {
197
- const response = await apiPost(`/${storeCode}/reward/${input.rewardId}/buy`, payload);
198
- // API returns array of issued rewards
199
- const firstIssued = Array.isArray(response) ? response[0] : response;
200
- return {
201
- issuedRewardId: firstIssued?.issuedRewardId || "",
202
- couponCode: firstIssued?.couponCode,
203
- };
204
- }
205
- catch (error) {
206
- const errorMessage = error instanceof Error ? error.message : String(error);
207
- if (errorMessage.includes("NotEnoughPoints") || errorMessage.includes("insufficient")) {
208
- throw new OpenLoyaltyError({
209
- code: "INSUFFICIENT_BALANCE",
210
- message: "Member does not have enough points to purchase this reward",
211
- hint: `Use points_get_balance(memberId: "${input.memberId}") to check available balance. Then use reward_get(rewardId: "${input.rewardId}") to see the costInPoints required.`,
212
- relatedTool: "openloyalty_reward_buy",
213
- });
214
- }
215
- throw formatApiError(error, "openloyalty_reward_buy");
216
- }
217
- }
218
- export async function rewardRedeem(input) {
219
- const storeCode = getStoreCode(input.storeCode);
220
- try {
221
- const response = await apiPost(`/${storeCode}/member/${input.memberId}/reward/redeem`, { couponCode: input.couponCode });
222
- return { code: response.code || input.couponCode, used: true };
223
- }
224
- catch (error) {
225
- const errorMessage = error instanceof Error ? error.message : String(error);
226
- if (errorMessage.includes("CouponDoesNotExist")) {
227
- throw new OpenLoyaltyError({
228
- code: "COUPON_NOT_FOUND",
229
- message: `Coupon '${input.couponCode}' does not exist`,
230
- hint: `Verify the coupon code is correct. Use reward_buy to purchase a reward and obtain a valid coupon code.`,
231
- relatedTool: "openloyalty_reward_redeem",
232
- });
233
- }
234
- if (errorMessage.includes("CouponAlreadyUsed")) {
235
- throw new OpenLoyaltyError({
236
- code: "COUPON_ALREADY_USED",
237
- message: `Coupon '${input.couponCode}' has already been redeemed`,
238
- hint: `Each coupon can only be used once. The member may need to purchase another reward to get a new coupon.`,
239
- relatedTool: "openloyalty_reward_redeem",
240
- });
241
- }
242
- if (errorMessage.includes("CouponIsExpired")) {
243
- throw new OpenLoyaltyError({
244
- code: "COUPON_EXPIRED",
245
- message: `Coupon '${input.couponCode}' has expired`,
246
- hint: `Coupons have a validity period. The member will need to purchase a new reward for a fresh coupon.`,
247
- relatedTool: "openloyalty_reward_redeem",
248
- });
249
- }
250
- throw formatApiError(error, "openloyalty_reward_redeem");
251
- }
252
- }
253
- export async function rewardCategoryList(input) {
254
- const storeCode = getStoreCode(input.storeCode);
255
- const params = new URLSearchParams();
256
- if (input.page)
257
- params.append("_page", String(input.page));
258
- if (input.perPage)
259
- params.append("_itemsOnPage", String(input.perPage));
260
- if (input.active !== undefined)
261
- params.append("active", String(input.active));
262
- const queryString = params.toString();
263
- const url = `/${storeCode}/rewardCategory${queryString ? `?${queryString}` : ""}`;
264
- try {
265
- const response = await apiGet(url);
266
- const items = response.items || response.categories || [];
267
- const categories = items.map((c) => {
268
- const cat = c;
269
- return {
270
- categoryId: (cat.rewardCategoryId || cat.categoryId),
271
- name: cat.name,
272
- active: (cat.active ?? false),
273
- };
274
- });
275
- return { categories };
276
- }
277
- catch (error) {
278
- throw formatApiError(error, "openloyalty_reward_category_list");
279
- }
280
- }
281
- // Tool definitions
282
- export const rewardToolDefinitions = [
283
- {
284
- name: "openloyalty_reward_list",
285
- title: "Browse Rewards",
286
- description: "List available rewards. Use reward_get for full details or reward_buy to redeem. " +
287
- "Filter by type, active status, or category.",
288
- readOnly: true,
289
- inputSchema: RewardListInputSchema,
290
- handler: rewardList,
291
- },
292
- {
293
- name: "openloyalty_reward_create",
294
- title: "Create New Reward",
295
- description: "Create a new reward that members can redeem with points. " +
296
- "Types: static_coupon (fixed discount), dynamic_coupon (variable value set at purchase), " +
297
- "material (physical goods), conversion_coupon (converts points), fortune_wheel (gamified). " +
298
- "Returns rewardId.",
299
- readOnly: false,
300
- inputSchema: RewardCreateInputSchema,
301
- handler: rewardCreate,
302
- },
303
- {
304
- name: "openloyalty_reward_get",
305
- title: "Get Reward Details",
306
- description: "Get full reward details including configuration, targeting, and coupon settings.",
307
- readOnly: true,
308
- inputSchema: RewardGetInputSchema,
309
- handler: rewardGet,
310
- },
311
- {
312
- name: "openloyalty_reward_update",
313
- title: "Update Reward",
314
- description: "Update reward configuration. Cannot change reward type after creation.",
315
- readOnly: false,
316
- inputSchema: RewardUpdateInputSchema,
317
- handler: rewardUpdate,
318
- },
319
- {
320
- name: "openloyalty_reward_activate",
321
- title: "Activate Reward",
322
- description: "Activate a reward, making it available for members to redeem.",
323
- readOnly: false,
324
- inputSchema: RewardIdInputSchema,
325
- handler: rewardActivate,
326
- },
327
- {
328
- name: "openloyalty_reward_deactivate",
329
- title: "Deactivate Reward",
330
- description: "Deactivate a reward, hiding it from members. Already purchased rewards remain valid.",
331
- readOnly: false,
332
- inputSchema: RewardIdInputSchema,
333
- handler: rewardDeactivate,
334
- },
335
- {
336
- name: "openloyalty_reward_buy",
337
- title: "Redeem Reward for Member",
338
- description: "Purchase reward for member, deducting points. Returns issuedRewardId and couponCode if applicable. " +
339
- "Use reward_redeem to mark the coupon as used.",
340
- readOnly: false,
341
- inputSchema: RewardBuyInputSchema,
342
- handler: rewardBuy,
343
- },
344
- {
345
- name: "openloyalty_reward_redeem",
346
- title: "Use Coupon Code",
347
- description: "Mark coupon as used. Validates coupon exists, belongs to member, and is active. " +
348
- "Fails if coupon is expired, already used, or doesn't exist.",
349
- readOnly: false,
350
- inputSchema: RewardRedeemInputSchema,
351
- handler: rewardRedeem,
352
- },
353
- {
354
- name: "openloyalty_reward_category_list",
355
- title: "List Reward Categories",
356
- description: "List reward categories. Use categoryId when creating or filtering rewards.",
357
- readOnly: true,
358
- inputSchema: RewardCategoryListInputSchema,
359
- handler: rewardCategoryList,
360
- },
361
- ];