@open-loyalty/mcp-server 1.3.7 → 1.5.3

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 (100) hide show
  1. package/dist/config.d.ts +4 -3
  2. package/dist/config.js +9 -7
  3. package/dist/instructions.d.ts +1 -1
  4. package/dist/instructions.js +26 -8
  5. package/dist/tools/achievement/handlers.js +60 -1
  6. package/dist/tools/achievement/index.d.ts +8 -8
  7. package/dist/tools/achievement/index.js +10 -11
  8. package/dist/tools/achievement/schemas.d.ts +8 -8
  9. package/dist/tools/achievement/schemas.js +36 -32
  10. package/dist/tools/analytics.js +9 -9
  11. package/dist/tools/badge.js +4 -4
  12. package/dist/tools/campaign/handlers.js +35 -1
  13. package/dist/tools/campaign/index.d.ts +97 -34
  14. package/dist/tools/campaign/index.js +14 -12
  15. package/dist/tools/campaign/schemas.d.ts +96 -33
  16. package/dist/tools/campaign/schemas.js +89 -55
  17. package/dist/tools/custom-event.js +10 -9
  18. package/dist/tools/export.js +4 -4
  19. package/dist/tools/import.d.ts +1 -1
  20. package/dist/tools/import.js +11 -6
  21. package/dist/tools/index.js +4 -4
  22. package/dist/tools/member/handlers.js +48 -1
  23. package/dist/tools/member/index.d.ts +1 -1
  24. package/dist/tools/member/index.js +3 -1
  25. package/dist/tools/member/schemas.js +12 -12
  26. package/dist/tools/points/handlers.d.ts +75 -0
  27. package/dist/tools/{points.js → points/handlers.js} +21 -112
  28. package/dist/tools/points/index.d.ts +84 -0
  29. package/dist/tools/points/index.js +63 -0
  30. package/dist/tools/points/schemas.d.ts +45 -0
  31. package/dist/tools/points/schemas.js +47 -0
  32. package/dist/tools/referral/schemas.js +3 -3
  33. package/dist/tools/reward/handlers.d.ts +2 -0
  34. package/dist/tools/reward/handlers.js +79 -6
  35. package/dist/tools/reward/index.d.ts +2 -0
  36. package/dist/tools/reward/index.js +10 -10
  37. package/dist/tools/reward/schemas.d.ts +2 -0
  38. package/dist/tools/reward/schemas.js +42 -23
  39. package/dist/tools/segment/index.js +7 -5
  40. package/dist/tools/segment/schemas.js +11 -11
  41. package/dist/tools/tierset/handlers.d.ts +26 -0
  42. package/dist/tools/tierset/handlers.js +196 -0
  43. package/dist/tools/tierset/index.d.ts +124 -0
  44. package/dist/tools/tierset/index.js +88 -0
  45. package/dist/tools/tierset/schemas.d.ts +127 -0
  46. package/dist/tools/tierset/schemas.js +62 -0
  47. package/dist/tools/transaction/handlers.d.ts +89 -0
  48. package/dist/tools/transaction/handlers.js +159 -0
  49. package/dist/tools/transaction/index.d.ts +153 -0
  50. package/dist/tools/transaction/index.js +54 -0
  51. package/dist/tools/transaction/schemas.d.ts +126 -0
  52. package/dist/tools/transaction/schemas.js +60 -0
  53. package/dist/tools/wallet-type/handlers.d.ts +63 -0
  54. package/dist/tools/{wallet-type.js → wallet-type/handlers.js} +15 -78
  55. package/dist/tools/{wallet-type.d.ts → wallet-type/index.d.ts} +3 -64
  56. package/dist/tools/wallet-type/index.js +65 -0
  57. package/dist/tools/wallet-type/schemas.d.ts +1 -0
  58. package/dist/tools/wallet-type/schemas.js +1 -0
  59. package/dist/tools/webhook.js +6 -6
  60. package/dist/types/schemas/achievement.d.ts +48 -48
  61. package/dist/types/schemas/admin.d.ts +10 -10
  62. package/dist/types/schemas/campaign.d.ts +12 -12
  63. package/dist/types/schemas/common.js +1 -1
  64. package/dist/types/schemas/member.d.ts +18 -18
  65. package/dist/types/schemas/role.d.ts +4 -4
  66. package/dist/types/schemas/tierset.js +2 -1
  67. package/dist/types/schemas/transaction.d.ts +12 -12
  68. package/dist/types/schemas/wallet-type.js +12 -10
  69. package/dist/types/schemas/webhook.d.ts +6 -6
  70. package/dist/utils/errors.js +40 -0
  71. package/package.json +3 -2
  72. package/dist/prompts/fan-engagement-setup.d.ts +0 -107
  73. package/dist/prompts/fan-engagement-setup.js +0 -492
  74. package/dist/tools/achievement.d.ts +0 -1017
  75. package/dist/tools/achievement.js +0 -354
  76. package/dist/tools/campaign.d.ts +0 -1800
  77. package/dist/tools/campaign.js +0 -737
  78. package/dist/tools/member.d.ts +0 -366
  79. package/dist/tools/member.js +0 -352
  80. package/dist/tools/points.d.ts +0 -201
  81. package/dist/tools/reward.d.ts +0 -279
  82. package/dist/tools/reward.js +0 -361
  83. package/dist/tools/segment.d.ts +0 -816
  84. package/dist/tools/segment.js +0 -333
  85. package/dist/tools/tierset.d.ts +0 -273
  86. package/dist/tools/tierset.js +0 -289
  87. package/dist/tools/transaction.d.ts +0 -365
  88. package/dist/tools/transaction.js +0 -259
  89. package/dist/workflows/app-login-streak.d.ts +0 -39
  90. package/dist/workflows/app-login-streak.js +0 -298
  91. package/dist/workflows/early-arrival.d.ts +0 -33
  92. package/dist/workflows/early-arrival.js +0 -148
  93. package/dist/workflows/index.d.ts +0 -101
  94. package/dist/workflows/index.js +0 -208
  95. package/dist/workflows/match-attendance.d.ts +0 -45
  96. package/dist/workflows/match-attendance.js +0 -308
  97. package/dist/workflows/sportsbar-visit.d.ts +0 -41
  98. package/dist/workflows/sportsbar-visit.js +0 -284
  99. package/dist/workflows/vod-watching.d.ts +0 -43
  100. package/dist/workflows/vod-watching.js +0 -326
