@open-loyalty/mcp-server 1.0.3 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +180 -177
  2. package/dist/auth/provider.js +2 -14
  3. package/dist/auth/storage.js +22 -0
  4. package/dist/client/http.d.ts +5 -0
  5. package/dist/client/http.js +62 -3
  6. package/dist/config.d.ts +6 -5
  7. package/dist/config.js +15 -11
  8. package/dist/http.js +170 -65
  9. package/dist/instructions.d.ts +5 -0
  10. package/dist/instructions.js +420 -0
  11. package/dist/prompts/fan-engagement-setup.d.ts +107 -0
  12. package/dist/prompts/fan-engagement-setup.js +492 -0
  13. package/dist/server.d.ts +1 -1
  14. package/dist/server.js +68 -278
  15. package/dist/tools/achievement/handlers.d.ts +117 -0
  16. package/dist/tools/achievement/handlers.js +161 -0
  17. package/dist/tools/achievement/index.d.ts +479 -0
  18. package/dist/tools/achievement/index.js +74 -0
  19. package/dist/tools/achievement/schemas.d.ts +433 -0
  20. package/dist/tools/achievement/schemas.js +142 -0
  21. package/dist/tools/achievement.d.ts +155 -121
  22. package/dist/tools/achievement.js +82 -39
  23. package/dist/tools/admin.d.ts +18 -6
  24. package/dist/tools/admin.js +24 -12
  25. package/dist/tools/analytics.d.ts +29 -11
  26. package/dist/tools/analytics.js +58 -48
  27. package/dist/tools/apikey.d.ts +10 -3
  28. package/dist/tools/apikey.js +13 -6
  29. package/dist/tools/audit.d.ts +6 -2
  30. package/dist/tools/audit.js +8 -4
  31. package/dist/tools/badge.d.ts +14 -6
  32. package/dist/tools/badge.js +36 -27
  33. package/dist/tools/campaign/handlers.d.ts +42 -0
  34. package/dist/tools/campaign/handlers.js +223 -0
  35. package/dist/tools/campaign/index.d.ts +783 -0
  36. package/dist/tools/campaign/index.js +112 -0
  37. package/dist/tools/campaign/member-handlers.d.ts +60 -0
  38. package/dist/tools/campaign/member-handlers.js +159 -0
  39. package/dist/tools/campaign/schemas.d.ts +704 -0
  40. package/dist/tools/campaign/schemas.js +259 -0
  41. package/dist/tools/campaign/types.d.ts +161 -0
  42. package/dist/tools/campaign/types.js +2 -0
  43. package/dist/tools/campaign.d.ts +41 -16
  44. package/dist/tools/campaign.js +38 -25
  45. package/dist/tools/custom-event.d.ts +315 -0
  46. package/dist/tools/custom-event.js +270 -0
  47. package/dist/tools/export.d.ts +12 -4
  48. package/dist/tools/export.js +25 -20
  49. package/dist/tools/import.d.ts +9 -3
  50. package/dist/tools/import.js +33 -21
  51. package/dist/tools/index.d.ts +3 -11
  52. package/dist/tools/index.js +17 -475
  53. package/dist/tools/member/handlers.d.ts +111 -0
  54. package/dist/tools/member/handlers.js +206 -0
  55. package/dist/tools/member/index.d.ts +169 -0
  56. package/dist/tools/member/index.js +92 -0
  57. package/dist/tools/member/schemas.d.ts +89 -0
  58. package/dist/tools/member/schemas.js +65 -0
  59. package/dist/tools/member.d.ts +21 -0
  60. package/dist/tools/member.js +56 -62
  61. package/dist/tools/points.d.ts +19 -6
  62. package/dist/tools/points.js +51 -49
  63. package/dist/tools/referral/handlers.d.ts +47 -0
  64. package/dist/tools/referral/handlers.js +115 -0
  65. package/dist/tools/referral/index.d.ts +44 -0
  66. package/dist/tools/referral/index.js +44 -0
  67. package/dist/tools/referral/schemas.d.ts +34 -0
  68. package/dist/tools/referral/schemas.js +52 -0
  69. package/dist/tools/reward/handlers.d.ts +110 -0
  70. package/dist/tools/reward/handlers.js +289 -0
  71. package/dist/tools/reward/index.d.ts +177 -0
  72. package/dist/tools/reward/index.js +90 -0
  73. package/dist/tools/reward/schemas.d.ts +116 -0
  74. package/dist/tools/reward/schemas.js +91 -0
  75. package/dist/tools/reward.d.ts +18 -0
  76. package/dist/tools/reward.js +56 -66
  77. package/dist/tools/role.d.ts +26 -7
  78. package/dist/tools/role.js +25 -12
  79. package/dist/tools/segment/handlers.d.ts +87 -0
  80. package/dist/tools/segment/handlers.js +174 -0
  81. package/dist/tools/segment/index.d.ts +395 -0
  82. package/dist/tools/segment/index.js +87 -0
  83. package/dist/tools/segment/schemas.d.ts +337 -0
  84. package/dist/tools/segment/schemas.js +79 -0
  85. package/dist/tools/segment.d.ts +29 -10
  86. package/dist/tools/segment.js +84 -50
  87. package/dist/tools/store.d.ts +12 -4
  88. package/dist/tools/store.js +16 -8
  89. package/dist/tools/tierset.d.ts +19 -7
  90. package/dist/tools/tierset.js +44 -35
  91. package/dist/tools/transaction.d.ts +16 -8
  92. package/dist/tools/transaction.js +25 -21
  93. package/dist/tools/wallet-type.d.ts +7 -3
  94. package/dist/tools/wallet-type.js +14 -12
  95. package/dist/tools/webhook.d.ts +23 -10
  96. package/dist/tools/webhook.js +135 -33
  97. package/dist/types/schemas/achievement.d.ts +12 -309
  98. package/dist/types/schemas/achievement.js +0 -13
  99. package/dist/types/schemas/admin.d.ts +10 -97
  100. package/dist/types/schemas/admin.js +0 -38
  101. package/dist/types/schemas/badge.d.ts +0 -37
  102. package/dist/types/schemas/badge.js +0 -11
  103. package/dist/types/schemas/campaign.d.ts +64 -832
  104. package/dist/types/schemas/campaign.js +2 -25
  105. package/dist/types/schemas/common.d.ts +5 -0
  106. package/dist/types/schemas/common.js +5 -0
  107. package/dist/types/schemas/export.d.ts +0 -17
  108. package/dist/types/schemas/export.js +0 -7
  109. package/dist/types/schemas/member.d.ts +37 -176
  110. package/dist/types/schemas/member.js +0 -27
  111. package/dist/types/schemas/points.d.ts +0 -63
  112. package/dist/types/schemas/points.js +0 -22
  113. package/dist/types/schemas/reward.d.ts +71 -68
  114. package/dist/types/schemas/reward.js +8 -28
  115. package/dist/types/schemas/role.d.ts +0 -100
  116. package/dist/types/schemas/role.js +0 -29
  117. package/dist/types/schemas/segment.d.ts +0 -58
  118. package/dist/types/schemas/segment.js +0 -17
  119. package/dist/types/schemas/tierset.d.ts +0 -176
  120. package/dist/types/schemas/tierset.js +0 -27
  121. package/dist/types/schemas/transaction.d.ts +23 -254
  122. package/dist/types/schemas/transaction.js +0 -7
  123. package/dist/types/schemas/wallet-type.d.ts +8 -8
  124. package/dist/types/schemas/wallet-type.js +1 -1
  125. package/dist/types/schemas/webhook.d.ts +0 -58
  126. package/dist/types/schemas/webhook.js +0 -12
  127. package/dist/utils/errors.js +30 -3
  128. package/dist/utils/payload.d.ts +12 -0
  129. package/dist/utils/payload.js +14 -0
  130. package/dist/workflows/app-login-streak.d.ts +39 -0
  131. package/dist/workflows/app-login-streak.js +298 -0
  132. package/dist/workflows/early-arrival.d.ts +33 -0
  133. package/dist/workflows/early-arrival.js +148 -0
  134. package/dist/workflows/index.d.ts +101 -0
  135. package/dist/workflows/index.js +208 -0
  136. package/dist/workflows/match-attendance.d.ts +45 -0
  137. package/dist/workflows/match-attendance.js +308 -0
  138. package/dist/workflows/sportsbar-visit.d.ts +41 -0
  139. package/dist/workflows/sportsbar-visit.js +284 -0
  140. package/dist/workflows/vod-watching.d.ts +43 -0
  141. package/dist/workflows/vod-watching.js +326 -0
  142. package/package.json +10 -2
