@brainerce/mcp-server 3.12.2 → 3.12.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/bin/http.js CHANGED
@@ -3324,11 +3324,18 @@ Points are earned automatically by the platform when an order is paid \u2014 the
3324
3324
  \`\`\`typescript
3325
3325
  // requires client.setCustomerToken(auth.token)
3326
3326
  const status = await client.getLoyaltyStatus();
3327
- // { enrolled, pointsBalance, lifetimeEarned, program: { pointsName, currencyRatio, status } | null }
3327
+ // {
3328
+ // enrolled, pointsBalance, lifetimeEarned,
3329
+ // program: { pointsName, currencyRatio, status } | null,
3330
+ // tier: { id, name, level, pointsMultiplier } | null,
3331
+ // nextTier: { id, name, level, pointsMultiplier, qualificationType, qualificationThreshold } | null,
3332
+ // progressToNextTier, pointsToNextTier,
3333
+ // }
3328
3334
  \`\`\`
3329
3335
 
3330
3336
  - \`program === null\` \u2192 the store has no loyalty program; hide the loyalty UI.
3331
3337
  - \`program.status !== 'ACTIVE'\` \u2192 program paused/draft; hide the loyalty UI.
3338
+ - \`tier\`/\`nextTier\` are \`null\` when the store hasn't configured tiers, or the customer hasn't qualified for one yet.
3332
3339
 
3333
3340
  ## Enroll (only if auto-enroll is off)
3334
3341
 
@@ -3336,19 +3343,30 @@ const status = await client.getLoyaltyStatus();
3336
3343
  await client.enrollInLoyalty(); // same status shape; no-op if already enrolled
3337
3344
  \`\`\`
3338
3345
 
3346
+ May grant a one-time "joined the program" bonus if configured \u2014 distinct from any account-signup bonus (granted automatically on registration, not by this call).
3347
+
3339
3348
  ## Rewards & redemption
3340
3349
 
3341
3350
  \`\`\`typescript
3342
3351
  const rewards = await client.getAvailableRewards();
3343
- // [{ id, name, description, pointsCost, discountValue, minOrderAmount, maxUsesPerUser, isActive }]
3352
+ // [{ id, name, description, pointsCost, type, discountValue, minOrderAmount, maxUsesPerUser, minTierLevel, isActive }]
3353
+ // Already filtered to rewards the customer's current tier qualifies for.
3344
3354
 
3345
- const { couponCode, discountValue, pointsBalance } = await client.redeemLoyaltyReward(rewardId);
3355
+ const { couponCode, discountType, discountValue, pointsBalance } =
3356
+ await client.redeemLoyaltyReward(rewardId);
3346
3357
  await client.applyCoupon(cartId, couponCode); // applies via the normal coupon engine
3347
3358
  \`\`\`
3348
3359
 
3349
- - \`redeemLoyaltyReward\` mints a one-time fixed-amount coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3350
- - Throws if the customer has insufficient points. If minting fails, points are refunded automatically.
3360
+ - \`reward.type\` is \`'FIXED_DISCOUNT'\` (currency amount) or \`'PERCENT_DISCOUNT'\` (0-100 percent) \u2014 the redeem result's \`discountType\` matches.
3361
+ - \`redeemLoyaltyReward\` mints a one-time coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3362
+ - Throws if the customer has insufficient points, or their tier is below \`reward.minTierLevel\`. If minting fails, points are refunded automatically.
3351
3363
  - Disable a reward's redeem button when \`pointsBalance < reward.pointsCost\`.
3364
+
3365
+ ## Social share (optional)
3366
+
3367
+ \`\`\`typescript
3368
+ await client.reportSocialShare('instagram'); // platform optional, self-reported, once per customer
3369
+ \`\`\`
3352
3370
  `;
3353
3371
  }