@@ -65,17 +65,17 @@ export declare const CampaignUpdateInputSchema: {
65
65
  description: z.ZodOptional<z.ZodString>;
66
66
  target: z.ZodOptional<z.ZodEnum<["self", "referrer"]>>;
67
67
  effects: z.ZodArray<z.ZodObject<{
68
- effect: z.ZodString;
68
+ effect: z.ZodEnum<["give_points", "give_reward", "deduct_unit", "assign_member_custom_attribute", "remove_member_custom_attribute"]>;
69
69
  pointsRule: z.ZodOptional<z.ZodString>;
70
70
  walletCode: z.ZodOptional<z.ZodString>;
71
71
  rewardId: z.ZodOptional<z.ZodString>;
72
72
  }, "strip", z.ZodTypeAny, {
73
- effect: string;
73
+ effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
74
74
  walletCode?: string | undefined;
75
75
  rewardId?: string | undefined;
76
76
  pointsRule?: string | undefined;
77
77
  }, {
78
- effect: string;
78
+ effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
79
79
  walletCode?: string | undefined;
80
80
  rewardId?: string | undefined;
81
81
  pointsRule?: string | undefined;
@@ -83,20 +83,20 @@ export declare const CampaignUpdateInputSchema: {
83
83
  conditions: z.ZodOptional<z.ZodArray<z.ZodObject<{
84
84
  operator: z.ZodString;
85
85
  attribute: z.ZodString;
86
- data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
86
+ data: z.ZodUnknown;
87
87
  }, "strip", z.ZodTypeAny, {
88
88
  attribute: string;
89
89
  operator: string;
90
- data?: Record<string, unknown> | undefined;
90
+ data?: unknown;
91
91
  }, {
92
92
  attribute: string;
93
93
  operator: string;
94
- data?: Record<string, unknown> | undefined;
94
+ data?: unknown;
95
95
  }>, "many">>;
96
96
  }, "strip", z.ZodTypeAny, {
97
97
  name: string;
98
98
  effects: {
99
- effect: string;
99
+ effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
100
100
  walletCode?: string | undefined;
101
101
  rewardId?: string | undefined;
102
102
  pointsRule?: string | undefined;
@@ -105,13 +105,13 @@ export declare const CampaignUpdateInputSchema: {
105
105
  conditions?: {
106
106
  attribute: string;
107
107
  operator: string;
108
- data?: Record<string, unknown> | undefined;
108
+ data?: unknown;
109
109
  }[] | undefined;
110
110
  target?: "self" | "referrer" | undefined;
111
111
  }, {
112
112
  name: string;
113
113
  effects: {
114
- effect: string;
114
+ effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
115
115
  walletCode?: string | undefined;
116
116
  rewardId?: string | undefined;
117
117
  pointsRule?: string | undefined;
@@ -120,7 +120,7 @@ export declare const CampaignUpdateInputSchema: {
120
120
  conditions?: {
121
121
  attribute: string;
122
122
  operator: string;
123
- data?: Record<string, unknown> | undefined;
123
+ data?: unknown;
124
124
  }[] | undefined;
125
125
  target?: "self" | "referrer" | undefined;
126
126
  }>, "many">;
@@ -129,11 +129,11 @@ export declare const CampaignUpdateInputSchema: {
129
129
  tiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
130
130
  segments: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
131
131
  }, "strip", z.ZodTypeAny, {
132
- target: "all" | "segment" | "tier";
132
+ target: "all" | "tier" | "segment";
133
133
  tiers?: string[] | undefined;
134
134
  segments?: string[] | undefined;
135
135
  }, {
136
- target: "all" | "segment" | "tier";
136
+ target: "all" | "tier" | "segment";
137
137
  tiers?: string[] | undefined;
138
138
  segments?: string[] | undefined;
139
139
  }>>;
@@ -142,70 +142,133 @@ export declare const CampaignUpdateInputSchema: {
142
142
  tiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
143
143
  segments: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
144
144
  }, "strip", z.ZodTypeAny, {
145
- target: "segment" | "tier";
145
+ target: "tier" | "segment";
146
146
  tiers?: string[] | undefined;
147
147
  segments?: string[] | undefined;
148
148
  }, {
149
- target: "segment" | "tier";
149
+ target: "tier" | "segment";
150
150
  tiers?: string[] | undefined;
151
151
  segments?: string[] | undefined;
152
152
  }>>;
153
153
  limits: z.ZodOptional<z.ZodObject<{
154
154
  points: z.ZodOptional<z.ZodObject<{
155
155
  value: z.ZodNumber;
156
- interval: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
156
+ interval: z.ZodOptional<z.ZodObject<{
157
+ type: z.ZodEnum<["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"]>;
158
+ value: z.ZodOptional<z.ZodNumber>;
159
+ }, "strip", z.ZodTypeAny, {
160
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
161
+ value?: number | undefined;
162
+ }, {
163
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
164
+ value?: number | undefined;
165
+ }>>;
157
166
  }, "strip", z.ZodTypeAny, {
158
167
  value: number;
159
- interval?: Record<string, unknown> | undefined;
168
+ interval?: {
169
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
170
+ value?: number | undefined;
171
+ } | undefined;
160
172
  }, {
161
173
  value: number;
162
- interval?: Record<string, unknown> | undefined;
174
+ interval?: {
175
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
176
+ value?: number | undefined;
177
+ } | undefined;
163
178
  }>>;
164
179
  pointsPerMember: z.ZodOptional<z.ZodObject<{
165
180
  value: z.ZodNumber;
166
- interval: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
181
+ interval: z.ZodOptional<z.ZodObject<{
182
+ type: z.ZodEnum<["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"]>;
183
+ value: z.ZodOptional<z.ZodNumber>;
184
+ }, "strip", z.ZodTypeAny, {
185
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
186
+ value?: number | undefined;
187
+ }, {
188
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
189
+ value?: number | undefined;
190
+ }>>;
167
191
  }, "strip", z.ZodTypeAny, {
168
192
  value: number;
169
- interval?: Record<string, unknown> | undefined;
193
+ interval?: {
194
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
195
+ value?: number | undefined;
196
+ } | undefined;
170
197
  }, {
171
198
  value: number;
172
- interval?: Record<string, unknown> | undefined;
199
+ interval?: {
200
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
201
+ value?: number | undefined;
202
+ } | undefined;
173
203
  }>>;
174
204
  executionsPerMember: z.ZodOptional<z.ZodObject<{
175
205
  value: z.ZodNumber;
176
- interval: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
206
+ interval: z.ZodOptional<z.ZodObject<{
207
+ type: z.ZodEnum<["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"]>;
208
+ value: z.ZodOptional<z.ZodNumber>;
209
+ }, "strip", z.ZodTypeAny, {
210
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
211
+ value?: number | undefined;
212
+ }, {
213
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
214
+ value?: number | undefined;
215
+ }>>;
177
216
  }, "strip", z.ZodTypeAny, {
178
217
  value: number;
179
- interval?: Record<string, unknown> | undefined;
218
+ interval?: {
219
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
220
+ value?: number | undefined;
221
+ } | undefined;
180
222
  }, {
181
223
  value: number;
182
- interval?: Record<string, unknown> | undefined;
224
+ interval?: {
225
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
226
+ value?: number | undefined;
227
+ } | undefined;
183
228
  }>>;
184
229
  }, "strip", z.ZodTypeAny, {
185
230
  points?: {
186
231
  value: number;
187
- interval?: Record<string, unknown> | undefined;
232
+ interval?: {
233
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
234
+ value?: number | undefined;
235
+ } | undefined;
188
236
  } | undefined;
189
237
  pointsPerMember?: {
190
238
  value: number;
191
- interval?: Record<string, unknown> | undefined;
239
+ interval?: {
240
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
241
+ value?: number | undefined;
242
+ } | undefined;
192
243
  } | undefined;
193
244
  executionsPerMember?: {
194
245
  value: number;
195
- interval?: Record<string, unknown> | undefined;
246
+ interval?: {
247
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
248
+ value?: number | undefined;
249
+ } | undefined;
196
250
  } | undefined;
197
251
  }, {
198
252
  points?: {
199
253
  value: number;
200
- interval?: Record<string, unknown> | undefined;
254
+ interval?: {
255
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
256
+ value?: number | undefined;
257
+ } | undefined;
201
258
  } | undefined;
202
259
  pointsPerMember?: {
203
260
  value: number;
204
- interval?: Record<string, unknown> | undefined;
261
+ interval?: {
262
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
263
+ value?: number | undefined;
264
+ } | undefined;
205
265
  } | undefined;
206
266
  executionsPerMember?: {
207
267
  value: number;
208
- interval?: Record<string, unknown> | undefined;
268
+ interval?: {
269
+ type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
270
+ value?: number | undefined;
271
+ } | undefined;
209
272
  } | undefined;
210
273
  }>>;
211
274
  active: z.ZodOptional<z.ZodBoolean>;
@@ -545,11 +608,11 @@ export declare const CampaignCreateInputSchema: {
545
608
  tiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
546
609
  segments: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
547
610
  }, "strip", z.ZodTypeAny, {
548
- target: "all" | "segment" | "tier";
611
+ target: "all" | "tier" | "segment";
549
612
  tiers?: string[] | undefined;
550
613
  segments?: string[] | undefined;
551
614
  }, {
552
- target: "all" | "segment" | "tier";
615
+ target: "all" | "tier" | "segment";
553
616
  tiers?: string[] | undefined;
554
617
  segments?: string[] | undefined;
555
618
  }>>;
@@ -558,11 +621,11 @@ export declare const CampaignCreateInputSchema: {
558
621
  tiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
559
622
  segments: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
560
623
  }, "strip", z.ZodTypeAny, {
561
- target: "segment" | "tier";
624
+ target: "tier" | "segment";
562
625
  tiers?: string[] | undefined;
563
626
  segments?: string[] | undefined;
564
627
  }, {
565
- target: "segment" | "tier";
628
+ target: "tier" | "segment";
566
629
  tiers?: string[] | undefined;
567
630
  segments?: string[] | undefined;
568
631
  }>>;
@@ -11,14 +11,13 @@ const TranslationsInputSchema = z.object({
11
11
  const CampaignEffectInputSchema = z.object({
12
12
  effect: z.enum(["give_points", "give_reward", "deduct_unit", "assign_member_custom_attribute", "remove_member_custom_attribute"])
13
13
  .describe("Effect type: give_points, give_reward, deduct_unit, etc. Use key `effect` (not `type`)."),
14
- pointsRule: z.string().optional().describe("Points calculation expression (required for give_points). " +
14
+ pointsRule: z.string().optional().describe("Points calculation expression (required for give_points). Must be a STRING. " +
15
15
  "Fixed: '100'. Dynamic: 'transaction.grossValue * 10'. " +
16
16
  "Category: 'transaction.category(\"electronics\").grossValue * 5'. " +
17
17
  "Capped: '(transaction.grossValue * 2 >= 100) ? 100 : transaction.grossValue * 2'. " +
18
- "Rounded: 'round_up(0.1 * transaction.grossValue)'. " +
19
- "CONDITIONAL: Use ternary for conditional rewards based on custom event attributes: " +
20
- "'event.body.minutes_before >= 60 ? 25 : 0' (awards 25 if condition met, else 0). " +
21
- "Operators: ==, !=, >, <, >=, <=, &&, ||"),
18
+ "Conditional: 'event.body.minutes_before >= 60 ? 25 : 0'. " +
19
+ "BUSINESS IMPACT: 'transaction.grossValue * 10' on $500 avg transaction = 5,000 points/purchase. " +
20
+ "At $0.01/point, that is a 10% return rate. Confirm the formula and earn rate with the user."),
22
21
  walletCode: z.string().optional().describe("Wallet code for points (default wallet if not specified)."),
23
22
  rewardId: z.string().optional().describe("Reward ID (required for give_reward effect)."),
24
23
  customAttributeKey: z.string().optional().describe("Custom attribute key (for assign/remove member custom attribute effects)."),
@@ -54,7 +53,9 @@ const CampaignRuleInputSchema = z.object({
54
53
  // Activity input schema
55
54
  const CampaignActivityInputSchema = z.object({
56
55
  startsAt: z.string().describe("Campaign start date/time (ISO format: YYYY-MM-DD HH:mm+TZ). REQUIRED."),
57
- endsAt: z.string().optional().describe("Campaign end date/time (ISO format). If not specified, campaign runs indefinitely."),
56
+ endsAt: z.string().optional().describe("Campaign end date/time (ISO format). " +
57
+ "BUSINESS IMPACT: If not specified, campaign runs indefinitely -- this is an open-ended budget commitment. " +
58
+ "Confirm with user whether the campaign should have an end date."),
58
59
  });
59
60
  // Visibility input schema
60
61
  const CampaignVisibilityInputSchema = z.object({
@@ -140,7 +141,7 @@ const SimulateReferrerSchema = z.object({
140
141
  }).optional();
141
142
  // Exported Input Schemas
142
143
  export const CampaignListInputSchema = {
143
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
144
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
144
145
  page: z.number().optional().describe("Page number (default: 1)."),
145
146
  perPage: z.number().optional().describe("Items per page (default: 10)."),
146
147
  active: z.boolean().optional().describe("Filter by active status."),
@@ -148,72 +149,100 @@ export const CampaignListInputSchema = {
148
149
  trigger: CampaignTriggerEnum.optional().describe("Filter by trigger type: transaction, custom_event, time, etc."),
149
150
  };
150
151
  export const CampaignGetInputSchema = {
151
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
152
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
152
153
  campaignId: z.string().describe("The campaign ID (UUID) to retrieve."),
153
154
  };
154
155
  export const CampaignUpdateInputSchema = {
155
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
156
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
156
157
  campaignId: z.string().describe("The campaign ID (UUID) to update."),
157
158
  type: CampaignTypeEnum.describe("Campaign type: direct or referral."),
158
- trigger: CampaignTriggerEnum.describe("What triggers the campaign."),
159
+ trigger: CampaignTriggerEnum.describe("What triggers the campaign: transaction, custom_event, time, achievement, geolocation, etc."),
159
160
  translations: z.object({
160
161
  en: z.object({
161
- name: z.string(),
162
- description: z.string().optional(),
162
+ name: z.string().describe("Campaign name in English (REQUIRED)."),
163
+ description: z.string().optional().describe("Campaign description in English."),
163
164
  }),
164
165
  }).passthrough().describe("Translations object with at least 'en' key."),
165
166
  activity: z.object({
166
- startsAt: z.string(),
167
- endsAt: z.string().optional(),
168
- }).describe("Campaign active period."),
167
+ startsAt: z.string().describe("Campaign start date/time (ISO format: YYYY-MM-DD HH:mm+TZ). REQUIRED."),
168
+ endsAt: z.string().optional().describe("Campaign end date/time (ISO format). If not specified, campaign runs indefinitely."),
169
+ }).describe("Campaign active period with required startsAt."),
169
170
  rules: z.array(z.object({
170
- name: z.string(),
171
- description: z.string().optional(),
172
- target: z.enum(["self", "referrer"]).optional(),
171
+ name: z.string().describe("Rule name (required)."),
172
+ description: z.string().optional().describe("Rule description."),
173
+ target: z.enum(["self", "referrer"]).optional().describe("Target for rule effects: self (default) or referrer."),
173
174
  effects: z.array(z.object({
174
- effect: z.string(),
175
- pointsRule: z.string().optional(),
176
- walletCode: z.string().optional(),
177
- rewardId: z.string().optional(),
178
- })),
175
+ effect: z.enum(["give_points", "give_reward", "deduct_unit", "assign_member_custom_attribute", "remove_member_custom_attribute"])
176
+ .describe("Effect type. Use key 'effect' (NOT 'type'): give_points, give_reward, deduct_unit."),
177
+ pointsRule: z.string().optional().describe("Points calculation expression (required for give_points). STRING value: '100' (fixed), 'transaction.grossValue * 10' (dynamic)."),
178
+ walletCode: z.string().optional().describe("Wallet code for points. Use ol_wallet_type_list to find valid codes. Default wallet if not specified."),
179
+ rewardId: z.string().optional().describe("Reward ID (required for give_reward effect). Use ol_reward_list to find rewardId."),
180
+ })).describe("Array of effects to apply when rule matches."),
179
181
  conditions: z.array(z.object({
180
- operator: z.string(),
181
- attribute: z.string(),
182
- data: z.record(z.unknown()).optional(),
183
- })).optional(),
184
- })).describe("Campaign rules."),
182
+ operator: z.string().describe("Condition operator. Valid: is_equal, is_not_equal, is_greater, is_greater_or_equal, is_less, is_less_or_equal, " +
183
+ "contains, not_contains, has_at_least_one_label, is_one_of, is_between, is_after, is_before. " +
184
+ "Use FULL names (NOT 'gte', 'lte')."),
185
+ attribute: z.string().describe("Attribute path: 'transaction.grossValue', 'transaction.labels', 'customer.email'. Use full path with context prefix."),
186
+ data: z.unknown().describe("Condition value. Number for comparisons: 100. Label array for has_at_least_one_label: [{key: 'k', value: 'v'}]. " +
187
+ "Object for is_between: {from: 50, to: 200}."),
188
+ })).optional().describe("Array of conditions that must match for rule to apply."),
189
+ })).describe("Campaign rules with effects and optional conditions."),
185
190
  visibility: z.object({
186
- target: z.enum(["all", "tier", "segment"]),
187
- tiers: z.array(z.string()).optional(),
188
- segments: z.array(z.string()).optional(),
189
- }).optional(),
191
+ target: z.enum(["all", "tier", "segment"]).describe("Who can see the campaign: all, tier (specific tiers), or segment (specific segments)."),
192
+ tiers: z.array(z.string()).optional().describe("Array of tier level IDs (required if target is 'tier'). Use ol_tierset_get_tiers to find IDs."),
193
+ segments: z.array(z.string()).optional().describe("Array of segment IDs (required if target is 'segment'). Use ol_segment_list to find IDs."),
194
+ }).optional().describe("Who can see the campaign."),
190
195
  audience: z.object({
191
- target: z.enum(["tier", "segment"]),
192
- tiers: z.array(z.string()).optional(),
193
- segments: z.array(z.string()).optional(),
194
- }).optional(),
196
+ target: z.enum(["tier", "segment"]).describe("Who can participate: tier or segment. To target ALL members, OMIT the audience parameter entirely - do NOT use 'all'."),
197
+ tiers: z.array(z.string()).optional().describe("Array of tier level IDs (required if target is 'tier')."),
198
+ segments: z.array(z.string()).optional().describe("Array of segment IDs (required if target is 'segment')."),
199
+ }).optional().describe("Who can participate. OMIT entirely for all members."),
195
200
  limits: z.object({
196
- points: z.object({ value: z.number(), interval: z.record(z.unknown()).optional() }).optional(),
197
- pointsPerMember: z.object({ value: z.number(), interval: z.record(z.unknown()).optional() }).optional(),
198
- executionsPerMember: z.object({ value: z.number(), interval: z.record(z.unknown()).optional() }).optional(),
199
- }).optional(),
200
- active: z.boolean().optional(),
201
- displayOrder: z.number().optional(),
202
- labels: z.array(z.object({ key: z.string(), value: z.string() })).optional(),
203
- event: z.string().optional(),
201
+ points: z.object({
202
+ value: z.number().describe("Maximum total points."),
203
+ interval: z.object({
204
+ type: z.enum(["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"])
205
+ .describe("Interval type: calendarDays, calendarWeeks, calendarMonths, calendarYears. Omit interval for lifetime limit."),
206
+ value: z.number().optional().describe("Interval value (e.g., 1 for every 1 day)."),
207
+ }).optional().describe("Time interval for limit reset. Omit for lifetime limit."),
208
+ }).optional().describe("Total points limit for the campaign."),
209
+ pointsPerMember: z.object({
210
+ value: z.number().describe("Maximum points per member."),
211
+ interval: z.object({
212
+ type: z.enum(["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"])
213
+ .describe("Interval type: calendarDays, calendarWeeks, calendarMonths, calendarYears."),
214
+ value: z.number().optional().describe("Interval value."),
215
+ }).optional().describe("Time interval for limit reset. Omit for lifetime limit."),
216
+ }).optional().describe("Points limit per member."),
217
+ executionsPerMember: z.object({
218
+ value: z.number().describe("Maximum executions per member."),
219
+ interval: z.object({
220
+ type: z.enum(["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"])
221
+ .describe("Interval type: calendarDays, calendarWeeks, calendarMonths, calendarYears."),
222
+ value: z.number().optional().describe("Interval value."),
223
+ }).optional().describe("Time interval for limit reset. Omit for lifetime limit."),
224
+ }).optional().describe("Execution limit per member."),
225
+ }).optional().describe("Campaign limits for points and executions."),
226
+ active: z.boolean().optional().describe("Whether campaign is active."),
227
+ displayOrder: z.number().optional().describe("Display order for sorting campaigns."),
228
+ labels: z.array(z.object({
229
+ key: z.string().describe("Label key."),
230
+ value: z.string().describe("Label value."),
231
+ })).optional().describe("Custom labels/tags for the campaign."),
232
+ event: z.string().optional().describe("Custom event name (required for custom_event trigger). Use ol_custom_event_schema_list to find valid event codes."),
204
233
  };