@@ -1,11 +1,13 @@
1
1
  import { z } from "zod";
2
2
  import { apiGet, apiPost } from "../client/http.js";
3
+ import "../types/schemas/points.js";
3
4
  import { formatApiError, OpenLoyaltyError } from "../utils/errors.js";
4
- import { getConfig } from "../config.js";
5
+ import { getStoreCode } from "../config.js";
5
6
  import { buildPaginationParams } from "../utils/pagination.js";
7
+ import { omitUndefined } from "../utils/payload.js";
6
8
  // Input Schemas
7
9
  export const PointsAddInputSchema = {
8
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
10
+ 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."),
9
11
  memberId: z.string().describe("The member ID (UUID) to add points to."),
10
12
  points: z.number().describe("Number of points to add (positive number)."),
11
13
  walletCode: z.string().optional().describe("Wallet type code (e.g., 'default'). Uses default wallet if not specified."),
@@ -14,25 +16,25 @@ export const PointsAddInputSchema = {
14
16
  lockedUntilDays: z.number().optional().describe("Days until points become available (1-9999)."),
15
17
  };
16
18
  export const PointsSpendInputSchema = {
17
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
19
+ 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."),
18
20
  memberId: z.string().describe("The member ID (UUID) to spend points from."),
19
21
  points: z.number().describe("Number of points to spend (positive number)."),
20
22
  walletCode: z.string().optional().describe("Wallet type code (e.g., 'default'). Uses default wallet if not specified."),
21
23
  comment: z.string().optional().describe("Reason for spending points (max 500 chars)."),
22
24
  };
23
25
  export const PointsTransferInputSchema = {
24
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
26
+ 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."),
25
27
  senderId: z.string().describe("The sender member ID (UUID)."),
26
28
  receiverId: z.string().describe("The receiver member ID (UUID)."),
27
29
  points: z.number().describe("Number of points to transfer."),
28
30
  };
29
31
  export const PointsBalanceInputSchema = {
30
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
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."),
31
33
  memberId: z.string().describe("The member ID (UUID) to get balance for."),
32
34
  walletCode: z.string().optional().describe("Wallet type code. Returns all wallets if not specified."),
33
35
  };
34
36
  export const PointsHistoryInputSchema = {
35
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
37
+ 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."),
36
38
  memberId: z.string().describe("The member ID (UUID) to get history for."),
37
39
  cursor: z.string().optional().describe("Pagination cursor from previous response. If provided, page/perPage are ignored."),
38
40
  page: z.number().optional().describe("Page number (default: 1)."),
@@ -40,7 +42,7 @@ export const PointsHistoryInputSchema = {
40
42
  type: z.enum(["adding", "spending", "p2p_spending", "p2p_adding", "blocked", "expired"]).optional().describe("Filter by transfer type."),
41
43
  };
42
44
  export const PointsHistogramInputSchema = {
43
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
45
+ 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
46
  memberId: z.string().describe("The member ID (UUID) to get histogram for."),
45
47
  pointType: z.enum(["spent", "earned", "expired", "pending"]).describe("Filter by point type (required). One of: spent, earned, expired, pending."),
46
48
  walletCode: z.string().optional().describe("Wallet type code. Uses default if not specified."),
@@ -50,37 +52,29 @@ export const PointsHistogramInputSchema = {
50
52
  };
51
53
  // Handler functions
52
54
  export async function pointsAdd(input) {
53
- const config = getConfig();
54
- const storeCode = input.storeCode || config.defaultStoreCode;
55
- const payload = {
55
+ const storeCode = getStoreCode(input.storeCode);
56
+ const payload = omitUndefined({
56
57
  points: input.points,
57
- };
58
- if (input.walletCode)
59
- payload.walletCode = input.walletCode;
60
- if (input.comment)
61
- payload.comment = input.comment;
62
- if (input.expiresInDays)
63
- payload.expiresInDays = input.expiresInDays;
64
- if (input.lockedUntilDays)
65
- payload.lockedUntilDays = input.lockedUntilDays;
58
+ walletCode: input.walletCode,
59
+ comment: input.comment,
60
+ expiresInDays: input.expiresInDays,
61
+ lockedUntilDays: input.lockedUntilDays,
62
+ });
66
63
  try {
67
64
  const response = await apiPost(`/${storeCode}/points/add`, { transfer: { customer: input.memberId, ...payload } });
68
65
  return { transferId: response.transferId };
69
66
  }
70
67
  catch (error) {
71
- throw formatApiError(error, "openloyalty_points_add");
68
+ throw formatApiError(error, "ol_points_add");
72
69
  }
73
70
  }
74
71
  export async function pointsSpend(input) {
75
- const config = getConfig();
76
- const storeCode = input.storeCode || config.defaultStoreCode;
77
- const payload = {
72
+ const storeCode = getStoreCode(input.storeCode);
73
+ const payload = omitUndefined({
78
74
  points: input.points,
79
- };
80
- if (input.walletCode)
81
- payload.walletCode = input.walletCode;
82
- if (input.comment)
83
- payload.comment = input.comment;
75
+ walletCode: input.walletCode,
76
+ comment: input.comment,
77
+ });
84
78
  try {
85
79
  const response = await apiPost(`/${storeCode}/points/spend`, { transfer: { customer: input.memberId, ...payload } });
86
80
  return { transferId: response.transferId };
@@ -93,15 +87,14 @@ export async function pointsSpend(input) {
93
87
  code: "INSUFFICIENT_BALANCE",
94
88
  message: "Member does not have enough points to complete this operation",
95
89
  hint: `Use points_get_balance(memberId: "${input.memberId}") to check available balance before spending.`,
96
- relatedTool: "openloyalty_points_spend",
90
+ relatedTool: "ol_points_spend",
97
91
  });
98
92
  }
99
- throw formatApiError(error, "openloyalty_points_spend");
93
+ throw formatApiError(error, "ol_points_spend");
100
94
  }
101
95
  }
102
96
  export async function pointsTransfer(input) {
103
- const config = getConfig();
104
- const storeCode = input.storeCode || config.defaultStoreCode;
97
+ const storeCode = getStoreCode(input.storeCode);
105
98
  if (input.senderId === input.receiverId) {
106
99
  throw new Error("Cannot transfer points to yourself. senderId and receiverId must be different.");
107
100
  }
@@ -123,15 +116,14 @@ export async function pointsTransfer(input) {
123
116
  code: "INSUFFICIENT_BALANCE",
124
117
  message: "Sender does not have enough points to transfer",
125
118
  hint: `Use points_get_balance(memberId: "${input.senderId}") to check sender's available balance before transferring.`,
126
- relatedTool: "openloyalty_points_transfer",
119
+ relatedTool: "ol_points_transfer",
127
120
  });
128
121
  }
