@open-loyalty/mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +654 -0
  3. package/dist/client/http.d.ts +8 -0
  4. package/dist/client/http.js +69 -0
  5. package/dist/config.d.ts +17 -0
  6. package/dist/config.js +40 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +20 -0
  9. package/dist/server.d.ts +4 -0
  10. package/dist/server.js +334 -0
  11. package/dist/tools/achievement.d.ts +983 -0
  12. package/dist/tools/achievement.js +311 -0
  13. package/dist/tools/admin.d.ts +153 -0
  14. package/dist/tools/admin.js +193 -0
  15. package/dist/tools/analytics.d.ts +162 -0
  16. package/dist/tools/analytics.js +245 -0
  17. package/dist/tools/apikey.d.ts +72 -0
  18. package/dist/tools/apikey.js +78 -0
  19. package/dist/tools/audit.d.ts +107 -0
  20. package/dist/tools/audit.js +90 -0
  21. package/dist/tools/badge.d.ts +135 -0
  22. package/dist/tools/badge.js +165 -0
  23. package/dist/tools/campaign.d.ts +1775 -0
  24. package/dist/tools/campaign.js +724 -0
  25. package/dist/tools/export.d.ts +110 -0
  26. package/dist/tools/export.js +147 -0
  27. package/dist/tools/import.d.ts +110 -0
  28. package/dist/tools/import.js +126 -0
  29. package/dist/tools/index.d.ts +22 -0
  30. package/dist/tools/index.js +527 -0
  31. package/dist/tools/member.d.ts +345 -0
  32. package/dist/tools/member.js +358 -0
  33. package/dist/tools/member.test.d.ts +1 -0
  34. package/dist/tools/member.test.js +213 -0
  35. package/dist/tools/points.d.ts +188 -0
  36. package/dist/tools/points.js +306 -0
  37. package/dist/tools/points.test.d.ts +1 -0
  38. package/dist/tools/points.test.js +292 -0
  39. package/dist/tools/reward.d.ts +261 -0
  40. package/dist/tools/reward.js +371 -0
  41. package/dist/tools/reward.test.d.ts +1 -0
  42. package/dist/tools/reward.test.js +240 -0
  43. package/dist/tools/role.d.ts +161 -0
  44. package/dist/tools/role.js +160 -0
  45. package/dist/tools/segment.d.ts +797 -0
  46. package/dist/tools/segment.js +299 -0
  47. package/dist/tools/store.d.ts +101 -0
  48. package/dist/tools/store.js +117 -0
  49. package/dist/tools/tierset.d.ts +288 -0
  50. package/dist/tools/tierset.js +244 -0
  51. package/dist/tools/transaction.d.ts +357 -0
  52. package/dist/tools/transaction.js +242 -0
  53. package/dist/tools/transaction.test.d.ts +1 -0
  54. package/dist/tools/transaction.test.js +235 -0
  55. package/dist/tools/wallet-type.d.ts +32 -0
  56. package/dist/tools/wallet-type.js +58 -0
  57. package/dist/tools/webhook.d.ts +179 -0
  58. package/dist/tools/webhook.js +171 -0
  59. package/dist/types/schemas/achievement.d.ts +1116 -0
  60. package/dist/types/schemas/achievement.js +172 -0
  61. package/dist/types/schemas/admin.d.ts +263 -0
  62. package/dist/types/schemas/admin.js +99 -0
  63. package/dist/types/schemas/analytics.d.ts +542 -0
  64. package/dist/types/schemas/analytics.js +130 -0
  65. package/dist/types/schemas/badge.d.ts +131 -0
  66. package/dist/types/schemas/badge.js +48 -0
  67. package/dist/types/schemas/campaign.d.ts +2005 -0
  68. package/dist/types/schemas/campaign.js +189 -0
  69. package/dist/types/schemas/common.d.ts +52 -0
  70. package/dist/types/schemas/common.js +26 -0
  71. package/dist/types/schemas/export.d.ts +127 -0
  72. package/dist/types/schemas/export.js +43 -0
  73. package/dist/types/schemas/import.d.ts +344 -0
  74. package/dist/types/schemas/import.js +68 -0
  75. package/dist/types/schemas/member.d.ts +443 -0
  76. package/dist/types/schemas/member.js +92 -0
  77. package/dist/types/schemas/points.d.ts +188 -0
  78. package/dist/types/schemas/points.js +54 -0
  79. package/dist/types/schemas/reward.d.ts +278 -0
  80. package/dist/types/schemas/reward.js +69 -0
  81. package/dist/types/schemas/role.d.ts +260 -0
  82. package/dist/types/schemas/role.js +75 -0
  83. package/dist/types/schemas/segment.d.ts +592 -0
  84. package/dist/types/schemas/segment.js +114 -0
  85. package/dist/types/schemas/tierset.d.ts +552 -0
  86. package/dist/types/schemas/tierset.js +87 -0
  87. package/dist/types/schemas/transaction.d.ts +1022 -0
  88. package/dist/types/schemas/transaction.js +63 -0
  89. package/dist/types/schemas/wallet-type.d.ts +99 -0
  90. package/dist/types/schemas/wallet-type.js +17 -0
  91. package/dist/types/schemas/webhook.d.ts +195 -0
  92. package/dist/types/schemas/webhook.js +39 -0
  93. package/dist/utils/cursor.d.ts +84 -0
  94. package/dist/utils/cursor.js +117 -0
  95. package/dist/utils/errors.d.ts +12 -0
  96. package/dist/utils/errors.js +69 -0
  97. package/dist/utils/pagination.d.ts +39 -0
  98. package/dist/utils/pagination.js +77 -0
  99. package/package.json +65 -0