205
234
  export const CampaignPatchInputSchema = {
206
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
235
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
207
236
  campaignId: z.string().describe("The campaign ID (UUID) to patch."),
208
237
  active: z.boolean().optional().describe("Set campaign active status."),
209
238
  displayOrder: z.number().optional().describe("Set campaign display order."),
210
239
  };
211
240
  export const CampaignDeleteInputSchema = {
212
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
241
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
213
242
  campaignId: z.string().describe("The campaign ID (UUID) to delete."),
214
243
  };
215
244
  export const CampaignSimulateInputSchema = {
216
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
245
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
217
246
  trigger: CampaignTriggerEnum.describe("Campaign trigger type to simulate: transaction, custom_event, etc."),
218
247
  transaction: SimulateTransactionSchema.describe("Transaction data (required for transaction trigger)."),
219
248
  customEvent: SimulateCustomEventSchema.describe("Custom event data (required for custom_event trigger)."),
@@ -221,12 +250,12 @@ export const CampaignSimulateInputSchema = {
221
250
  referrer: SimulateReferrerSchema.describe("Referrer data for referral campaigns."),
222
251
  };
223
252
  export const CampaignGenerateCodesInputSchema = {
224
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
253
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
225
254
  campaignId: z.string().describe("The campaign ID (UUID) to generate codes for."),
226
255
  quantity: z.number().min(1).describe("Number of codes to generate."),
227
256
  };
228
257
  export const CampaignListCodesInputSchema = {
229
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
258
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
230
259
  campaignId: z.string().describe("The campaign ID (UUID) to list codes for."),
231
260
  page: z.number().optional().describe("Page number (default: 1)."),
232
261
  perPage: z.number().optional().describe("Items per page (default: 25)."),
@@ -234,7 +263,7 @@ export const CampaignListCodesInputSchema = {
234
263
  code: z.string().optional().describe("Filter by specific code."),
235
264
  };
236
265
  export const CampaignGetAvailableInputSchema = {
237
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
266
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
238
267
  memberId: z.string().describe("The member ID (UUID) to get available campaigns for."),
239
268
  page: z.number().optional().describe("Page number (default: 1)."),
240
269
  perPage: z.number().optional().describe("Items per page (default: 25)."),
@@ -242,27 +271,32 @@ export const CampaignGetAvailableInputSchema = {
242
271
  trigger: CampaignTriggerEnum.optional().describe("Filter by campaign trigger."),
243
272
  };
244
273
  export const CampaignGetVisibleInputSchema = {
245
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
274
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
246
275
  memberId: z.string().describe("The member ID (UUID) to get visible campaigns for."),
247
276
  page: z.number().optional().describe("Page number (default: 1)."),
248
277
  perPage: z.number().optional().describe("Items per page (default: 25)."),
249
278
  active: z.boolean().optional().describe("Filter by active status."),
250
279
  };
251
280
  export const CampaignGetLeaderboardInputSchema = {
252
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
281
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
253
282
  campaignId: z.string().describe("The campaign ID (UUID) to get leaderboard for."),
254
283
  type: z.string().optional().describe("Cycle type for ranking (e.g., 'weekly', 'monthly')."),
255
284
  };
256
285
  export const CampaignCreateInputSchema = {
257
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
286
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
258
287
  type: CampaignTypeEnum.describe("Campaign type: direct (standard) or referral (for referral programs)."),
259
288
  trigger: CampaignTriggerEnum.describe("What triggers the campaign: transaction, custom_event, time, achievement, etc."),
260
289
  translations: TranslationsInputSchema,
261
290
  activity: CampaignActivityInputSchema.describe("Campaign active period with required startsAt and optional endsAt."),
262
291
  rules: z.array(CampaignRuleInputSchema).describe("Array of rules defining when and what effects to apply. Each rule requires a name."),
263
292
  visibility: CampaignVisibilityInputSchema.describe("Who can see the campaign."),
264
- audience: CampaignAudienceInputSchema.describe("Who can participate in the campaign. OMIT this parameter entirely to target ALL members."),
265
- limits: CampaignLimitsInputSchema.describe("Campaign limits for points and executions."),
293
+ audience: CampaignAudienceInputSchema.describe("Who can participate. OMIT entirely for all members -- do NOT pass target: 'all' (API rejects it). " +
294
+ "BUSINESS DECISION: Targeting wrong audience wastes budget or excludes key segments. " +
295
+ "Use target: 'tier' + tiers array, or target: 'segment' + segments array."),
296
+ limits: CampaignLimitsInputSchema.describe("Budget controls for the campaign. " +
297
+ "BUSINESS IMPACT: Without limits, a campaign running 12 months on 10K txn/month at 100 pts each = 12M points liability. " +
298
+ "BUSINESS DECISION: Set points (total cap), pointsPerMember (per-member cap), and/or executionsPerMember (frequency). " +
299
+ "Omit interval for lifetime limit, or use { type: 'calendarDays', value: 1 } for daily reset."),
266
300
  active: z.boolean().optional().describe("Whether campaign is active (default: false)."),
267
301
  displayOrder: z.number().optional().describe("Display order for sorting campaigns."),
268
302
  labels: z.array(CampaignLabelInputSchema).optional().describe("Custom labels/tags for the campaign."),
@@ -4,7 +4,7 @@ import { formatApiError } from "../utils/errors.js";
4
4
  import { getStoreCode } from "../config.js";
5
5
  // Input Schemas
6
6
  export const CustomEventSchemaListInputSchema = {
7
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
7
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
8
8
  page: z.number().optional().describe("Page number (default: 1)."),
9
9
  perPage: z.number().optional().describe("Items per page (default: 25)."),
10
10
  eventType: z.string().optional().describe("Filter by event type code."),
@@ -12,7 +12,7 @@ export const CustomEventSchemaListInputSchema = {
12
12
  active: z.boolean().optional().describe("Filter by active status."),
13
13
  };
14
14
  export const CustomEventSchemaGetInputSchema = {
15
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
15
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
16
16
  eventType: z.string().describe("The custom event type code to retrieve."),
17
17
  };
18
18
  const CustomEventSchemaFieldSchema = z.object({
@@ -21,27 +21,27 @@ const CustomEventSchemaFieldSchema = z.object({
21
21
  description: z.string().optional().describe("Field description."),
22
22
  });
23
23
  export const CustomEventSchemaCreateInputSchema = {
24
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
24
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
25
25
  eventType: z.string().describe("Unique event type code (e.g., 'location_visit', 'app_login', 'video_watch'). " +
26
26
  "Use snake_case. This is referenced in campaigns and achievements."),
27
27
  name: z.string().describe("Human-readable name for the event schema."),
28
- fields: z.array(CustomEventSchemaFieldSchema).describe("Array of fields the event can contain. Example: [{name: 'minutes_watched', type: 'integer'}]"),
28
+ fields: z.array(CustomEventSchemaFieldSchema).describe("Array of fields. Example: [{name: 'minutes_watched', type: 'number'}, {name: 'location', type: 'text'}]. Valid types: text, number, boolean, datetime."),
29
29
  active: z.boolean().optional().describe("Whether the schema is active (default: true)."),
30
30
  };
31
31
  export const CustomEventSchemaUpdateInputSchema = {
32
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
32
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
33
33
  eventType: z.string().describe("The custom event type code to update."),
34
34
  name: z.string().describe("Human-readable name for the event schema."),
35
35
  fields: z.array(CustomEventSchemaFieldSchema).describe("Array of fields the event can contain."),
36
36
  active: z.boolean().optional().describe("Whether the schema is active."),
37
37
  };
38
38
  export const CustomEventSchemaActivateInputSchema = {
39
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
39
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
40
40
  eventType: z.string().describe("The custom event type code to activate/deactivate."),
41
41
  active: z.boolean().describe("Set to true to activate, false to deactivate."),
42
42
  };
43
43
  export const CustomEventSendInputSchema = {
44
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
44
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
45
45
  eventType: z.string().describe("The custom event type code (must match an existing schema)."),
46
46
  customerData: z.object({
47
47
  customerId: z.string().optional().describe("Member ID (UUID) for identification."),
@@ -54,7 +54,7 @@ export const CustomEventSendInputSchema = {
54
54
  eventId: z.string().optional().describe("Unique event identifier for deduplication (optional, max 255 chars)."),
55
55
  };
56
56
  export const CustomEventListInputSchema = {
57
- storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
57
+ storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
58
58
  page: z.number().optional().describe("Page number (default: 1)."),
59
59
  perPage: z.number().optional().describe("Items per page (default: 25)."),
60
60
  type: z.string().optional().describe("Filter by event type."),
@@ -228,7 +228,8 @@ export const customEventToolDefinitions = [
228
228
  name: "ol_custom_event_schema_create",
229
229
  title: "Create Custom Event Schema",
230
230
  description: "Create a new custom event schema. REQUIRED before using a custom event in campaigns or achievements. " +
231
- "Example: To track location visits, create schema with eventType='location_visit' and fields like [{name: 'location_id', type: 'string'}]. " +
231
+ "Example: To track location visits, create schema with eventType='location_visit' and fields like [{name: 'location_id', type: 'text'}]. " +
232
+ "Valid field types: 'text' (strings), 'number' (integers/decimals), 'boolean', 'datetime'. " +
232
233
  "Then use campaign_create with trigger='custom_event', event='location_visit'.",
233
234
  readOnly: false,
234
235
  inputSchema: CustomEventSchemaCreateInputSchema,