129
- throw formatApiError(error, "openloyalty_points_transfer");
122
+ throw formatApiError(error, "ol_points_transfer");
130
123
  }
131
124
  }
132
125
  export async function pointsGetBalance(input) {
133
- const config = getConfig();
134
- const storeCode = input.storeCode || config.defaultStoreCode;
126
+ const storeCode = getStoreCode(input.storeCode);
135
127
  const params = new URLSearchParams();
136
128
  if (input.walletCode)
137
129
  params.append("walletType:code", input.walletCode);
@@ -176,12 +168,11 @@ export async function pointsGetBalance(input) {
176
168
  };
177
169
  }
178
170
  catch (error) {
179
- throw formatApiError(error, "openloyalty_points_get_balance");
171
+ throw formatApiError(error, "ol_points_get_balance");
180
172
  }
181
173
  }
182
174
  export async function pointsGetHistory(input) {
183
- const config = getConfig();
184
- const storeCode = input.storeCode || config.defaultStoreCode;
175
+ const storeCode = getStoreCode(input.storeCode);
185
176
  const params = new URLSearchParams();
186
177
  params.append("member:id", input.memberId);
187
178
  // Use buildPaginationParams for cursor/page handling
@@ -214,12 +205,11 @@ export async function pointsGetHistory(input) {
214
205
  };
215
206
  }
