@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.
- package/dist/config.d.ts +4 -3
- package/dist/config.js +9 -7
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.js +26 -8
- package/dist/tools/achievement/handlers.js +60 -1
- package/dist/tools/achievement/index.d.ts +8 -8
- package/dist/tools/achievement/index.js +10 -11
- package/dist/tools/achievement/schemas.d.ts +8 -8
- package/dist/tools/achievement/schemas.js +36 -32
- package/dist/tools/analytics.js +9 -9
- package/dist/tools/badge.js +4 -4
- package/dist/tools/campaign/handlers.js +35 -1
- package/dist/tools/campaign/index.d.ts +97 -34
- package/dist/tools/campaign/index.js +14 -12
- package/dist/tools/campaign/schemas.d.ts +96 -33
- package/dist/tools/campaign/schemas.js +89 -55
- package/dist/tools/custom-event.js +10 -9
- package/dist/tools/export.js +4 -4
- package/dist/tools/import.d.ts +1 -1
- package/dist/tools/import.js +11 -6
- package/dist/tools/index.js +4 -4
- package/dist/tools/member/handlers.js +48 -1
- package/dist/tools/member/index.d.ts +1 -1
- package/dist/tools/member/index.js +3 -1
- package/dist/tools/member/schemas.js +12 -12
- package/dist/tools/points/handlers.d.ts +75 -0
- package/dist/tools/{points.js → points/handlers.js} +21 -112
- package/dist/tools/points/index.d.ts +84 -0
- package/dist/tools/points/index.js +63 -0
- package/dist/tools/points/schemas.d.ts +45 -0
- package/dist/tools/points/schemas.js +47 -0
- package/dist/tools/referral/schemas.js +3 -3
- package/dist/tools/reward/handlers.d.ts +2 -0
- package/dist/tools/reward/handlers.js +79 -6
- package/dist/tools/reward/index.d.ts +2 -0
- package/dist/tools/reward/index.js +10 -10
- package/dist/tools/reward/schemas.d.ts +2 -0
- package/dist/tools/reward/schemas.js +42 -23
- package/dist/tools/segment/index.js +7 -5
- package/dist/tools/segment/schemas.js +11 -11
- package/dist/tools/tierset/handlers.d.ts +26 -0
- package/dist/tools/tierset/handlers.js +196 -0
- package/dist/tools/tierset/index.d.ts +124 -0
- package/dist/tools/tierset/index.js +88 -0
- package/dist/tools/tierset/schemas.d.ts +127 -0
- package/dist/tools/tierset/schemas.js +62 -0
- package/dist/tools/transaction/handlers.d.ts +89 -0
- package/dist/tools/transaction/handlers.js +159 -0
- package/dist/tools/transaction/index.d.ts +153 -0
- package/dist/tools/transaction/index.js +54 -0
- package/dist/tools/transaction/schemas.d.ts +126 -0
- package/dist/tools/transaction/schemas.js +60 -0
- package/dist/tools/wallet-type/handlers.d.ts +63 -0
- package/dist/tools/{wallet-type.js → wallet-type/handlers.js} +15 -78
- package/dist/tools/{wallet-type.d.ts → wallet-type/index.d.ts} +3 -64
- package/dist/tools/wallet-type/index.js +65 -0
- package/dist/tools/wallet-type/schemas.d.ts +1 -0
- package/dist/tools/wallet-type/schemas.js +1 -0
- package/dist/tools/webhook.js +6 -6
- package/dist/types/schemas/achievement.d.ts +48 -48
- package/dist/types/schemas/admin.d.ts +10 -10
- package/dist/types/schemas/campaign.d.ts +12 -12
- package/dist/types/schemas/common.js +1 -1
- package/dist/types/schemas/member.d.ts +18 -18
- package/dist/types/schemas/role.d.ts +4 -4
- package/dist/types/schemas/tierset.js +2 -1
- package/dist/types/schemas/transaction.d.ts +12 -12
- package/dist/types/schemas/wallet-type.js +12 -10
- package/dist/types/schemas/webhook.d.ts +6 -6
- package/dist/utils/errors.js +40 -0
- package/package.json +3 -2
- package/dist/prompts/fan-engagement-setup.d.ts +0 -107
- package/dist/prompts/fan-engagement-setup.js +0 -492
- package/dist/tools/achievement.d.ts +0 -1017
- package/dist/tools/achievement.js +0 -354
- package/dist/tools/campaign.d.ts +0 -1800
- package/dist/tools/campaign.js +0 -737
- package/dist/tools/member.d.ts +0 -366
- package/dist/tools/member.js +0 -352
- package/dist/tools/points.d.ts +0 -201
- package/dist/tools/reward.d.ts +0 -279
- package/dist/tools/reward.js +0 -361
- package/dist/tools/segment.d.ts +0 -816
- package/dist/tools/segment.js +0 -333
- package/dist/tools/tierset.d.ts +0 -273
- package/dist/tools/tierset.js +0 -289
- package/dist/tools/transaction.d.ts +0 -365
- package/dist/tools/transaction.js +0 -259
- package/dist/workflows/app-login-streak.d.ts +0 -39
- package/dist/workflows/app-login-streak.js +0 -298
- package/dist/workflows/early-arrival.d.ts +0 -33
- package/dist/workflows/early-arrival.js +0 -148
- package/dist/workflows/index.d.ts +0 -101
- package/dist/workflows/index.js +0 -208
- package/dist/workflows/match-attendance.d.ts +0 -45
- package/dist/workflows/match-attendance.js +0 -308
- package/dist/workflows/sportsbar-visit.d.ts +0 -41
- package/dist/workflows/sportsbar-visit.js +0 -284
- package/dist/workflows/vod-watching.d.ts +0 -43
- package/dist/workflows/vod-watching.js +0 -326
|
@@ -40,8 +40,9 @@ const AchievementRuleInputSchema = z.object({
|
|
|
40
40
|
completeRule: z.object({
|
|
41
41
|
periodGoal: z.union([z.number(), z.string()]).describe("Goal value to reach (e.g., 5 for 5 purchases, 100 for 100 points)."),
|
|
42
42
|
period: z.object({
|
|
43
|
-
type: AchievementPeriodTypeEnum.describe("Period type.
|
|
44
|
-
"
|
|
43
|
+
type: AchievementPeriodTypeEnum.describe("Period type. BUSINESS DECISION: 'day' with consecutive=1 = all-time tracking (for one-time badges). " +
|
|
44
|
+
"'calendarDays' with consecutive=N = streak tracking (for N consecutive days). " +
|
|
45
|
+
"BUSINESS IMPACT: Using streak settings for a one-time badge means members must act on consecutive days to earn it -- nobody will."),
|
|
45
46
|
value: z.number().optional().describe("Period value (e.g., 7 for 'last 7 days' when type='last_day'). Usually omit for simple achievements."),
|
|
46
47
|
consecutive: z.number().min(1).describe("⭐ CONSECUTIVE PERIODS: For ONE-TIME achievements (first purchase): use consecutive=1. " +
|
|
47
48
|
"For STREAKS (7 consecutive days): use consecutive=7 with type='calendarDays'. " +
|
|
@@ -54,26 +55,28 @@ const AchievementRuleInputSchema = z.object({
|
|
|
54
55
|
aggregation: z.object({
|
|
55
56
|
type: AchievementAggregationTypeEnum.describe("How to aggregate: 'quantity' (count events). NOTE: Only 'quantity' is supported by the API."),
|
|
56
57
|
}).describe("Value aggregation. Use type='quantity' for event counting. NOTE: 'sum', 'average', 'min', 'max' are NOT supported by the API."),
|
|
57
|
-
conditions: z.array(z.record(z.unknown())).optional().describe("Conditions that must be met."
|
|
58
|
+
conditions: z.array(z.record(z.unknown())).optional().describe("Conditions that must be met for rule progress. Same structure as campaign conditions: " +
|
|
59
|
+
"{ operator: 'is_greater_or_equal', attribute: 'transaction.grossValue', data: 100 }. " +
|
|
60
|
+
"For labels: { operator: 'has_at_least_one_label', attribute: 'transaction.labels', data: [{key: 'category', value: 'electronics'}] }."),
|
|
58
61
|
limit: z.object({
|
|
59
62
|
value: z.number().optional().describe("Max events per interval (e.g., 1 for once-per-day limit)."),
|
|
60
63
|
interval: z.object({
|
|
61
|
-
type: z.string().describe("Interval type: 'calendarDays', 'calendarWeeks',
|
|
62
|
-
value: z.number().optional().describe("Interval
|
|
64
|
+
type: z.string().describe("Interval type. Valid values: 'calendarDays' (NOT 'days'), 'calendarWeeks' (NOT 'weeks'), 'calendarMonths', 'calendarYears'."),
|
|
65
|
+
value: z.number().optional().describe("Interval length (e.g., 1 for every 1 calendar day)."),
|
|
63
66
|
}).optional().describe("Time interval for the limit."),
|
|
64
|
-
}).optional().describe("
|
|
65
|
-
"For
|
|
67
|
+
}).optional().describe("Only for streak achievements -- DO NOT set for one-time badges. " +
|
|
68
|
+
"BUSINESS IMPACT: Controls how events are counted per period. For streaks: { value: 1, interval: { type: 'calendarDays', value: 1 } } ensures max 1 event per day counts toward the streak."),
|
|
66
69
|
uniqueReferee: z.boolean().optional().describe("Whether referee must be unique (for referral achievements)."),
|
|
67
70
|
});
|
|
68
71
|
export const AchievementListInputSchema = {
|
|
69
|
-
storeCode: z.string().optional().describe("
|
|
72
|
+
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."),
|
|
70
73
|
page: z.number().optional().describe("Page number (default: 1)."),
|
|
71
74
|
perPage: z.number().optional().describe("Items per page (default: 10)."),
|
|
72
75
|
active: z.boolean().optional().describe("Filter by active status."),
|
|
73
76
|
name: z.string().optional().describe("Filter by achievement name."),
|
|
74
77
|
};
|
|
75
78
|
export const AchievementCreateInputSchema = {
|
|
76
|
-
storeCode: z.string().optional().describe("
|
|
79
|
+
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."),
|
|
77
80
|
translations: z.record(z.string(), z.object({
|
|
78
81
|
name: z.string(),
|
|
79
82
|
description: z.string().optional(),
|
|
@@ -87,47 +90,48 @@ export const AchievementCreateInputSchema = {
|
|
|
87
90
|
limit: z.object({
|
|
88
91
|
value: z.number().optional().describe("Maximum completions (e.g., 1 for one-time badges)."),
|
|
89
92
|
interval: z.object({
|
|
90
|
-
type: z.string(),
|
|
91
|
-
value: z.number().optional(),
|
|
92
|
-
}).optional(),
|
|
93
|
-
}).optional().describe("
|
|
94
|
-
"For
|
|
95
|
-
"
|
|
96
|
-
"IMPORTANT: Without limit.value=1, members can earn the badge unlimited times!"),
|
|
93
|
+
type: z.string().describe("Interval type. Valid values: 'calendarDays', 'calendarWeeks', 'calendarMonths', 'calendarYears'."),
|
|
94
|
+
value: z.number().optional().describe("Interval length (e.g., 1 for every 1 calendar period)."),
|
|
95
|
+
}).optional().describe("Interval for repeatable achievements (omit for one-time badges)."),
|
|
96
|
+
}).optional().describe("How many times a member can earn this achievement. " +
|
|
97
|
+
"BUSINESS DECISION: For one-time badges ('First Purchase'): set value=1 with NO interval. For repeatable challenges: omit or set higher. " +
|
|
98
|
+
"BUSINESS IMPACT: Without limit.value=1, members earn the badge unlimited times -- this defeats milestone purpose and can trigger unlimited achievement-based rewards."),
|
|
97
99
|
rules: z.array(AchievementRuleInputSchema).describe("Achievement rules defining completion criteria."),
|
|
98
100
|
badgeTypeId: z.string().optional().describe("Badge type ID to award upon completion. " +
|
|
99
101
|
"NOTE: This field may cause 'extra fields' validation errors in some API versions. " +
|
|
100
102
|
"If creation fails, try without badgeTypeId - the system will assign a default badge."),
|
|
101
103
|
};
|
|
102
104
|
export const AchievementGetInputSchema = {
|
|
103
|
-
storeCode: z.string().optional().describe("
|
|
105
|
+
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."),
|
|
104
106
|
achievementId: z.string().describe("The achievement ID (UUID) to retrieve."),
|
|
105
107
|
};
|
|
106
108
|
export const AchievementUpdateInputSchema = {
|
|
107
|
-
storeCode: z.string().optional().describe("
|
|
109
|
+
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."),
|
|
108
110
|
achievementId: z.string().describe("The achievement ID (UUID) to update."),
|
|
109
111
|
translations: z.record(z.string(), z.object({
|
|
110
112
|
name: z.string(),
|
|
111
113
|
description: z.string().optional(),
|
|
112
|
-
})).describe("Achievement name and description."),
|
|
114
|
+
})).describe("Achievement name and description. At least 'en' key required."),
|
|
113
115
|
active: z.boolean().optional().describe("Whether achievement is active."),
|
|
114
116
|
activity: z.object({
|
|
115
|
-
startsAt: z.string().optional(),
|
|
116
|
-
endsAt: z.string().optional(),
|
|
117
|
-
operator: z.string().optional(),
|
|
117
|
+
startsAt: z.string().optional().describe("ISO datetime when achievement becomes active (e.g., '2026-01-01T00:00:00+00:00')."),
|
|
118
|
+
endsAt: z.string().optional().describe("ISO datetime when achievement ends."),
|
|
119
|
+
operator: z.string().optional().describe("Activity condition operator: 'between' (both dates) or 'from' (start only) or 'to' (end only)."),
|
|
118
120
|
}).optional().describe("Time period configuration."),
|
|
119
121
|
limit: z.object({
|
|
120
|
-
value: z.number().optional(),
|
|
122
|
+
value: z.number().optional().describe("Maximum completions (e.g., 1 for one-time badges)."),
|
|
121
123
|
interval: z.object({
|
|
122
|
-
type: z.string(),
|
|
123
|
-
value: z.number().optional(),
|
|
124
|
-
}).optional(),
|
|
125
|
-
}).optional().describe("
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
type: z.string().describe("Interval type. Valid values: 'calendarDays', 'calendarWeeks', 'calendarMonths', 'calendarYears'."),
|
|
125
|
+
value: z.number().optional().describe("Interval length (e.g., 1 for every 1 calendar period)."),
|
|
126
|
+
}).optional().describe("Interval for repeatable achievements (omit for one-time badges)."),
|
|
127
|
+
}).optional().describe("Achievement limit. For ONE-TIME badges: { value: 1 } with NO interval. " +
|
|
128
|
+
"For repeatable: omit or set higher value."),
|
|
129
|
+
rules: z.array(AchievementRuleInputSchema).describe("Achievement rules. Use achievement_get first to retrieve current rules and include achievementRuleId for existing rules."),
|
|
130
|
+
badgeTypeId: z.string().optional().describe("Badge type ID to award. Use ol_badge_list() to find valid IDs. " +
|
|
131
|
+
"May cause 'extra fields' errors in some API versions - try without if creation fails."),
|
|
128
132
|
};
|
|
129
133
|
export const AchievementPatchInputSchema = {
|
|
130
|
-
storeCode: z.string().optional().describe("
|
|
134
|
+
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."),
|
|
131
135
|
achievementId: z.string().describe("The achievement ID (UUID) to patch."),
|
|
132
136
|
active: z.boolean().optional().describe("Whether achievement is active."),
|
|
133
137
|
translations: z.record(z.string(), z.object({
|
|
@@ -136,12 +140,12 @@ export const AchievementPatchInputSchema = {
|
|
|
136
140
|
})).optional().describe("Partial translation updates."),
|
|
137
141
|
};
|
|
138
142
|
export const AchievementGetMemberProgressInputSchema = {
|
|
139
|
-
storeCode: z.string().optional().describe("
|
|
143
|
+
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."),
|
|
140
144
|
memberId: z.string().describe("The member ID (UUID)."),
|
|
141
145
|
achievementId: z.string().describe("The achievement ID (UUID)."),
|
|
142
146
|
};
|
|
143
147
|
export const AchievementListMemberAchievementsInputSchema = {
|
|
144
|
-
storeCode: z.string().optional().describe("
|
|
148
|
+
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."),
|
|
145
149
|
memberId: z.string().describe("The member ID (UUID)."),
|
|
146
150
|
page: z.number().optional().describe("Page number (default: 1)."),
|
|
147
151
|
perPage: z.number().optional().describe("Items per page (default: 25)."),
|
package/dist/tools/analytics.js
CHANGED
|
@@ -4,29 +4,29 @@ import { formatApiError } from "../utils/errors.js";
|
|
|
4
4
|
import { getStoreCode } from "../config.js";
|
|
5
5
|
// Input Schemas
|
|
6
6
|
export const AnalyticsTiersInputSchema = {
|
|
7
|
-
storeCode: z.string().optional().describe("
|
|
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
|
};
|
|
9
9
|
export const AnalyticsMembersInputSchema = {
|
|
10
|
-
storeCode: z.string().optional().describe("
|
|
10
|
+
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."),
|
|
11
11
|
withTransaction: z.boolean().optional().describe("Filter: true for members with transactions, false for members without, omit for all."),
|
|
12
12
|
};
|
|
13
13
|
export const AnalyticsPointsInputSchema = {
|
|
14
|
-
storeCode: z.string().optional().describe("
|
|
14
|
+
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."),
|
|
15
15
|
};
|
|
16
16
|
export const AnalyticsTransactionsInputSchema = {
|
|
17
|
-
storeCode: z.string().optional().describe("
|
|
17
|
+
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."),
|
|
18
18
|
};
|
|
19
19
|
export const AnalyticsReferralsInputSchema = {
|
|
20
|
-
storeCode: z.string().optional().describe("
|
|
20
|
+
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."),
|
|
21
21
|
};
|
|
22
22
|
export const AnalyticsCampaignsInputSchema = {
|
|
23
|
-
storeCode: z.string().optional().describe("
|
|
23
|
+
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."),
|
|
24
24
|
page: z.number().optional().describe("Page number (default: 1)."),
|
|
25
25
|
perPage: z.number().optional().describe("Items per page (default: 25)."),
|
|
26
26
|
executedAt: z.string().optional().describe("Filter by execution date (ISO format)."),
|
|
27
27
|
};
|
|
28
28
|
export const AnalyticsDashboardInputSchema = {
|
|
29
|
-
storeCode: z.string().optional().describe("
|
|
29
|
+
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."),
|
|
30
30
|
dataType: z.enum([
|
|
31
31
|
"registeredMembers", "activeMembers", "revenue", "avgSpending",
|
|
32
32
|
"transactions", "avgTransactionValue", "avgNumberOfTransactions"
|
|
@@ -36,7 +36,7 @@ export const AnalyticsDashboardInputSchema = {
|
|
|
36
36
|
intervalEndDate: z.string().optional().describe("End date (YYYY-MM-DD format)."),
|
|
37
37
|
};
|
|
38
38
|
export const AnalyticsUnitsInputSchema = {
|
|
39
|
-
storeCode: z.string().optional().describe("
|
|
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
|
walletTypeCode: z.string().describe("Wallet type code (e.g., 'default' or 'points')."),
|
|
41
41
|
dataType: z.enum([
|
|
42
42
|
"unitsIssued", "unitsSpent", "unitsExpired", "unitsPending", "unitsActive"
|
|
@@ -46,7 +46,7 @@ export const AnalyticsUnitsInputSchema = {
|
|
|
46
46
|
intervalEndDate: z.string().optional().describe("End date (YYYY-MM-DD format)."),
|
|
47
47
|
};
|
|
48
48
|
export const AnalyticsCampaignDetailInputSchema = {
|
|
49
|
-
storeCode: z.string().optional().describe("
|
|
49
|
+
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."),
|
|
50
50
|
campaignId: z.string().describe("The campaign ID to get analytics for."),
|
|
51
51
|
};
|
|
52
52
|
// Handler functions
|
package/dist/tools/badge.js
CHANGED
|
@@ -4,18 +4,18 @@ import { formatApiError } from "../utils/errors.js";
|
|
|
4
4
|
import { getStoreCode } from "../config.js";
|
|
5
5
|
// Input Schemas
|
|
6
6
|
export const BadgeListInputSchema = {
|
|
7
|
-
storeCode: z.string().optional().describe("
|
|
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: 10)."),
|
|
10
10
|
name: z.string().optional().describe("Filter by badge name."),
|
|
11
11
|
badgeTypeId: z.string().optional().describe("Filter by specific badge type ID."),
|
|
12
12
|
};
|
|
13
13
|
export const BadgeGetInputSchema = {
|
|
14
|
-
storeCode: z.string().optional().describe("
|
|
14
|
+
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."),
|
|
15
15
|
badgeTypeId: z.string().describe("The badge type ID (UUID) to retrieve."),
|
|
16
16
|
};
|
|
17
17
|
export const BadgeUpdateInputSchema = {
|
|
18
|
-
storeCode: z.string().optional().describe("
|
|
18
|
+
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."),
|
|
19
19
|
badgeTypeId: z.string().describe("The badge type ID (UUID) to update."),
|
|
20
20
|
name: z.string().describe("Badge name (REQUIRED). API requires name as a direct field."),
|
|
21
21
|
translations: z.record(z.string(), z.object({
|
|
@@ -26,7 +26,7 @@ export const BadgeUpdateInputSchema = {
|
|
|
26
26
|
active: z.boolean().optional().describe("Whether badge type is active."),
|
|
27
27
|
};
|
|
28
28
|
export const BadgeGetMemberBadgesInputSchema = {
|
|
29
|
-
storeCode: z.string().optional().describe("
|
|
29
|
+
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."),
|
|
30
30
|
memberId: z.string().describe("The member ID (UUID)."),
|
|
31
31
|
page: z.number().optional().describe("Page number (default: 1)."),
|
|
32
32
|
perPage: z.number().optional().describe("Items per page (default: 10)."),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { apiGet, apiPost, apiPut, apiPatch, apiDelete } from "../../client/http.js";
|
|
2
|
-
import { formatApiError } from "../../utils/errors.js";
|
|
2
|
+
import { formatApiError, OpenLoyaltyError } from "../../utils/errors.js";
|
|
3
3
|
import { getStoreCode } from "../../config.js";
|
|
4
4
|
// Core CRUD handlers
|
|
5
5
|
export async function campaignList(input) {
|
|
@@ -95,6 +95,40 @@ export async function campaignCreate(input) {
|
|
|
95
95
|
return { campaignId: response.campaignId };
|
|
96
96
|
}
|
|
97
97
|
catch (error) {
|
|
98
|
+
const axiosError = error;
|
|
99
|
+
const apiErrors = axiosError.response?.data?.errors || [];
|
|
100
|
+
const allMessages = [
|
|
101
|
+
error instanceof Error ? error.message : "",
|
|
102
|
+
axiosError.response?.data?.message || "",
|
|
103
|
+
...apiErrors.map(e => `${e.path || ""}: ${e.message}`)
|
|
104
|
+
].join(" ").toLowerCase();
|
|
105
|
+
if (allMessages.includes("trigger") && allMessages.includes("choice")) {
|
|
106
|
+
throw new OpenLoyaltyError({
|
|
107
|
+
code: "INVALID_TRIGGER",
|
|
108
|
+
message: "Invalid campaign trigger type",
|
|
109
|
+
hint: "Valid trigger values: 'transaction', 'custom_event', 'geolocation', 'time', 'achievement'. For custom_event, also set event='your_event_type'. For achievement, set achievementId='uuid'.",
|
|
110
|
+
relatedTool: "ol_campaign_create",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (allMessages.includes("operator") || (allMessages.includes("condition") && allMessages.includes("choice"))) {
|
|
114
|
+
throw new OpenLoyaltyError({
|
|
115
|
+
code: "INVALID_CONDITION",
|
|
116
|
+
message: "Invalid rule condition in campaign",
|
|
117
|
+
hint: "Use full operator names: 'is_greater_or_equal' (NOT 'gte'), 'is_less_or_equal' (NOT 'lte'). " +
|
|
118
|
+
"Use full attribute paths: 'transaction.grossValue' (NOT 'grossValue'). " +
|
|
119
|
+
"Example: { operator: 'is_greater_or_equal', attribute: 'transaction.grossValue', data: 100 }.",
|
|
120
|
+
relatedTool: "ol_campaign_create",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (input.trigger === "custom_event" && !input.event && allMessages.includes("event")) {
|
|
124
|
+
throw new OpenLoyaltyError({
|
|
125
|
+
code: "MISSING_EVENT",
|
|
126
|
+
message: "Missing event field for custom_event trigger",
|
|
127
|
+
hint: "For trigger='custom_event', you MUST also set event='your_event_code'. " +
|
|
128
|
+
"Use ol_custom_event_schema_list() to find valid event codes.",
|
|
129
|
+
relatedTool: "ol_campaign_create",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
98
132
|
throw formatApiError(error, "ol_campaign_create");
|
|
99
133
|
}
|
|
100
134
|
}
|
|
@@ -150,11 +150,11 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
150
150
|
tiers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
151
151
|
segments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
152
152
|
}, "strip", import("zod").ZodTypeAny, {
|
|
153
|
-
target: "all" | "
|
|
153
|
+
target: "all" | "tier" | "segment";
|
|
154
154
|
tiers?: string[] | undefined;
|
|
155
155
|
segments?: string[] | undefined;
|
|
156
156
|
}, {
|
|
157
|
-
target: "all" | "
|
|
157
|
+
target: "all" | "tier" | "segment";
|
|
158
158
|
tiers?: string[] | undefined;
|
|
159
159
|
segments?: string[] | undefined;
|
|
160
160
|
}>>;
|
|
@@ -163,11 +163,11 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
163
163
|
tiers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
164
164
|
segments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
165
165
|
}, "strip", import("zod").ZodTypeAny, {
|
|
166
|
-
target: "
|
|
166
|
+
target: "tier" | "segment";
|
|
167
167
|
tiers?: string[] | undefined;
|
|
168
168
|
segments?: string[] | undefined;
|
|
169
169
|
}, {
|
|
170
|
-
target: "
|
|
170
|
+
target: "tier" | "segment";
|
|
171
171
|
tiers?: string[] | undefined;
|
|
172
172
|
segments?: string[] | undefined;
|
|
173
173
|
}>>;
|
|
@@ -377,17 +377,17 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
377
377
|
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
378
378
|
target: import("zod").ZodOptional<import("zod").ZodEnum<["self", "referrer"]>>;
|
|
379
379
|
effects: import("zod").ZodArray<import("zod").ZodObject<{
|
|
380
|
-
effect: import("zod").
|
|
380
|
+
effect: import("zod").ZodEnum<["give_points", "give_reward", "deduct_unit", "assign_member_custom_attribute", "remove_member_custom_attribute"]>;
|
|
381
381
|
pointsRule: import("zod").ZodOptional<import("zod").ZodString>;
|
|
382
382
|
walletCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
383
383
|
rewardId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
384
384
|
}, "strip", import("zod").ZodTypeAny, {
|
|
385
|
-
effect:
|
|
385
|
+
effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
|
|
386
386
|
walletCode?: string | undefined;
|
|
387
387
|
rewardId?: string | undefined;
|
|
388
388
|
pointsRule?: string | undefined;
|
|
389
389
|
}, {
|
|
390
|
-
effect:
|
|
390
|
+
effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
|
|
391
391
|
walletCode?: string | undefined;
|
|
392
392
|
rewardId?: string | undefined;
|
|
393
393
|
pointsRule?: string | undefined;
|
|
@@ -395,20 +395,20 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
395
395
|
conditions: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
|
|
396
396
|
operator: import("zod").ZodString;
|
|
397
397
|
attribute: import("zod").ZodString;
|
|
398
|
-
data: import("zod").
|
|
398
|
+
data: import("zod").ZodUnknown;
|
|
399
399
|
}, "strip", import("zod").ZodTypeAny, {
|
|
400
400
|
attribute: string;
|
|
401
401
|
operator: string;
|
|
402
|
-
data?:
|
|
402
|
+
data?: unknown;
|
|
403
403
|
}, {
|
|
404
404
|
attribute: string;
|
|
405
405
|
operator: string;
|
|
406
|
-
data?:
|
|
406
|
+
data?: unknown;
|
|
407
407
|
}>, "many">>;
|
|
408
408
|
}, "strip", import("zod").ZodTypeAny, {
|
|
409
409
|
name: string;
|
|
410
410
|
effects: {
|
|
411
|
-
effect:
|
|
411
|
+
effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
|
|
412
412
|
walletCode?: string | undefined;
|
|
413
413
|
rewardId?: string | undefined;
|
|
414
414
|
pointsRule?: string | undefined;
|
|
@@ -417,13 +417,13 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
417
417
|
conditions?: {
|
|
418
418
|
attribute: string;
|
|
419
419
|
operator: string;
|
|
420
|
-
data?:
|
|
420
|
+
data?: unknown;
|
|
421
421
|
}[] | undefined;
|
|
422
422
|
target?: "self" | "referrer" | undefined;
|
|
423
423
|
}, {
|
|
424
424
|
name: string;
|
|
425
425
|
effects: {
|
|
426
|
-
effect:
|
|
426
|
+
effect: "give_points" | "give_reward" | "deduct_unit" | "assign_member_custom_attribute" | "remove_member_custom_attribute";
|
|
427
427
|
walletCode?: string | undefined;
|
|
428
428
|
rewardId?: string | undefined;
|
|
429
429
|
pointsRule?: string | undefined;
|
|
@@ -432,7 +432,7 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
432
432
|
conditions?: {
|
|
433
433
|
attribute: string;
|
|
434
434
|
operator: string;
|
|
435
|
-
data?:
|
|
435
|
+
data?: unknown;
|
|
436
436
|
}[] | undefined;
|
|
437
437
|
target?: "self" | "referrer" | undefined;
|
|
438
438
|
}>, "many">;
|
|
@@ -441,11 +441,11 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
441
441
|
tiers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
442
442
|
segments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
443
443
|
}, "strip", import("zod").ZodTypeAny, {
|
|
444
|
-
target: "all" | "
|
|
444
|
+
target: "all" | "tier" | "segment";
|
|
445
445
|
tiers?: string[] | undefined;
|
|
446
446
|
segments?: string[] | undefined;
|
|
447
447
|
}, {
|
|
448
|
-
target: "all" | "
|
|
448
|
+
target: "all" | "tier" | "segment";
|
|
449
449
|
tiers?: string[] | undefined;
|
|
450
450
|
segments?: string[] | undefined;
|
|
451
451
|
}>>;
|
|
@@ -454,70 +454,133 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
454
454
|
tiers: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
455
455
|
segments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
|
|
456
456
|
}, "strip", import("zod").ZodTypeAny, {
|
|
457
|
-
target: "
|
|
457
|
+
target: "tier" | "segment";
|
|
458
458
|
tiers?: string[] | undefined;
|
|
459
459
|
segments?: string[] | undefined;
|
|
460
460
|
}, {
|
|
461
|
-
target: "
|
|
461
|
+
target: "tier" | "segment";
|
|
462
462
|
tiers?: string[] | undefined;
|
|
463
463
|
segments?: string[] | undefined;
|
|
464
464
|
}>>;
|
|
465
465
|
limits: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
466
466
|
points: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
467
467
|
value: import("zod").ZodNumber;
|
|
468
|
-
interval: import("zod").ZodOptional<import("zod").
|
|
468
|
+
interval: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
469
|
+
type: import("zod").ZodEnum<["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"]>;
|
|
470
|
+
value: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
471
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
472
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
473
|
+
value?: number | undefined;
|
|
474
|
+
}, {
|
|
475
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
476
|
+
value?: number | undefined;
|
|
477
|
+
}>>;
|
|
469
478
|
}, "strip", import("zod").ZodTypeAny, {
|
|
470
479
|
value: number;
|
|
471
|
-
interval?:
|
|
480
|
+
interval?: {
|
|
481
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
482
|
+
value?: number | undefined;
|
|
483
|
+
} | undefined;
|
|
472
484
|
}, {
|
|
473
485
|
value: number;
|
|
474
|
-
interval?:
|
|
486
|
+
interval?: {
|
|
487
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
488
|
+
value?: number | undefined;
|
|
489
|
+
} | undefined;
|
|
475
490
|
}>>;
|
|
476
491
|
pointsPerMember: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
477
492
|
value: import("zod").ZodNumber;
|
|
478
|
-
interval: import("zod").ZodOptional<import("zod").
|
|
493
|
+
interval: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
494
|
+
type: import("zod").ZodEnum<["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"]>;
|
|
495
|
+
value: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
496
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
497
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
498
|
+
value?: number | undefined;
|
|
499
|
+
}, {
|
|
500
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
501
|
+
value?: number | undefined;
|
|
502
|
+
}>>;
|
|
479
503
|
}, "strip", import("zod").ZodTypeAny, {
|
|
480
504
|
value: number;
|
|
481
|
-
interval?:
|
|
505
|
+
interval?: {
|
|
506
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
507
|
+
value?: number | undefined;
|
|
508
|
+
} | undefined;
|
|
482
509
|
}, {
|
|
483
510
|
value: number;
|
|
484
|
-
interval?:
|
|
511
|
+
interval?: {
|
|
512
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
513
|
+
value?: number | undefined;
|
|
514
|
+
} | undefined;
|
|
485
515
|
}>>;
|
|
486
516
|
executionsPerMember: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
487
517
|
value: import("zod").ZodNumber;
|
|
488
|
-
interval: import("zod").ZodOptional<import("zod").
|
|
518
|
+
interval: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
519
|
+
type: import("zod").ZodEnum<["calendarDays", "calendarWeeks", "calendarMonths", "calendarYears"]>;
|
|
520
|
+
value: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
521
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
522
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
523
|
+
value?: number | undefined;
|
|
524
|
+
}, {
|
|
525
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
526
|
+
value?: number | undefined;
|
|
527
|
+
}>>;
|
|
489
528
|
}, "strip", import("zod").ZodTypeAny, {
|
|
490
529
|
value: number;
|
|
491
|
-
interval?:
|
|
530
|
+
interval?: {
|
|
531
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
532
|
+
value?: number | undefined;
|
|
533
|
+
} | undefined;
|
|
492
534
|
}, {
|
|
493
535
|
value: number;
|
|
494
|
-
interval?:
|
|
536
|
+
interval?: {
|
|
537
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
538
|
+
value?: number | undefined;
|
|
539
|
+
} | undefined;
|
|
495
540
|
}>>;
|
|
496
541
|
}, "strip", import("zod").ZodTypeAny, {
|
|
497
542
|
points?: {
|
|
498
543
|
value: number;
|
|
499
|
-
interval?:
|
|
544
|
+
interval?: {
|
|
545
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
546
|
+
value?: number | undefined;
|
|
547
|
+
} | undefined;
|
|
500
548
|
} | undefined;
|
|
501
549
|
pointsPerMember?: {
|
|
502
550
|
value: number;
|
|
503
|
-
interval?:
|
|
551
|
+
interval?: {
|
|
552
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
553
|
+
value?: number | undefined;
|
|
554
|
+
} | undefined;
|
|
504
555
|
} | undefined;
|
|
505
556
|
executionsPerMember?: {
|
|
506
557
|
value: number;
|
|
507
|
-
interval?:
|
|
558
|
+
interval?: {
|
|
559
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
560
|
+
value?: number | undefined;
|
|
561
|
+
} | undefined;
|
|
508
562
|
} | undefined;
|
|
509
563
|
}, {
|
|
510
564
|
points?: {
|
|
511
565
|
value: number;
|
|
512
|
-
interval?:
|
|
566
|
+
interval?: {
|
|
567
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
568
|
+
value?: number | undefined;
|
|
569
|
+
} | undefined;
|
|
513
570
|
} | undefined;
|
|
514
571
|
pointsPerMember?: {
|
|
515
572
|
value: number;
|
|
516
|
-
interval?:
|
|
573
|
+
interval?: {
|
|
574
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
575
|
+
value?: number | undefined;
|
|
576
|
+
} | undefined;
|
|
517
577
|
} | undefined;
|
|
518
578
|
executionsPerMember?: {
|
|
519
579
|
value: number;
|
|
520
|
-
interval?:
|
|
580
|
+
interval?: {
|
|
581
|
+
type: "calendarDays" | "calendarWeeks" | "calendarMonths" | "calendarYears";
|
|
582
|
+
value?: number | undefined;
|
|
583
|
+
} | undefined;
|
|
521
584
|
} | undefined;
|
|
522
585
|
}>>;
|
|
523
586
|
active: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
@@ -561,7 +624,7 @@ export declare const campaignToolDefinitions: readonly [{
|
|
|
561
624
|
}, {
|
|
562
625
|
readonly name: "ol_campaign_simulate";
|
|
563
626
|
readonly title: "Simulate Campaign Effects";
|
|
564
|
-
readonly description:
|
|
627
|
+
readonly description: string;
|
|
565
628
|
readonly readOnly: true;
|
|
566
629
|
readonly inputSchema: {
|
|
567
630
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
@@ -20,17 +20,14 @@ export const campaignToolDefinitions = [
|
|
|
20
20
|
{
|
|
21
21
|
name: "ol_campaign_create",
|
|
22
22
|
title: "Create Campaign",
|
|
23
|
-
description: "Create campaign
|
|
24
|
-
"
|
|
25
|
-
"1.
|
|
26
|
-
"2.
|
|
27
|
-
"3.
|
|
28
|
-
"4.
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"CONDITIONS: Use operator='is_greater_or_equal' (NOT 'gte'), attribute='transaction.grossValue', data=100. " +
|
|
32
|
-
"For labels: operator='has_at_least_one_label', attribute='transaction.labels', data=[{key:'name',value:'val'}]. " +
|
|
33
|
-
"To target ALL members, OMIT the audience parameter entirely.",
|
|
23
|
+
description: "Create a campaign (earning rule) that automatically awards points or rewards when triggered. " +
|
|
24
|
+
"KEY DECISIONS (confirm with user if not specified): " +
|
|
25
|
+
"1. Points formula -- fixed ('100') or dynamic ('transaction.grossValue * 10')? This determines cost per transaction. " +
|
|
26
|
+
"2. Budget caps -- total points limit and per-member limit? Without limits, the campaign has uncapped financial exposure. " +
|
|
27
|
+
"3. Audience -- all members, or specific tiers/segments? " +
|
|
28
|
+
"4. End date -- campaigns without endsAt run forever, which is a budget commitment. " +
|
|
29
|
+
"REQUIRED: type, trigger, translations.en.name, activity.startsAt, rules with effects. " +
|
|
30
|
+
"In effects array, use key 'effect' (NOT 'type'). pointsRule is a STRING: '100' not 100.",
|
|
34
31
|
readOnly: false,
|
|
35
32
|
inputSchema: CampaignCreateInputSchema,
|
|
36
33
|
handler: campaignCreate,
|
|
@@ -71,7 +68,12 @@ export const campaignToolDefinitions = [
|
|
|
71
68
|
{
|
|
72
69
|
name: "ol_campaign_simulate",
|
|
73
70
|
title: "Simulate Campaign Effects",
|
|
74
|
-
description: "Simulate campaign effects without executing them. Use to preview what points/rewards a transaction would earn.
|
|
71
|
+
description: "Simulate campaign effects without executing them. Use to preview what points/rewards a transaction would earn. " +
|
|
72
|
+
"Example for transaction trigger: { trigger: 'transaction', " +
|
|
73
|
+
"transaction: { grossValue: 100, documentNumber: 'SIM-001', purchasedAt: '2026-01-01T10:00:00Z', " +
|
|
74
|
+
"items: [{ sku: 'SKU-1', name: 'Product', grossValue: 100, qty: 1 }] }, " +
|
|
75
|
+
"customer: { customerId: 'member-uuid' } }. " +
|
|
76
|
+
"Returns simulated effects grouped by campaign.",
|
|
75
77
|
readOnly: true,
|
|
76
78
|
inputSchema: CampaignSimulateInputSchema,
|
|
77
79
|
handler: campaignSimulate,
|