3354
3372
  function getSectionByTopic(topic, connectionId, currency) {
@@ -4884,6 +4902,18 @@ interface TaxEstimateResponse {
4884
4902
  // full shipping address. The country comes from your edge runtime
4885
4903
  // (CF-IPCountry / request.geo.country / etc.), NOT the request IP.`;
4886
4904
  var LOYALTY_TYPES = `// ---- Loyalty & Rewards (storefront mode only) ----
4905
+ interface LoyaltyTierSummary {
4906
+ id: string;
4907
+ name: string;
4908
+ level: number; // ordering; higher = better tier
4909
+ pointsMultiplier: number;
4910
+ }
4911
+
4912
+ interface LoyaltyNextTierSummary extends LoyaltyTierSummary {
4913
+ qualificationType: 'SPEND' | 'POINTS';
4914
+ qualificationThreshold: number;
4915
+ }
4916
+
4887
4917
  interface LoyaltyStatus {
4888
4918
  enrolled: boolean;
4889
4919
  pointsBalance: number; // redeemable points (pending earns excluded)
@@ -4893,6 +4923,10 @@ interface LoyaltyStatus {
4893
4923
  currencyRatio: number; // points needed to redeem 1 unit of store currency
4894
4924
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
4895
4925
  } | null; // null when the store has no loyalty program
4926
+ tier: LoyaltyTierSummary | null; // null if untiered / no tiers configured
4927
+ nextTier: LoyaltyNextTierSummary | null; // null if at the top tier already
4928
+ progressToNextTier: number; // 0..1
4929
+ pointsToNextTier: number | null;
4896
4930
  }
4897
4931
 
4898
4932
  interface LoyaltyReward {
@@ -4900,16 +4934,19 @@ interface LoyaltyReward {
4900
4934
  name: string;
4901
4935
  description: string | null;
4902
4936
  pointsCost: number;
4903
- discountValue: number; // fixed amount off, store currency
4937
+ type: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4938
+ discountValue: number; // currency amount (FIXED_DISCOUNT) or 0-100 percent (PERCENT_DISCOUNT)
4904
4939
  minOrderAmount: number | null;
4905
4940
  maxUsesPerUser: number;
4906
4941
  isActive: boolean;
4942
+ minTierLevel: number | null; // minimum tier level required, or null for no restriction
4907
4943
  createdAt: string;
4908
4944
  updatedAt: string;
4909
4945
  }
4910
4946
 
4911
4947
  interface RedeemRewardResult {
4912
4948
  couponCode: string; // one-time coupon to apply at checkout
4949
+ discountType: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4913
4950
  discountValue: number;
4914
4951
  pointsSpent: number;
4915
4952
  pointsBalance: number; // remaining balance after redemption
@@ -4919,6 +4956,7 @@ interface RedeemRewardResult {
4919
4956
  // client.enrollInLoyalty(): Promise<LoyaltyStatus>
4920
4957
  // client.getAvailableRewards(): Promise<LoyaltyReward[]>
4921
4958
  // client.redeemLoyaltyReward(rewardId: string): Promise<RedeemRewardResult>
4959
+ // client.reportSocialShare(platform?: string): Promise<{ awarded: boolean; points: number }>
4922
4960
  `;
4923
4961
  var TYPES_BY_DOMAIN = {
4924
4962
  products: PRODUCTS_TYPES,
@@ -6464,7 +6502,7 @@ function formatCapabilities(caps) {
6464
6502
  }
6465
6503
  if (caps.features.hasLoyaltyProgram) {
6466
6504
  suggestions.push(
6467
- "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus(), getAvailableRewards(), and redeemLoyaltyReward(id). Note: loyalty is NOT available in vibe-coded mode."
6505
+ "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance, tier progress, and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus() (includes tier/nextTier/progressToNextTier), getAvailableRewards(), redeemLoyaltyReward(id), and optionally reportSocialShare(). Note: loyalty is NOT available in vibe-coded mode."
6468
6506
  );
6469
6507
  }
6470
6508
  if (caps.features.hasCheckoutCustomFields) {
package/dist/bin/stdio.js CHANGED
@@ -3321,11 +3321,18 @@ Points are earned automatically by the platform when an order is paid \u2014 the
3321
3321
  \`\`\`typescript
3322
3322
  // requires client.setCustomerToken(auth.token)
3323
3323
  const status = await client.getLoyaltyStatus();
3324
- // { enrolled, pointsBalance, lifetimeEarned, program: { pointsName, currencyRatio, status } | null }
3324
+ // {
3325
+ // enrolled, pointsBalance, lifetimeEarned,
3326
+ // program: { pointsName, currencyRatio, status } | null,
3327
+ // tier: { id, name, level, pointsMultiplier } | null,
3328
+ // nextTier: { id, name, level, pointsMultiplier, qualificationType, qualificationThreshold } | null,
3329
+ // progressToNextTier, pointsToNextTier,
3330
+ // }
3325
3331
  \`\`\`
3326
3332
 
3327
3333
  - \`program === null\` \u2192 the store has no loyalty program; hide the loyalty UI.
3328
3334
  - \`program.status !== 'ACTIVE'\` \u2192 program paused/draft; hide the loyalty UI.
3335
+ - \`tier\`/\`nextTier\` are \`null\` when the store hasn't configured tiers, or the customer hasn't qualified for one yet.
3329
3336
 
3330
3337
  ## Enroll (only if auto-enroll is off)
3331
3338
 
@@ -3333,19 +3340,30 @@ const status = await client.getLoyaltyStatus();
3333
3340
  await client.enrollInLoyalty(); // same status shape; no-op if already enrolled
3334
3341
  \`\`\`
3335
3342
 
3343
+ May grant a one-time "joined the program" bonus if configured \u2014 distinct from any account-signup bonus (granted automatically on registration, not by this call).
3344
+
3336
3345
  ## Rewards & redemption
3337
3346
 
3338
3347
  \`\`\`typescript
3339
3348
  const rewards = await client.getAvailableRewards();
3340
- // [{ id, name, description, pointsCost, discountValue, minOrderAmount, maxUsesPerUser, isActive }]
3349
+ // [{ id, name, description, pointsCost, type, discountValue, minOrderAmount, maxUsesPerUser, minTierLevel, isActive }]
3350
+ // Already filtered to rewards the customer's current tier qualifies for.
3341
3351
 
3342
- const { couponCode, discountValue, pointsBalance } = await client.redeemLoyaltyReward(rewardId);
3352
+ const { couponCode, discountType, discountValue, pointsBalance } =
3353
+ await client.redeemLoyaltyReward(rewardId);
3343
3354
  await client.applyCoupon(cartId, couponCode); // applies via the normal coupon engine
3344
3355
  \`\`\`
3345
3356
 
3346
- - \`redeemLoyaltyReward\` mints a one-time fixed-amount coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3347
- - Throws if the customer has insufficient points. If minting fails, points are refunded automatically.
3357
+ - \`reward.type\` is \`'FIXED_DISCOUNT'\` (currency amount) or \`'PERCENT_DISCOUNT'\` (0-100 percent) \u2014 the redeem result's \`discountType\` matches.
3358
+ - \`redeemLoyaltyReward\` mints a one-time coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3359
+ - Throws if the customer has insufficient points, or their tier is below \`reward.minTierLevel\`. If minting fails, points are refunded automatically.
3348
3360
  - Disable a reward's redeem button when \`pointsBalance < reward.pointsCost\`.
3361
+
3362
+ ## Social share (optional)
3363
+
3364
+ \`\`\`typescript
3365
+ await client.reportSocialShare('instagram'); // platform optional, self-reported, once per customer
3366
+ \`\`\`
3349
3367
  `;
3350
3368
  }
3351
3369
  function getSectionByTopic(topic, connectionId, currency) {
@@ -4881,6 +4899,18 @@ interface TaxEstimateResponse {
4881
4899
  // full shipping address. The country comes from your edge runtime
4882
4900
  // (CF-IPCountry / request.geo.country / etc.), NOT the request IP.`;
4883
4901
  var LOYALTY_TYPES = `// ---- Loyalty & Rewards (storefront mode only) ----
4902
+ interface LoyaltyTierSummary {
4903
+ id: string;
4904
+ name: string;
4905
+ level: number; // ordering; higher = better tier
4906
+ pointsMultiplier: number;
4907
+ }
4908
+
4909
+ interface LoyaltyNextTierSummary extends LoyaltyTierSummary {
4910
+ qualificationType: 'SPEND' | 'POINTS';
4911
+ qualificationThreshold: number;
4912
+ }
4913
+
4884
4914
  interface LoyaltyStatus {
4885
4915
  enrolled: boolean;
4886
4916
  pointsBalance: number; // redeemable points (pending earns excluded)
@@ -4890,6 +4920,10 @@ interface LoyaltyStatus {
4890
4920
  currencyRatio: number; // points needed to redeem 1 unit of store currency
4891
4921
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
4892
4922
  } | null; // null when the store has no loyalty program
4923
+ tier: LoyaltyTierSummary | null; // null if untiered / no tiers configured
4924
+ nextTier: LoyaltyNextTierSummary | null; // null if at the top tier already
4925
+ progressToNextTier: number; // 0..1
4926
+ pointsToNextTier: number | null;
4893
4927
  }
4894
4928
 
4895
4929
  interface LoyaltyReward {
@@ -4897,16 +4931,19 @@ interface LoyaltyReward {
4897
4931
  name: string;
4898
4932
  description: string | null;
4899
4933
  pointsCost: number;
4900
- discountValue: number; // fixed amount off, store currency
4934
+ type: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4935
+ discountValue: number; // currency amount (FIXED_DISCOUNT) or 0-100 percent (PERCENT_DISCOUNT)
4901
4936
  minOrderAmount: number | null;
4902
4937
  maxUsesPerUser: number;
4903
4938
  isActive: boolean;
4939
+ minTierLevel: number | null; // minimum tier level required, or null for no restriction
4904
4940
  createdAt: string;
4905
4941
  updatedAt: string;
4906
4942
  }
4907
4943
 
4908
4944
  interface RedeemRewardResult {
4909
4945
  couponCode: string; // one-time coupon to apply at checkout
4946
+ discountType: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4910
4947
  discountValue: number;
4911
4948
  pointsSpent: number;
4912
4949
  pointsBalance: number; // remaining balance after redemption
@@ -4916,6 +4953,7 @@ interface RedeemRewardResult {
4916
4953
  // client.enrollInLoyalty(): Promise<LoyaltyStatus>
4917
4954
  // client.getAvailableRewards(): Promise<LoyaltyReward[]>
4918
4955
  // client.redeemLoyaltyReward(rewardId: string): Promise<RedeemRewardResult>
4956
+ // client.reportSocialShare(platform?: string): Promise<{ awarded: boolean; points: number }>
4919
4957
  `;
4920
4958
  var TYPES_BY_DOMAIN = {
4921
4959
  products: PRODUCTS_TYPES,
@@ -6461,7 +6499,7 @@ function formatCapabilities(caps) {
6461
6499
  }
6462
6500
  if (caps.features.hasLoyaltyProgram) {
6463
6501
  suggestions.push(
6464
- "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus(), getAvailableRewards(), and redeemLoyaltyReward(id). Note: loyalty is NOT available in vibe-coded mode."
6502
+ "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance, tier progress, and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus() (includes tier/nextTier/progressToNextTier), getAvailableRewards(), redeemLoyaltyReward(id), and optionally reportSocialShare(). Note: loyalty is NOT available in vibe-coded mode."
6465
6503
  );
6466
6504
  }
6467
6505
  if (caps.features.hasCheckoutCustomFields) {
package/dist/index.js CHANGED
@@ -3347,11 +3347,18 @@ Points are earned automatically by the platform when an order is paid \u2014 the
3347
3347
  \`\`\`typescript
3348
3348
  // requires client.setCustomerToken(auth.token)
3349
3349
  const status = await client.getLoyaltyStatus();
3350
- // { enrolled, pointsBalance, lifetimeEarned, program: { pointsName, currencyRatio, status } | null }
3350
+ // {
3351
+ // enrolled, pointsBalance, lifetimeEarned,
3352
+ // program: { pointsName, currencyRatio, status } | null,
3353
+ // tier: { id, name, level, pointsMultiplier } | null,
3354
+ // nextTier: { id, name, level, pointsMultiplier, qualificationType, qualificationThreshold } | null,
3355
+ // progressToNextTier, pointsToNextTier,
3356
+ // }
3351
3357
  \`\`\`
3352
3358
 
3353
3359
  - \`program === null\` \u2192 the store has no loyalty program; hide the loyalty UI.
3354
3360
  - \`program.status !== 'ACTIVE'\` \u2192 program paused/draft; hide the loyalty UI.
3361
+ - \`tier\`/\`nextTier\` are \`null\` when the store hasn't configured tiers, or the customer hasn't qualified for one yet.
3355
3362
 
3356
3363
  ## Enroll (only if auto-enroll is off)
3357
3364
 
@@ -3359,19 +3366,30 @@ const status = await client.getLoyaltyStatus();
3359
3366
  await client.enrollInLoyalty(); // same status shape; no-op if already enrolled
3360
3367
  \`\`\`
3361
3368
 
3369
+ May grant a one-time "joined the program" bonus if configured \u2014 distinct from any account-signup bonus (granted automatically on registration, not by this call).
3370
+
3362
3371
  ## Rewards & redemption
3363
3372
 
3364
3373
  \`\`\`typescript
3365
3374
  const rewards = await client.getAvailableRewards();
3366
- // [{ id, name, description, pointsCost, discountValue, minOrderAmount, maxUsesPerUser, isActive }]
3375
+ // [{ id, name, description, pointsCost, type, discountValue, minOrderAmount, maxUsesPerUser, minTierLevel, isActive }]
3376
+ // Already filtered to rewards the customer's current tier qualifies for.
3367
3377
 
3368
- const { couponCode, discountValue, pointsBalance } = await client.redeemLoyaltyReward(rewardId);
3378
+ const { couponCode, discountType, discountValue, pointsBalance } =
3379
+ await client.redeemLoyaltyReward(rewardId);
3369
3380
  await client.applyCoupon(cartId, couponCode); // applies via the normal coupon engine
3370
3381
  \`\`\`
3371
3382
 
3372
- - \`redeemLoyaltyReward\` mints a one-time fixed-amount coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3373
- - Throws if the customer has insufficient points. If minting fails, points are refunded automatically.
3383
+ - \`reward.type\` is \`'FIXED_DISCOUNT'\` (currency amount) or \`'PERCENT_DISCOUNT'\` (0-100 percent) \u2014 the redeem result's \`discountType\` matches.
3384
+ - \`redeemLoyaltyReward\` mints a one-time coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3385
+ - Throws if the customer has insufficient points, or their tier is below \`reward.minTierLevel\`. If minting fails, points are refunded automatically.
3374
3386
  - Disable a reward's redeem button when \`pointsBalance < reward.pointsCost\`.
3387
+
3388
+ ## Social share (optional)
3389
+
3390
+ \`\`\`typescript
3391
+ await client.reportSocialShare('instagram'); // platform optional, self-reported, once per customer
3392
+ \`\`\`
3375
3393
  `;
3376
3394
  }
3377
3395
  function getSectionByTopic(topic, connectionId, currency) {
@@ -4907,6 +4925,18 @@ interface TaxEstimateResponse {
4907
4925
  // full shipping address. The country comes from your edge runtime
4908
4926
  // (CF-IPCountry / request.geo.country / etc.), NOT the request IP.`;
4909
4927
  var LOYALTY_TYPES = `// ---- Loyalty & Rewards (storefront mode only) ----
4928
+ interface LoyaltyTierSummary {
4929
+ id: string;
4930
+ name: string;
4931
+ level: number; // ordering; higher = better tier
4932
+ pointsMultiplier: number;
4933
+ }
4934
+
4935
+ interface LoyaltyNextTierSummary extends LoyaltyTierSummary {
4936
+ qualificationType: 'SPEND' | 'POINTS';
4937
+ qualificationThreshold: number;
4938
+ }
4939
+
4910
4940
  interface LoyaltyStatus {
4911
4941
  enrolled: boolean;
4912
4942
  pointsBalance: number; // redeemable points (pending earns excluded)
@@ -4916,6 +4946,10 @@ interface LoyaltyStatus {
4916
4946
  currencyRatio: number; // points needed to redeem 1 unit of store currency
4917
4947
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
4918
4948
  } | null; // null when the store has no loyalty program
4949
+ tier: LoyaltyTierSummary | null; // null if untiered / no tiers configured
4950
+ nextTier: LoyaltyNextTierSummary | null; // null if at the top tier already
4951
+ progressToNextTier: number; // 0..1
4952
+ pointsToNextTier: number | null;
4919
4953
  }
4920
4954
 
4921
4955
  interface LoyaltyReward {
@@ -4923,16 +4957,19 @@ interface LoyaltyReward {
4923
4957
  name: string;
4924
4958
  description: string | null;
4925
4959
  pointsCost: number;
4926
- discountValue: number; // fixed amount off, store currency
4960
+ type: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4961
+ discountValue: number; // currency amount (FIXED_DISCOUNT) or 0-100 percent (PERCENT_DISCOUNT)
4927
4962
  minOrderAmount: number | null;
4928
4963
  maxUsesPerUser: number;
4929
4964
  isActive: boolean;
4965
+ minTierLevel: number | null; // minimum tier level required, or null for no restriction
4930
4966
  createdAt: string;
4931
4967
  updatedAt: string;
4932
4968
  }
4933
4969
 
4934
4970
  interface RedeemRewardResult {
4935
4971
  couponCode: string; // one-time coupon to apply at checkout
4972
+ discountType: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4936
4973
  discountValue: number;
4937
4974
  pointsSpent: number;
4938
4975
  pointsBalance: number; // remaining balance after redemption
@@ -4942,6 +4979,7 @@ interface RedeemRewardResult {
4942
4979
  // client.enrollInLoyalty(): Promise<LoyaltyStatus>
4943
4980
  // client.getAvailableRewards(): Promise<LoyaltyReward[]>
4944
4981
  // client.redeemLoyaltyReward(rewardId: string): Promise<RedeemRewardResult>
4982
+ // client.reportSocialShare(platform?: string): Promise<{ awarded: boolean; points: number }>
4945
4983
  `;
4946
4984
  var TYPES_BY_DOMAIN = {
4947
4985
  products: PRODUCTS_TYPES,
@@ -6487,7 +6525,7 @@ function formatCapabilities(caps) {
6487
6525
  }
6488
6526
  if (caps.features.hasLoyaltyProgram) {
6489
6527
  suggestions.push(
6490
- "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus(), getAvailableRewards(), and redeemLoyaltyReward(id). Note: loyalty is NOT available in vibe-coded mode."
6528
+ "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance, tier progress, and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus() (includes tier/nextTier/progressToNextTier), getAvailableRewards(), redeemLoyaltyReward(id), and optionally reportSocialShare(). Note: loyalty is NOT available in vibe-coded mode."
6491
6529
  );
6492
6530
  }
6493
6531
  if (caps.features.hasCheckoutCustomFields) {
package/dist/index.mjs CHANGED
@@ -3315,11 +3315,18 @@ Points are earned automatically by the platform when an order is paid \u2014 the
3315
3315
  \`\`\`typescript
3316
3316
  // requires client.setCustomerToken(auth.token)
3317
3317
  const status = await client.getLoyaltyStatus();
3318
- // { enrolled, pointsBalance, lifetimeEarned, program: { pointsName, currencyRatio, status } | null }
3318
+ // {
3319
+ // enrolled, pointsBalance, lifetimeEarned,
3320
+ // program: { pointsName, currencyRatio, status } | null,
3321
+ // tier: { id, name, level, pointsMultiplier } | null,
3322
+ // nextTier: { id, name, level, pointsMultiplier, qualificationType, qualificationThreshold } | null,
3323
+ // progressToNextTier, pointsToNextTier,
3324
+ // }
3319
3325
  \`\`\`
3320
3326
 
3321
3327
  - \`program === null\` \u2192 the store has no loyalty program; hide the loyalty UI.
3322
3328
  - \`program.status !== 'ACTIVE'\` \u2192 program paused/draft; hide the loyalty UI.
3329
+ - \`tier\`/\`nextTier\` are \`null\` when the store hasn't configured tiers, or the customer hasn't qualified for one yet.
3323
3330
 
3324
3331
  ## Enroll (only if auto-enroll is off)
3325
3332
 
@@ -3327,19 +3334,30 @@ const status = await client.getLoyaltyStatus();
3327
3334
  await client.enrollInLoyalty(); // same status shape; no-op if already enrolled
3328
3335
  \`\`\`
3329
3336
 
3337
+ May grant a one-time "joined the program" bonus if configured \u2014 distinct from any account-signup bonus (granted automatically on registration, not by this call).
3338
+
3330
3339
  ## Rewards & redemption
3331
3340
 
3332
3341
  \`\`\`typescript
3333
3342
  const rewards = await client.getAvailableRewards();
3334
- // [{ id, name, description, pointsCost, discountValue, minOrderAmount, maxUsesPerUser, isActive }]
3343
+ // [{ id, name, description, pointsCost, type, discountValue, minOrderAmount, maxUsesPerUser, minTierLevel, isActive }]
3344
+ // Already filtered to rewards the customer's current tier qualifies for.
3335
3345
 
3336
- const { couponCode, discountValue, pointsBalance } = await client.redeemLoyaltyReward(rewardId);
3346
+ const { couponCode, discountType, discountValue, pointsBalance } =
3347
+ await client.redeemLoyaltyReward(rewardId);
3337
3348
  await client.applyCoupon(cartId, couponCode); // applies via the normal coupon engine
3338
3349
  \`\`\`
3339
3350
 
3340
- - \`redeemLoyaltyReward\` mints a one-time fixed-amount coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3341
- - Throws if the customer has insufficient points. If minting fails, points are refunded automatically.
3351
+ - \`reward.type\` is \`'FIXED_DISCOUNT'\` (currency amount) or \`'PERCENT_DISCOUNT'\` (0-100 percent) \u2014 the redeem result's \`discountType\` matches.
3352
+ - \`redeemLoyaltyReward\` mints a one-time coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
3353
+ - Throws if the customer has insufficient points, or their tier is below \`reward.minTierLevel\`. If minting fails, points are refunded automatically.
3342
3354
  - Disable a reward's redeem button when \`pointsBalance < reward.pointsCost\`.
3355
+
3356
+ ## Social share (optional)
3357
+
3358
+ \`\`\`typescript
3359
+ await client.reportSocialShare('instagram'); // platform optional, self-reported, once per customer
3360
+ \`\`\`
3343
3361
  `;
3344
3362
  }
3345
3363
  function getSectionByTopic(topic, connectionId, currency) {
@@ -4875,6 +4893,18 @@ interface TaxEstimateResponse {
4875
4893
  // full shipping address. The country comes from your edge runtime
4876
4894
  // (CF-IPCountry / request.geo.country / etc.), NOT the request IP.`;
4877
4895
  var LOYALTY_TYPES = `// ---- Loyalty & Rewards (storefront mode only) ----
4896
+ interface LoyaltyTierSummary {
4897
+ id: string;
4898
+ name: string;
4899
+ level: number; // ordering; higher = better tier
4900
+ pointsMultiplier: number;
4901
+ }
4902
+
4903
+ interface LoyaltyNextTierSummary extends LoyaltyTierSummary {
4904
+ qualificationType: 'SPEND' | 'POINTS';
4905
+ qualificationThreshold: number;
4906
+ }
4907
+
4878
4908
  interface LoyaltyStatus {
4879
4909
  enrolled: boolean;
4880
4910
  pointsBalance: number; // redeemable points (pending earns excluded)
@@ -4884,6 +4914,10 @@ interface LoyaltyStatus {
4884
4914
  currencyRatio: number; // points needed to redeem 1 unit of store currency
4885
4915
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
4886
4916
  } | null; // null when the store has no loyalty program
4917
+ tier: LoyaltyTierSummary | null; // null if untiered / no tiers configured
4918
+ nextTier: LoyaltyNextTierSummary | null; // null if at the top tier already
4919
+ progressToNextTier: number; // 0..1
4920
+ pointsToNextTier: number | null;
4887
4921
  }
4888
4922
 
4889
4923
  interface LoyaltyReward {
@@ -4891,16 +4925,19 @@ interface LoyaltyReward {
4891
4925
  name: string;
4892
4926
  description: string | null;
4893
4927
  pointsCost: number;
4894
- discountValue: number; // fixed amount off, store currency
4928
+ type: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4929
+ discountValue: number; // currency amount (FIXED_DISCOUNT) or 0-100 percent (PERCENT_DISCOUNT)
4895
4930
  minOrderAmount: number | null;
4896
4931
  maxUsesPerUser: number;
4897
4932
  isActive: boolean;
4933
+ minTierLevel: number | null; // minimum tier level required, or null for no restriction
4898
4934
  createdAt: string;
4899
4935
  updatedAt: string;
4900
4936
  }
4901
4937
 
4902
4938
  interface RedeemRewardResult {
4903
4939
  couponCode: string; // one-time coupon to apply at checkout
4940
+ discountType: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
4904
4941
  discountValue: number;
4905
4942
  pointsSpent: number;
4906
4943
  pointsBalance: number; // remaining balance after redemption
@@ -4910,6 +4947,7 @@ interface RedeemRewardResult {
4910
4947
  // client.enrollInLoyalty(): Promise<LoyaltyStatus>
4911
4948
  // client.getAvailableRewards(): Promise<LoyaltyReward[]>
4912
4949
  // client.redeemLoyaltyReward(rewardId: string): Promise<RedeemRewardResult>
4950
+ // client.reportSocialShare(platform?: string): Promise<{ awarded: boolean; points: number }>
4913
4951
  `;
4914
4952
  var TYPES_BY_DOMAIN = {
4915
4953
  products: PRODUCTS_TYPES,
@@ -6455,7 +6493,7 @@ function formatCapabilities(caps) {
6455
6493
  }
6456
6494
  if (caps.features.hasLoyaltyProgram) {
6457
6495
  suggestions.push(
6458
- "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus(), getAvailableRewards(), and redeemLoyaltyReward(id). Note: loyalty is NOT available in vibe-coded mode."
6496
+ "A loyalty program is active. In a storefront-mode client (new BrainerceClient({ storeId })), show the logged-in customer their points balance, tier progress, and redeemable rewards, and let them redeem for a coupon at checkout. Use getLoyaltyStatus() (includes tier/nextTier/progressToNextTier), getAvailableRewards(), redeemLoyaltyReward(id), and optionally reportSocialShare(). Note: loyalty is NOT available in vibe-coded mode."
6459
6497
  );
6460
6498
  }
6461
6499
  if (caps.features.hasCheckoutCustomFields) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainerce/mcp-server",
3
- "version": "3.12.2",
3
+ "version": "3.12.3",
4
4
  "packageManager": "pnpm@9.0.0",
5
5
  "description": "Framework-agnostic domain knowledge API for Brainerce. Provides SDK docs, types, business flows, critical rules, and store capabilities to AI tools like Lovable, Cursor, Bolt, v0, and Claude Code. Does NOT provide framework-specific boilerplate — clients build in whatever framework fits.",
6
6
  "bin": {