216
207
  catch (error) {
217
- throw formatApiError(error, "openloyalty_points_get_history");
208
+ throw formatApiError(error, "ol_points_get_history");
218
209
  }
219
210
  }
220
211
  export async function pointsGetHistogram(input) {
221
- const config = getConfig();
222
- const storeCode = input.storeCode || config.defaultStoreCode;
212
+ const storeCode = getStoreCode(input.storeCode);
223
213
  const params = new URLSearchParams();
224
214
  params.append("member:id", input.memberId);
225
215
  // pointType is required by the API: spent|earned|expired|pending
@@ -255,51 +245,63 @@ export async function pointsGetHistogram(input) {
255
245
  });
256
246
  }
257
247
  catch (error) {
258
- throw formatApiError(error, "openloyalty_points_get_histogram");
248
+ throw formatApiError(error, "ol_points_get_histogram");
259
249
  }
260
250
  }
261
251
  // Tool definitions
262
252
  export const pointsToolDefinitions = [
263
253
  {
264
- name: "openloyalty_points_add",
254
+ name: "ol_points_add",
255
+ title: "Add Points to Member",
265
256
  description: "Add points to member wallet. Points can have optional expiration and lock period. " +
266
257
  "Use for welcome bonuses, manual adjustments, or custom rewards. Returns transferId.",
258
+ readOnly: false,
267
259
  inputSchema: PointsAddInputSchema,
268
260
  handler: pointsAdd,
269
261
  },
270
262
  {
271
- name: "openloyalty_points_spend",
263
+ name: "ol_points_spend",
264
+ title: "Spend Member Points",
272
265
  description: "Deduct points from member wallet. Fails if insufficient balance. " +
273
266
  "Use points_get_balance first to verify available points. Returns transferId.",
267
+ readOnly: false,
274
268
  inputSchema: PointsSpendInputSchema,
275
269
  handler: pointsSpend,
276
270
  },
277
271
  {
278
- name: "openloyalty_points_transfer",
272
+ name: "ol_points_transfer",
273
+ title: "Transfer Points Between Members",
279
274
  description: "Transfer points from one member to another (P2P transfer). " +
280
275
  "Sender must have sufficient balance. Returns transferId.",
276
+ readOnly: false,
281
277
  inputSchema: PointsTransferInputSchema,
282
278
  handler: pointsTransfer,
283
279
  },
284
280
  {
285
- name: "openloyalty_points_get_balance",
281
+ name: "ol_points_get_balance",
282
+ title: "Check Points Balance",
286
283
  description: "Get member points balance breakdown. activeUnits is available for spending. " +
287
284
  "earnedUnits shows lifetime earnings, lockedUnits shows pending points.",
285
+ readOnly: true,
288
286
  inputSchema: PointsBalanceInputSchema,
289
287
  handler: pointsGetBalance,
290
288
  },
291
289
  {
292
- name: "openloyalty_points_get_history",
290
+ name: "ol_points_get_history",
291
+ title: "View Points History",
293
292
  description: "Get points transaction history for a member. Filter by type: adding, spending, " +
294
293
  "p2p_spending, p2p_adding, blocked, expired. Returns paginated list of transfers. " +
295
294
  "Supports cursor pagination: provide 'cursor' from previous response to get next page.",
295
+ readOnly: true,
296
296
  inputSchema: PointsHistoryInputSchema,
297
297
  handler: pointsGetHistory,
298
298
  },
299
299
  {
300
- name: "openloyalty_points_get_histogram",
300
+ name: "ol_points_get_histogram",
301
+ title: "View Points Trends",
301
302
  description: "Get points histogram data for visualization. Shows earning and spending patterns over time. " +
302
303
  "Use interval (day/week/month) to aggregate data and dateFrom/dateTo to filter range.",
304
+ readOnly: true,
303
305
  inputSchema: PointsHistogramInputSchema,
304
306
  handler: pointsGetHistogram,
305
307
  },
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Create a referral relationship between two members
3
+ * POST /api/:storeCode/member/:member/referral
4
+ */
5
+ export declare function referralCreate(input: {
6
+ storeCode?: string;
7
+ memberId: string;
8
+ referrerId: string;
9
+ }): Promise<void>;
10
+ /**
11
+ * List referrals with optional filters
12
+ * GET /api/:storeCode/referral
13
+ */
14
+ export declare function referralList(input: {
15
+ storeCode?: string;
16
+ referralId?: string;
17
+ referrerId?: string;
18
+ referrerName?: string;
19
+ referrerToken?: string;
20
+ refereeId?: string;
21
+ refereeName?: string;
22
+ createdAt?: string;
23
+ page?: number;
24
+ perPage?: number;
25
+ }): Promise<{
26
+ referrals: Array<{
27
+ referralId: string;
28
+ referrerId: string;
29
+ referrerName?: string;
30
+ referrerToken?: string;
31
+ refereeId: string;
32
+ refereeName?: string;
33
+ createdAt: string;
34
+ }>;
35
+ total: {
36
+ all?: number;
37
+ filtered?: number;
38
+ };
39
+ }>;
40
+ /**
41
+ * Delete a referral relationship
42
+ * DELETE /api/:storeCode/member/:member/referral
43
+ */
44
+ export declare function referralDelete(input: {
45
+ storeCode?: string;
46
+ memberId: string;
47
+ }): Promise<void>;
@@ -0,0 +1,115 @@
1
+ import { apiGet, apiPost, apiDelete } from "../../client/http.js";
2
+ import { formatApiError, OpenLoyaltyError } from "../../utils/errors.js";
3
+ import { getStoreCode } from "../../config.js";
4
+ /**
5
+ * Create a referral relationship between two members
6
+ * POST /api/:storeCode/member/:member/referral
7
+ */
8
+ export async function referralCreate(input) {
9
+ const storeCode = getStoreCode(input.storeCode);
10
+ // Validate that memberId and referrerId are different
11
+ if (input.memberId === input.referrerId) {
12
+ throw new OpenLoyaltyError({
13
+ code: "INVALID_REFERRAL",
14
+ message: "A member cannot refer themselves",
15
+ hint: "The memberId (referee) must be different from the referrerId (referrer). The referee is the new member, the referrer is the existing member who made the referral.",
16
+ relatedTool: "ol_referral_create",
17
+ });
18
+ }
19
+ try {
20
+ await apiPost(`/${storeCode}/member/${input.memberId}/referral`, { referrerId: input.referrerId });
21
+ }
22
+ catch (error) {
23
+ const errorMessage = error instanceof Error ? error.message : String(error);
24
+ if (errorMessage.includes("already has a referrer") || errorMessage.includes("referral already exists")) {
25
+ throw new OpenLoyaltyError({
26
+ code: "REFERRAL_EXISTS",
27
+ message: "This member already has a referral relationship",
28
+ hint: `Member ${input.memberId} has already been referred by someone. Use referral_list(refereeId: "${input.memberId}") to see existing referral.`,
29
+ relatedTool: "ol_referral_create",
30
+ });
31
+ }
32
+ if (errorMessage.includes("not found") || errorMessage.includes("Not Found")) {
33
+ throw new OpenLoyaltyError({
34
+ code: "MEMBER_NOT_FOUND",
35
+ message: "One or both member IDs do not exist",
36
+ hint: `Verify both members exist: member_get(memberId: "${input.memberId}") for referee and member_get(memberId: "${input.referrerId}") for referrer.`,
37
+ relatedTool: "ol_referral_create",
38
+ });
39
+ }
40
+ throw formatApiError(error, "ol_referral_create");
41
+ }
42
+ }
43
+ /**
44
+ * List referrals with optional filters
45
+ * GET /api/:storeCode/referral
46
+ */
47
+ export async function referralList(input) {
48
+ const storeCode = getStoreCode(input.storeCode);
49
+ const params = new URLSearchParams();
50
+ if (input.referralId)
51
+ params.append("referralId", input.referralId);
52
+ if (input.referrerId)
53
+ params.append("referrerId", input.referrerId);
54
+ if (input.referrerName)
55
+ params.append("referrerName", input.referrerName);
56
+ if (input.referrerToken)
57
+ params.append("referrerToken", input.referrerToken);
58
+ if (input.refereeId)
59
+ params.append("refereeId", input.refereeId);
60
+ if (input.refereeName)
61
+ params.append("refereeName", input.refereeName);
62
+ if (input.createdAt)
63
+ params.append("createdAt", input.createdAt);
64
+ if (input.page)
65
+ params.append("_page", String(input.page));
66
+ if (input.perPage)
67
+ params.append("_itemsOnPage", String(input.perPage));
68
+ const queryString = params.toString();
69
+ const url = `/${storeCode}/referral${queryString ? `?${queryString}` : ""}`;
70
+ try {
71
+ const response = await apiGet(url);
72
+ const referrals = (response.items || []).map((item) => ({
73
+ referralId: item.referralId,
74
+ referrerId: item.referrerId,
75
+ referrerName: item.referrerName,
76
+ referrerToken: item.referrerToken,
77
+ refereeId: item.refereeId,
78
+ refereeName: item.refereeName,
79
+ createdAt: item.createdAt,
80
+ }));
81
+ const total = response.total || {};
82
+ return {
83
+ referrals,
84
+ total: {
85
+ all: typeof total.all === "number" ? total.all : undefined,
86
+ filtered: typeof total.filtered === "number" ? total.filtered : undefined,
87
+ },
88
+ };
89
+ }
90
+ catch (error) {
91
+ throw formatApiError(error, "ol_referral_list");
92
+ }
93
+ }
94
+ /**
95
+ * Delete a referral relationship
96
+ * DELETE /api/:storeCode/member/:member/referral
97
+ */
98
+ export async function referralDelete(input) {
99
+ const storeCode = getStoreCode(input.storeCode);
100
+ try {
101
+ await apiDelete(`/${storeCode}/member/${input.memberId}/referral`);
102
+ }
103
+ catch (error) {
104
+ const errorMessage = error instanceof Error ? error.message : String(error);
105
+ if (errorMessage.includes("not found") || errorMessage.includes("Not Found")) {
106
+ throw new OpenLoyaltyError({
107
+ code: "REFERRAL_NOT_FOUND",
108
+ message: "No referral relationship found for this member",
109
+ hint: `Member ${input.memberId} does not have a referral relationship. Use referral_list(refereeId: "${input.memberId}") to verify.`,
110
+ relatedTool: "ol_referral_delete",
111
+ });
112
+ }
113
+ throw formatApiError(error, "ol_referral_delete");
114
+ }
115
+ }
@@ -0,0 +1,44 @@
1
+ export { ReferralCreateInputSchema, ReferralListInputSchema, ReferralDeleteInputSchema, } from "./schemas.js";
2
+ export { referralCreate, referralList, referralDelete } from "./handlers.js";
3
+ import { referralCreate, referralList, referralDelete } from "./handlers.js";
4
+ export declare const referralToolDefinitions: readonly [{
5
+ readonly name: "ol_referral_create";
6
+ readonly title: "Create Referral Relationship";
7
+ readonly description: string;
8
+ readonly readOnly: false;
9
+ readonly inputSchema: {
10
+ storeCode: import("zod").ZodOptional<import("zod").ZodString>;
11
+ memberId: import("zod").ZodString;
12
+ referrerId: import("zod").ZodString;
13
+ };
14
+ readonly handler: typeof referralCreate;
15
+ }, {
16
+ readonly name: "ol_referral_list";
17
+ readonly title: "List Referrals";
18
+ readonly description: string;
19
+ readonly readOnly: true;
20
+ readonly inputSchema: {
21
+ storeCode: import("zod").ZodOptional<import("zod").ZodString>;
22
+ referralId: import("zod").ZodOptional<import("zod").ZodString>;
23
+ referrerId: import("zod").ZodOptional<import("zod").ZodString>;
24
+ referrerName: import("zod").ZodOptional<import("zod").ZodString>;
25
+ referrerToken: import("zod").ZodOptional<import("zod").ZodString>;
26
+ refereeId: import("zod").ZodOptional<import("zod").ZodString>;
27
+ refereeName: import("zod").ZodOptional<import("zod").ZodString>;
28
+ createdAt: import("zod").ZodOptional<import("zod").ZodString>;
29
+ page: import("zod").ZodOptional<import("zod").ZodNumber>;
30
+ perPage: import("zod").ZodOptional<import("zod").ZodNumber>;
31
+ };
32
+ readonly handler: typeof referralList;
33
+ }, {
34
+ readonly name: "ol_referral_delete";
35
+ readonly title: "Delete Referral Relationship";
36
+ readonly description: string;
37
+ readonly readOnly: false;
38
+ readonly destructive: true;
39
+ readonly inputSchema: {
40
+ storeCode: import("zod").ZodOptional<import("zod").ZodString>;
41
+ memberId: import("zod").ZodString;
42
+ };
43
+ readonly handler: typeof referralDelete;
44
+ }];
@@ -0,0 +1,44 @@
1
+ // Re-export schemas
2
+ export { ReferralCreateInputSchema, ReferralListInputSchema, ReferralDeleteInputSchema, } from "./schemas.js";
3
+ // Re-export handlers
4
+ export { referralCreate, referralList, referralDelete } from "./handlers.js";
5
+ // Imports for tool definitions
6
+ import { ReferralCreateInputSchema, ReferralListInputSchema, ReferralDeleteInputSchema, } from "./schemas.js";
7
+ import { referralCreate, referralList, referralDelete } from "./handlers.js";
8
+ // Tool definitions
9
+ export const referralToolDefinitions = [
10
+ {
11
+ name: "ol_referral_create",
12
+ title: "Create Referral Relationship",
13
+ description: "Create a referral relationship between an existing member (referrer) and a new member (referee). " +
14
+ "The referrer is the member who made the referral and will receive referral rewards. " +
15
+ "The referee (memberId) is the new member who was referred. " +
16
+ "Use this after creating a new member who was referred by an existing member. " +
17
+ "Both members must exist. A member can only have one referrer.",
18
+ readOnly: false,
19
+ inputSchema: ReferralCreateInputSchema,
20
+ handler: referralCreate,
21
+ },
22
+ {
23
+ name: "ol_referral_list",
24
+ title: "List Referrals",
25
+ description: "List referral relationships with optional filters. " +
26
+ "Filter by referrerId to see all members a specific person has referred. " +
27
+ "Filter by refereeId to find who referred a specific member. " +
28
+ "Returns referralId, referrerId, referrerName, refereeId, refereeName, and createdAt.",
29
+ readOnly: true,
30
+ inputSchema: ReferralListInputSchema,
31
+ handler: referralList,
32
+ },
33
+ {
34
+ name: "ol_referral_delete",
35
+ title: "Delete Referral Relationship",
36
+ description: "Delete a referral relationship for a member. " +
37
+ "Use with caution - this removes the referral tracking but may not reverse any rewards already given. " +
38
+ "The memberId is the referee (the member who was referred).",
39
+ readOnly: false,
40
+ destructive: true,
41
+ inputSchema: ReferralDeleteInputSchema,
42
+ handler: referralDelete,
43
+ },
44
+ ];
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Schema for creating a referral relationship
4
+ * POST /api/:storeCode/member/:member/referral
5
+ */
6
+ export declare const ReferralCreateInputSchema: {
7
+ storeCode: z.ZodOptional<z.ZodString>;
8
+ memberId: z.ZodString;
9
+ referrerId: z.ZodString;
10
+ };
11
+ /**
12
+ * Schema for listing referrals
13
+ * GET /api/:storeCode/referral
14
+ */
15
+ export declare const ReferralListInputSchema: {
16
+ storeCode: z.ZodOptional<z.ZodString>;
17
+ referralId: z.ZodOptional<z.ZodString>;
18
+ referrerId: z.ZodOptional<z.ZodString>;
19
+ referrerName: z.ZodOptional<z.ZodString>;
20
+ referrerToken: z.ZodOptional<z.ZodString>;
21
+ refereeId: z.ZodOptional<z.ZodString>;
22
+ refereeName: z.ZodOptional<z.ZodString>;
23
+ createdAt: z.ZodOptional<z.ZodString>;
24
+ page: z.ZodOptional<z.ZodNumber>;
25
+ perPage: z.ZodOptional<z.ZodNumber>;
26
+ };
27
+ /**
28
+ * Schema for deleting a referral relationship
29
+ * DELETE /api/:storeCode/member/:member/referral
30
+ */
31
+ export declare const ReferralDeleteInputSchema: {
32
+ storeCode: z.ZodOptional<z.ZodString>;
33
+ memberId: z.ZodString;
34
+ };
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Schema for creating a referral relationship
4
+ * POST /api/:storeCode/member/:member/referral
5
+ */
6
+ export const ReferralCreateInputSchema = {
7
+ storeCode: z
8
+ .string()
9
+ .optional()
10
+ .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."),
11
+ memberId: z
12
+ .string()
13
+ .uuid()
14
+ .describe("The member ID (UUID) of the referee (the new member being referred). This is the member who was referred by someone else."),
15
+ referrerId: z
16
+ .string()
17
+ .uuid()
18
+ .describe("The member ID (UUID) of the referrer (the existing member who made the referral). This member will receive referral rewards."),
19
+ };
20
+ /**
21
+ * Schema for listing referrals
22
+ * GET /api/:storeCode/referral
23
+ */
24
+ export const ReferralListInputSchema = {
25
+ storeCode: z
26
+ .string()
27
+ .optional()
28
+ .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."),
29
+ referralId: z.string().uuid().optional().describe("Filter by specific referral ID"),
30
+ referrerId: z.string().uuid().optional().describe("Filter by referrer member ID"),
31
+ referrerName: z.string().max(255).optional().describe("Filter by referrer name"),
32
+ referrerToken: z.string().max(255).optional().describe("Filter by referrer token"),
33
+ refereeId: z.string().uuid().optional().describe("Filter by referee member ID"),
34
+ refereeName: z.string().max(255).optional().describe("Filter by referee name"),
35
+ createdAt: z.string().optional().describe("Filter by creation date (ISO 8601)"),
36
+ page: z.number().int().min(1).optional().describe("Page number (starts from 1)"),
37
+ perPage: z.number().int().min(1).max(100).optional().describe("Items per page (default 25, max 100)"),
38
+ };
39
+ /**
40
+ * Schema for deleting a referral relationship
41
+ * DELETE /api/:storeCode/member/:member/referral
42
+ */
43
+ export const ReferralDeleteInputSchema = {
44
+ storeCode: z
45
+ .string()
46
+ .optional()
47
+ .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."),
48
+ memberId: z
49
+ .string()
50
+ .uuid()
51
+ .describe("The member ID (UUID) of the referee whose referral relationship should be deleted."),
52
+ };