@@ -0,0 +1,311 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPost, apiPut, apiPatch } from "../client/http.js";
3
+ import { formatApiError } from "../utils/errors.js";
4
+ import { getConfig } from "../config.js";
5
+ // Input Schemas
6
+ export const AchievementListInputSchema = {
7
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
8
+ page: z.number().optional().describe("Page number (default: 1)."),
9
+ perPage: z.number().optional().describe("Items per page (default: 10)."),
10
+ active: z.boolean().optional().describe("Filter by active status."),
11
+ name: z.string().optional().describe("Filter by achievement name."),
12
+ };
13
+ // Rule input schema
14
+ const AchievementRuleInputSchema = z.object({
15
+ achievementRuleId: z.string().optional().describe("Rule ID (for updates)."),
16
+ translations: z.record(z.string(), z.object({
17
+ name: z.string(),
18
+ description: z.string().optional(),
19
+ })).optional().describe("Rule name and description translations."),
20
+ trigger: z.string().optional().describe("Event type: transaction, custom_event, points_transfer, etc."),
21
+ type: z.string().optional().describe("Rule type."),
22
+ event: z.string().optional().describe("Custom event code for custom_event trigger."),
23
+ completeRule: z.object({
24
+ periodGoal: z.union([z.number(), z.string()]).describe("Goal value to reach."),
25
+ period: z.object({
26
+ consecutive: z.number().optional(),
27
+ value: z.number().optional(),
28
+ }).optional(),
29
+ uniqueAttribute: z.string().optional(),
30
+ }).describe("Completion goal configuration."),
31
+ aggregation: z.object({
32
+ rule: z.string().optional(),
33
+ }).optional().describe("Value aggregation."),
34
+ conditions: z.array(z.record(z.unknown())).optional().describe("Conditions that must be met."),
35
+ limit: z.object({
36
+ value: z.number().optional(),
37
+ interval: z.object({
38
+ type: z.string(),
39
+ value: z.number().optional(),
40
+ }).optional(),
41
+ }).optional().describe("Per-rule limit."),
42
+ uniqueReferee: z.boolean().optional().describe("Whether referee must be unique."),
43
+ });
44
+ export const AchievementCreateInputSchema = {
45
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
46
+ translations: z.record(z.string(), z.object({
47
+ name: z.string(),
48
+ description: z.string().optional(),
49
+ })).describe("Achievement name and description. At least 'en' key required."),
50
+ active: z.boolean().optional().describe("Whether achievement is active (default: false)."),
51
+ activity: z.object({
52
+ startsAt: z.string().optional().describe("ISO datetime when achievement becomes active."),
53
+ endsAt: z.string().optional().describe("ISO datetime when achievement ends."),
54
+ operator: z.string().optional().describe("Activity condition operator."),
55
+ }).optional().describe("Time period configuration."),
56
+ limit: z.object({
57
+ value: z.number().optional().describe("Maximum completions."),
58
+ interval: z.object({
59
+ type: z.string(),
60
+ value: z.number().optional(),
61
+ }).optional(),
62
+ }).optional().describe("Overall limit configuration."),
63
+ rules: z.array(AchievementRuleInputSchema).describe("Achievement rules defining completion criteria."),
64
+ badgeTypeId: z.string().optional().describe("Badge type ID to award upon completion."),
65
+ };
66
+ export const AchievementGetInputSchema = {
67
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
68
+ achievementId: z.string().describe("The achievement ID (UUID) to retrieve."),
69
+ };
70
+ export const AchievementUpdateInputSchema = {
71
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
72
+ achievementId: z.string().describe("The achievement ID (UUID) to update."),
73
+ translations: z.record(z.string(), z.object({
74
+ name: z.string(),
75
+ description: z.string().optional(),
76
+ })).describe("Achievement name and description."),
77
+ active: z.boolean().optional().describe("Whether achievement is active."),
78
+ activity: z.object({
79
+ startsAt: z.string().optional(),
80
+ endsAt: z.string().optional(),
81
+ operator: z.string().optional(),
82
+ }).optional().describe("Time period configuration."),
83
+ limit: z.object({
84
+ value: z.number().optional(),
85
+ interval: z.object({
86
+ type: z.string(),
87
+ value: z.number().optional(),
88
+ }).optional(),
89
+ }).optional().describe("Limit configuration."),
90
+ rules: z.array(AchievementRuleInputSchema).describe("Achievement rules."),
91
+ badgeTypeId: z.string().optional().describe("Badge type ID to award."),
92
+ };
93
+ export const AchievementPatchInputSchema = {
94
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
95
+ achievementId: z.string().describe("The achievement ID (UUID) to patch."),
96
+ active: z.boolean().optional().describe("Whether achievement is active."),
97
+ translations: z.record(z.string(), z.object({
98
+ name: z.string().optional(),
99
+ description: z.string().optional(),
100
+ })).optional().describe("Partial translation updates."),
101
+ };
102
+ export const AchievementGetMemberProgressInputSchema = {
103
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
104
+ memberId: z.string().describe("The member ID (UUID)."),
105
+ achievementId: z.string().describe("The achievement ID (UUID)."),
106
+ };
107
+ export const AchievementListMemberAchievementsInputSchema = {
108
+ storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
109
+ memberId: z.string().describe("The member ID (UUID)."),
110
+ page: z.number().optional().describe("Page number (default: 1)."),
111
+ perPage: z.number().optional().describe("Items per page (default: 25)."),
112
+ name: z.string().optional().describe("Filter by achievement name."),
113
+ achievementId: z.string().optional().describe("Filter by specific achievement ID."),
114
+ };
115
+ // Handler functions
116
+ export async function achievementList(input) {
117
+ const config = getConfig();
118
+ const storeCode = input.storeCode || config.defaultStoreCode;
119
+ const params = new URLSearchParams();
120
+ if (input.page)
121
+ params.append("_page", String(input.page));
122
+ if (input.perPage)
123
+ params.append("_itemsOnPage", String(input.perPage));
124
+ if (input.active !== undefined)
125
+ params.append("active", String(input.active));
126
+ if (input.name)
127
+ params.append("name", input.name);
128
+ const queryString = params.toString();
129
+ const url = `/${storeCode}/achievement${queryString ? `?${queryString}` : ""}`;
130
+ try {
131
+ const response = await apiGet(url);
132
+ const achievements = (response.items || []).map((item) => ({
133
+ achievementId: item.achievementId,
134
+ name: item.name,
135
+ active: item.active,
136
+ createdAt: item.createdAt,
137
+ badgeTypeId: item.badgeTypeId,
138
+ }));
139
+ const total = response.total || {};
140
+ return {
141
+ achievements,
142
+ total: {
143
+ all: typeof total.all === "number" ? total.all : undefined,
144
+ filtered: typeof total.filtered === "number" ? total.filtered : undefined,
145
+ },
146
+ };
147
+ }
148
+ catch (error) {
149
+ throw formatApiError(error, "openloyalty_achievement_list");
150
+ }
151
+ }
152
+ export async function achievementCreate(input) {
153
+ const config = getConfig();
154
+ const storeCode = input.storeCode || config.defaultStoreCode;
155
+ const achievementPayload = {
156
+ translations: input.translations,
157
+ rules: input.rules,
158
+ };
159
+ if (input.active !== undefined)
160
+ achievementPayload.active = input.active;
161
+ if (input.activity)
162
+ achievementPayload.activity = input.activity;
163
+ if (input.limit)
164
+ achievementPayload.limit = input.limit;
165
+ if (input.badgeTypeId)
166
+ achievementPayload.badgeTypeId = input.badgeTypeId;
167
+ try {
168
+ // CRITICAL: Wrap body as { achievement: {...} }
169
+ const response = await apiPost(`/${storeCode}/achievement`, { achievement: achievementPayload });
170
+ return { achievementId: response.achievementId };
171
+ }
172
+ catch (error) {
173
+ throw formatApiError(error, "openloyalty_achievement_create");
174
+ }
175
+ }
176
+ export async function achievementGet(input) {
177
+ const config = getConfig();
178
+ const storeCode = input.storeCode || config.defaultStoreCode;
179
+ try {
180
+ const response = await apiGet(`/${storeCode}/achievement/${input.achievementId}`);
181
+ return response;
182
+ }
183
+ catch (error) {
184
+ throw formatApiError(error, "openloyalty_achievement_get");
185
+ }
186
+ }
187
+ export async function achievementUpdate(input) {
188
+ const config = getConfig();
189
+ const storeCode = input.storeCode || config.defaultStoreCode;
190
+ const achievementPayload = {
191
+ translations: input.translations,
192
+ rules: input.rules,
193
+ };
194
+ if (input.active !== undefined)
195
+ achievementPayload.active = input.active;
196
+ if (input.activity)
197
+ achievementPayload.activity = input.activity;
198
+ if (input.limit)
199
+ achievementPayload.limit = input.limit;
200
+ if (input.badgeTypeId !== undefined)
201
+ achievementPayload.badgeTypeId = input.badgeTypeId;
202
+ try {
203
+ // CRITICAL: Wrap body as { achievement: {...} }
204
+ await apiPut(`/${storeCode}/achievement/${input.achievementId}`, { achievement: achievementPayload });
205
+ }
206
+ catch (error) {
207
+ throw formatApiError(error, "openloyalty_achievement_update");
208
+ }
209
+ }
210
+ export async function achievementPatch(input) {
211
+ const config = getConfig();
212
+ const storeCode = input.storeCode || config.defaultStoreCode;
213
+ const achievementPayload = {};
214
+ if (input.active !== undefined)
215
+ achievementPayload.active = input.active;
216
+ if (input.translations)
217
+ achievementPayload.translations = input.translations;
218
+ try {
219
+ // CRITICAL: Wrap body as { achievement: {...} }
220
+ await apiPatch(`/${storeCode}/achievement/${input.achievementId}`, { achievement: achievementPayload });
221
+ }
222
+ catch (error) {
223
+ throw formatApiError(error, "openloyalty_achievement_patch");
224
+ }
225
+ }
226
+ export async function achievementGetMemberProgress(input) {
227
+ const config = getConfig();
228
+ const storeCode = input.storeCode || config.defaultStoreCode;
229
+ try {
230
+ const response = await apiGet(`/${storeCode}/member/${input.memberId}/achievement/${input.achievementId}`);
231
+ return response;
232
+ }
233
+ catch (error) {
234
+ throw formatApiError(error, "openloyalty_achievement_get_member_progress");
235
+ }
236
+ }
237
+ export async function achievementListMemberAchievements(input) {
238
+ const config = getConfig();
239
+ const storeCode = input.storeCode || config.defaultStoreCode;
240
+ const params = new URLSearchParams();
241
+ if (input.page)
242
+ params.append("_page", String(input.page));
243
+ if (input.perPage)
244
+ params.append("_itemsOnPage", String(input.perPage));
245
+ if (input.name)
246
+ params.append("name", input.name);
247
+ if (input.achievementId)
248
+ params.append("achievementId", input.achievementId);
249
+ const queryString = params.toString();
250
+ const url = `/${storeCode}/member/${input.memberId}/achievement${queryString ? `?${queryString}` : ""}`;
251
+ try {
252
+ const response = await apiGet(url);
253
+ const achievements = response.items || [];
254
+ const total = response.total || {};
255
+ return {
256
+ achievements,
257
+ total: {
258
+ all: typeof total.all === "number" ? total.all : undefined,
259
+ filtered: typeof total.filtered === "number" ? total.filtered : undefined,
260
+ },
261
+ };
262
+ }
263
+ catch (error) {
264
+ throw formatApiError(error, "openloyalty_achievement_list_member_achievements");
265
+ }
266
+ }
267
+ // Tool definitions
268
+ export const achievementToolDefinitions = [
269
+ {
270
+ name: "openloyalty_achievement_list",
271
+ description: "List achievements. Achievements gamify member behavior by setting goals (e.g., 'Make 5 purchases this month'). Returns achievementId, name, active status, and associated badge. Use achievement_get for full rules and configuration.",
272
+ inputSchema: AchievementListInputSchema,
273
+ handler: achievementList,
274
+ },
275
+ {
276
+ name: "openloyalty_achievement_create",
277
+ description: "Create achievement with rules that track member progress. Triggers: transaction (purchases), custom_event (custom actions), points_transfer, referral, etc. CompleteRule sets the goal: periodGoal (target value) with optional period (consecutive periods). Example - '5 purchases/month': rules: [{ trigger: 'transaction', completeRule: { periodGoal: 5, period: { value: 1, consecutive: 1 } } }]",
278
+ inputSchema: AchievementCreateInputSchema,
279
+ handler: achievementCreate,
280
+ },
281
+ {
282
+ name: "openloyalty_achievement_get",
283
+ description: "Get achievement details including all rules, conditions, activity period, limits, and completions count.",
284
+ inputSchema: AchievementGetInputSchema,
285
+ handler: achievementGet,
286
+ },
287
+ {
288
+ name: "openloyalty_achievement_update",
289
+ description: "Update achievement configuration. Requires full achievement object (translations, rules). Use achievement_get first to retrieve current configuration.",
290
+ inputSchema: AchievementUpdateInputSchema,
291
+ handler: achievementUpdate,
292
+ },
293
+ {
294
+ name: "openloyalty_achievement_patch",
295
+ description: "Partial update of achievement. Use for simple changes like activating/deactivating or updating translations without providing full rules.",
296
+ inputSchema: AchievementPatchInputSchema,
297
+ handler: achievementPatch,
298
+ },
299
+ {
300
+ name: "openloyalty_achievement_get_member_progress",
301
+ description: "Get member's progress on a specific achievement. Returns completedCount, and for each rule: periodGoal, currentPeriodValue, and consecutive period tracking.",
302
+ inputSchema: AchievementGetMemberProgressInputSchema,
303
+ handler: achievementGetMemberProgress,
304
+ },
305
+ {
306
+ name: "openloyalty_achievement_list_member_achievements",
307
+ description: "List all achievements with member's progress. Returns each achievement's status, completion count, and per-rule progress. Use for displaying gamification dashboard.",
308
+ inputSchema: AchievementListMemberAchievementsInputSchema,
309
+ handler: achievementListMemberAchievements,
310
+ },
311
+ ];
@@ -0,0 +1,153 @@
1
+ import { z } from "zod";
2
+ import { AdminUser, AdminUserListItem, AdminPermission } from "../types/schemas/admin.js";
3
+ export declare const AdminListInputSchema: {
4
+ page: z.ZodOptional<z.ZodNumber>;
5
+ perPage: z.ZodOptional<z.ZodNumber>;
6
+ email: z.ZodOptional<z.ZodString>;
7
+ isActive: z.ZodOptional<z.ZodBoolean>;
8
+ firstName: z.ZodOptional<z.ZodString>;
9
+ lastName: z.ZodOptional<z.ZodString>;
10
+ role: z.ZodOptional<z.ZodString>;
11
+ };
12
+ export declare const AdminCreateInputSchema: {
13
+ email: z.ZodString;
14
+ password: z.ZodString;
15
+ firstName: z.ZodOptional<z.ZodString>;
16
+ lastName: z.ZodOptional<z.ZodString>;
17
+ phone: z.ZodOptional<z.ZodString>;
18
+ roles: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
19
+ isActive: z.ZodOptional<z.ZodBoolean>;
20
+ external: z.ZodOptional<z.ZodBoolean>;
21
+ notificationsEnabled: z.ZodOptional<z.ZodBoolean>;
22
+ };
23
+ export declare const AdminGetInputSchema: {
24
+ adminId: z.ZodString;
25
+ };
26
+ export declare const AdminUpdateInputSchema: {
27
+ adminId: z.ZodString;
28
+ email: z.ZodOptional<z.ZodString>;
29
+ firstName: z.ZodOptional<z.ZodString>;
30
+ lastName: z.ZodOptional<z.ZodString>;
31
+ phone: z.ZodOptional<z.ZodString>;
32
+ roles: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
33
+ isActive: z.ZodOptional<z.ZodBoolean>;
34
+ external: z.ZodOptional<z.ZodBoolean>;
35
+ notificationsEnabled: z.ZodOptional<z.ZodBoolean>;
36
+ password: z.ZodOptional<z.ZodString>;
37
+ };
38
+ export declare const AdminChangePasswordInputSchema: {
39
+ currentPassword: z.ZodString;
40
+ newPassword: z.ZodString;
41
+ };
42
+ export declare function adminList(input: {
43
+ page?: number;
44
+ perPage?: number;
45
+ email?: string;
46
+ isActive?: boolean;
47
+ firstName?: string;
48
+ lastName?: string;
49
+ role?: string;
50
+ }): Promise<{
51
+ items: AdminUserListItem[];
52
+ total?: number;
53
+ }>;
54
+ export declare function adminCreate(input: {
55
+ email: string;
56
+ password: string;
57
+ firstName?: string;
58
+ lastName?: string;
59
+ phone?: string;
60
+ roles?: (string | number)[];
61
+ isActive?: boolean;
62
+ external?: boolean;
63
+ notificationsEnabled?: boolean;
64
+ }): Promise<{
65
+ adminId: string;
66
+ }>;
67
+ export declare function adminGet(input: {
68
+ adminId: string;
69
+ }): Promise<AdminUser>;
70
+ export declare function adminUpdate(input: {
71
+ adminId: string;
72
+ email?: string;
73
+ firstName?: string;
74
+ lastName?: string;
75
+ phone?: string;
76
+ roles?: (string | number)[];
77
+ isActive?: boolean;
78
+ external?: boolean;
79
+ notificationsEnabled?: boolean;
80
+ password?: string;
81
+ }): Promise<{
82
+ adminId: string;
83
+ }>;
84
+ export declare function adminChangePassword(input: {
85
+ currentPassword: string;
86
+ newPassword: string;
87
+ }): Promise<void>;
88
+ export declare function adminGetPermissions(): Promise<AdminPermission>;
89
+ export declare const adminToolDefinitions: readonly [{
90
+ readonly name: "openloyalty_admin_list";
91
+ readonly description: "List admin users with optional filtering. Returns paginated list of admin users with id, email, firstName, lastName, isActive, createdAt.";
92
+ readonly inputSchema: {
93
+ page: z.ZodOptional<z.ZodNumber>;
94
+ perPage: z.ZodOptional<z.ZodNumber>;
95
+ email: z.ZodOptional<z.ZodString>;
96
+ isActive: z.ZodOptional<z.ZodBoolean>;
97
+ firstName: z.ZodOptional<z.ZodString>;
98
+ lastName: z.ZodOptional<z.ZodString>;
99
+ role: z.ZodOptional<z.ZodString>;
100
+ };
101
+ readonly handler: typeof adminList;
102
+ }, {
103
+ readonly name: "openloyalty_admin_create";
104
+ readonly description: "Create a new admin user. Requires email and password. Optionally assign roles, set active status, and configure notifications. Returns adminId.";
105
+ readonly inputSchema: {
106
+ email: z.ZodString;
107
+ password: z.ZodString;
108
+ firstName: z.ZodOptional<z.ZodString>;
109
+ lastName: z.ZodOptional<z.ZodString>;
110
+ phone: z.ZodOptional<z.ZodString>;
111
+ roles: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
112
+ isActive: z.ZodOptional<z.ZodBoolean>;
113
+ external: z.ZodOptional<z.ZodBoolean>;
114
+ notificationsEnabled: z.ZodOptional<z.ZodBoolean>;
115
+ };
116
+ readonly handler: typeof adminCreate;
117
+ }, {
118
+ readonly name: "openloyalty_admin_get";
119
+ readonly description: "Get full admin user details by ID. Returns profile including email, name, roles, settings, active status, and creation date.";
120
+ readonly inputSchema: {
121
+ adminId: z.ZodString;
122
+ };
123
+ readonly handler: typeof adminGet;
124
+ }, {
125
+ readonly name: "openloyalty_admin_update";
126
+ readonly description: "Update admin user profile. Can update email, name, phone, roles, active status, and password. Returns adminId on success.";
127
+ readonly inputSchema: {
128
+ adminId: z.ZodString;
129
+ email: z.ZodOptional<z.ZodString>;
130
+ firstName: z.ZodOptional<z.ZodString>;
131
+ lastName: z.ZodOptional<z.ZodString>;
132
+ phone: z.ZodOptional<z.ZodString>;
133
+ roles: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "many">>;
134
+ isActive: z.ZodOptional<z.ZodBoolean>;
135
+ external: z.ZodOptional<z.ZodBoolean>;
136
+ notificationsEnabled: z.ZodOptional<z.ZodBoolean>;
137
+ password: z.ZodOptional<z.ZodString>;
138
+ };
139
+ readonly handler: typeof adminUpdate;
140
+ }, {
141
+ readonly name: "openloyalty_admin_change_password";
142
+ readonly description: "Change the currently logged-in admin's password. Requires current password for verification. Returns void on success.";
143
+ readonly inputSchema: {
144
+ currentPassword: z.ZodString;
145
+ newPassword: z.ZodString;
146
+ };
147
+ readonly handler: typeof adminChangePassword;
148
+ }, {
149
+ readonly name: "openloyalty_admin_get_permissions";
150
+ readonly description: "Get the current admin user's permissions. Returns superAdmin flag, list of roles, and list of permission strings. Use to check what actions are available.";
151
+ readonly inputSchema: {};
152
+ readonly handler: typeof adminGetPermissions;
153
+ }];
@@ -0,0 +1,193 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPost, apiPut } from "../client/http.js";
3
+ import { formatApiError } from "../utils/errors.js";
4
+ // Input Schemas
5
+ export const AdminListInputSchema = {
6
+ page: z.number().optional().describe("Page number (default: 1)."),
7
+ perPage: z.number().optional().describe("Items per page (default: 25)."),
8
+ email: z.string().optional().describe("Filter by email address."),
9
+ isActive: z.boolean().optional().describe("Filter by active status."),
10
+ firstName: z.string().optional().describe("Filter by first name."),
11
+ lastName: z.string().optional().describe("Filter by last name."),
12
+ role: z.string().optional().describe("Filter by role."),
13
+ };
14
+ export const AdminCreateInputSchema = {
15
+ email: z.string().describe("Admin email address (required)."),
16
+ password: z.string().describe("Admin password (required)."),
17
+ firstName: z.string().optional().describe("Admin first name."),
18
+ lastName: z.string().optional().describe("Admin last name."),
19
+ phone: z.string().optional().describe("Admin phone number."),
20
+ roles: z.array(z.union([z.string(), z.number()])).optional().describe("Role IDs to assign."),
21
+ isActive: z.boolean().optional().describe("Whether account is active (default: true)."),
22
+ external: z.boolean().optional().describe("Whether admin is external."),
23
+ notificationsEnabled: z.boolean().optional().describe("Whether notifications are enabled."),
24
+ };
25
+ export const AdminGetInputSchema = {
26
+ adminId: z.string().describe("The admin ID (UUID) to retrieve."),
27
+ };
28
+ export const AdminUpdateInputSchema = {
29
+ adminId: z.string().describe("The admin ID (UUID) to update."),
30
+ email: z.string().optional().describe("Admin email address."),
31
+ firstName: z.string().optional().describe("Admin first name."),
32
+ lastName: z.string().optional().describe("Admin last name."),
33
+ phone: z.string().optional().describe("Admin phone number."),
34
+ roles: z.array(z.union([z.string(), z.number()])).optional().describe("Role IDs to assign."),
35
+ isActive: z.boolean().optional().describe("Whether account is active."),
36
+ external: z.boolean().optional().describe("Whether admin is external."),
37
+ notificationsEnabled: z.boolean().optional().describe("Whether notifications are enabled."),
38
+ password: z.string().optional().describe("New password (if changing)."),
39
+ };
40
+ export const AdminChangePasswordInputSchema = {
41
+ currentPassword: z.string().describe("Current password."),
42
+ newPassword: z.string().describe("New password."),
43
+ };
44
+ // Handler functions
45
+ export async function adminList(input) {
46
+ const params = new URLSearchParams();
47
+ if (input.page)
48
+ params.append("_page", String(input.page));
49
+ if (input.perPage)
50
+ params.append("_itemsOnPage", String(input.perPage));
51
+ if (input.email)
52
+ params.append("email", input.email);
53
+ if (input.isActive !== undefined)
54
+ params.append("isActive", String(input.isActive));
55
+ if (input.firstName)
56
+ params.append("firstName", input.firstName);
57
+ if (input.lastName)
58
+ params.append("lastName", input.lastName);
59
+ if (input.role)
60
+ params.append("role", input.role);
61
+ const queryString = params.toString();
62
+ const url = `/admin${queryString ? `?${queryString}` : ""}`;
63
+ try {
64
+ const response = await apiGet(url);
65
+ return response;
66
+ }
67
+ catch (error) {
68
+ throw formatApiError(error, "openloyalty_admin_list");
69
+ }
70
+ }
71
+ export async function adminCreate(input) {
72
+ const payload = {
73
+ email: input.email,
74
+ plainPassword: input.password,
75
+ };
76
+ if (input.firstName)
77
+ payload.firstName = input.firstName;
78
+ if (input.lastName)
79
+ payload.lastName = input.lastName;
80
+ if (input.phone)
81
+ payload.phone = input.phone;
82
+ if (input.roles)
83
+ payload.roles = input.roles;
84
+ if (input.isActive !== undefined)
85
+ payload.isActive = input.isActive;
86
+ if (input.external !== undefined)
87
+ payload.external = input.external;
88
+ if (input.notificationsEnabled !== undefined)
89
+ payload.notificationsEnabled = input.notificationsEnabled;
90
+ try {
91
+ const response = await apiPost("/admin/data", { admin: payload });
92
+ return response;
93
+ }
94
+ catch (error) {
95
+ throw formatApiError(error, "openloyalty_admin_create");
96
+ }
97
+ }
98
+ export async function adminGet(input) {
99
+ try {
100
+ const response = await apiGet(`/admin/data/${input.adminId}`);
101
+ return response;
102
+ }
103
+ catch (error) {
104
+ throw formatApiError(error, "openloyalty_admin_get");
105
+ }
106
+ }
107
+ export async function adminUpdate(input) {
108
+ const payload = {};
109
+ if (input.email)
110
+ payload.email = input.email;
111
+ if (input.firstName)
112
+ payload.firstName = input.firstName;
113
+ if (input.lastName)
114
+ payload.lastName = input.lastName;
115
+ if (input.phone)
116
+ payload.phone = input.phone;
117
+ if (input.roles)
118
+ payload.roles = input.roles;
119
+ if (input.isActive !== undefined)
120
+ payload.isActive = input.isActive;
121
+ if (input.external !== undefined)
122
+ payload.external = input.external;
123
+ if (input.notificationsEnabled !== undefined)
124
+ payload.notificationsEnabled = input.notificationsEnabled;
125
+ if (input.password)
126
+ payload.plainPassword = input.password;
127
+ try {
128
+ const response = await apiPut(`/admin/data/${input.adminId}`, { admin: payload });
129
+ return response;
130
+ }
131
+ catch (error) {
132
+ throw formatApiError(error, "openloyalty_admin_update");
133
+ }
134
+ }
135
+ export async function adminChangePassword(input) {
136
+ try {
137
+ await apiPut("/admin/password", {
138
+ currentPassword: input.currentPassword,
139
+ plainPassword: input.newPassword,
140
+ });
141
+ }
142
+ catch (error) {
143
+ throw formatApiError(error, "openloyalty_admin_change_password");
144
+ }
145
+ }
146
+ export async function adminGetPermissions() {
147
+ try {
148
+ const response = await apiGet("/admin/permissions");
149
+ return response;
150
+ }
151
+ catch (error) {
152
+ throw formatApiError(error, "openloyalty_admin_get_permissions");
153
+ }
154
+ }
155
+ // Tool definitions
156
+ export const adminToolDefinitions = [
157
+ {
158
+ name: "openloyalty_admin_list",
159
+ description: "List admin users with optional filtering. Returns paginated list of admin users with id, email, firstName, lastName, isActive, createdAt.",
160
+ inputSchema: AdminListInputSchema,
161
+ handler: adminList,
162
+ },
163
+ {
164
+ name: "openloyalty_admin_create",
165
+ description: "Create a new admin user. Requires email and password. Optionally assign roles, set active status, and configure notifications. Returns adminId.",
166
+ inputSchema: AdminCreateInputSchema,
167
+ handler: adminCreate,
168
+ },
169
+ {
170
+ name: "openloyalty_admin_get",
171
+ description: "Get full admin user details by ID. Returns profile including email, name, roles, settings, active status, and creation date.",
172
+ inputSchema: AdminGetInputSchema,
173
+ handler: adminGet,
174
+ },
175
+ {
176
+ name: "openloyalty_admin_update",
177
+ description: "Update admin user profile. Can update email, name, phone, roles, active status, and password. Returns adminId on success.",
178
+ inputSchema: AdminUpdateInputSchema,
179
+ handler: adminUpdate,
180
+ },
181
+ {
182
+ name: "openloyalty_admin_change_password",
183
+ description: "Change the currently logged-in admin's password. Requires current password for verification. Returns void on success.",
184
+ inputSchema: AdminChangePasswordInputSchema,
185
+ handler: adminChangePassword,
186
+ },
187
+ {
188
+ name: "openloyalty_admin_get_permissions",
189
+ description: "Get the current admin user's permissions. Returns superAdmin flag, list of roles, and list of permission strings. Use to check what actions are available.",
190
+ inputSchema: {},
191
+ handler: adminGetPermissions,
192
+ },
193
+ ];