@brainerce/mcp-server 3.12.2 → 3.12.4
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 +172 -68
- package/dist/bin/stdio.js +136 -10
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +136 -10
- package/dist/index.mjs +136 -10
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -211,7 +211,7 @@ async function startCheckout() {
|
|
|
211
211
|
2. Customer optionally applies coupon on cart page \u2192 \`applyCoupon(cartId, code)\`
|
|
212
212
|
3. Detect payment providers \u2192 \`getPaymentProviders()\`
|
|
213
213
|
4. Start checkout session (\`startGuestCheckout()\` or \`createCheckout()\`)
|
|
214
|
-
5. Set shipping address (includes required email) \u2192 \`setShippingAddress()\`
|
|
214
|
+
5. Set shipping address (includes required email) \u2192 \`setShippingAddress()\` \u2014 also pass \`notes\` from the **"Order notes" textarea that every checkout page should include by default** (optional field, max 2000 chars; lands on the order for the merchant)
|
|
215
215
|
6. Select shipping method \u2192 \`selectShippingMethod()\`
|
|
216
216
|
6b. (Optional) Set checkout custom fields \u2192 \`setCheckoutCustomFields()\` \u2014 surcharges auto-calculated
|
|
217
217
|
7. Create payment intent \u2192 \`createPaymentIntent()\` \u2192 returns \`{ clientSecret, provider }\`
|
|
@@ -233,6 +233,8 @@ function CheckoutPage() {
|
|
|
233
233
|
const [checkout, setCheckout] = useState<Checkout | null>(null);
|
|
234
234
|
const [error, setError] = useState<string | null>(null);
|
|
235
235
|
const [loading, setLoading] = useState(true);
|
|
236
|
+
// Optional "Order notes" textarea \u2014 render it on the checkout page by default
|
|
237
|
+
const [orderNotes, setOrderNotes] = useState('');
|
|
236
238
|
|
|
237
239
|
useEffect(() => { startCheckout(); }, []);
|
|
238
240
|
|
|
@@ -267,6 +269,7 @@ function CheckoutPage() {
|
|
|
267
269
|
postalCode: cart.shippingAddress.postalCode,
|
|
268
270
|
country: cart.shippingAddress.country,
|
|
269
271
|
phone: cart.shippingAddress.phone,
|
|
272
|
+
notes: orderNotes || undefined, // from the "Order notes" textarea \u2014 include one by default
|
|
270
273
|
});
|
|
271
274
|
setCheckout(checkoutData);
|
|
272
275
|
|
|
@@ -2117,6 +2120,7 @@ A useful order card includes ALL of the following when the data is present. Each
|
|
|
2117
2120
|
| **Tracking** | \`order.trackingNumber\`, \`order.trackingUrl\`, \`order.carrier\`, \`order.shippedAt\`, \`order.deliveredAt\` | Link out to \`trackingUrl\` when set. |
|
|
2118
2121
|
| **Payment** | \`order.paymentMethod\`, \`order.financialStatus\` | Badge \`financialStatus\` (paid / pending / refunded / partially_refunded). |
|
|
2119
2122
|
| Downloads | \`order.hasDownloads\` \u2192 \`client.getOrderDownloads(id)\` | Separate call; returns \`OrderDownloadLink[]\`. |
|
|
2123
|
+
| **Order note** | \`order.notes\` | The shopper's own checkout note, echoed back read-only. Render when present ("Your order note"). |
|
|
2120
2124
|
| Financial summary | \`order.subtotal\`, \`order.appliedDiscounts\`, \`order.couponCode\` + \`couponDiscount\`, \`order.shippingAmount\`, \`order.taxAmount\`, \`order.totalAmount\` | Breakdown rows + final total. In VAT-inclusive mode \`taxAmount\` is 0 \u2014 read \`order.taxBreakdown.totalTax\` and label "Tax (incl.)". |
|
|
2121
2125
|
|
|
2122
2126
|
#### Rendering \`order.items[i].customizations\` by type
|
|
@@ -2142,7 +2146,6 @@ The storefront scaffolded by \`create-brainerce-store\` already implements this.
|
|
|
2142
2146
|
These fields are NOT returned to buyers by \`/customers/me/orders\`. If you see them in older examples, ignore them \u2014 they are for merchant/admin views only.
|
|
2143
2147
|
|
|
2144
2148
|
- \`order.accountId\`, \`order.storeId\`, \`order.customerId\` (already known on the request)
|
|
2145
|
-
- \`order.notes\` (internal merchant notes)
|
|
2146
2149
|
- \`order.customFieldValues\` (order-level checkout fields \u2014 merchant concept; buyers see \`items[i].customizations\`)
|
|
2147
2150
|
- \`order.appliedSurcharges\`, \`order.surchargeAmount\`, \`order.appliedRuleIds\`, \`order.downloadMeta\`, \`order.pickupLocationData\``;
|
|
2148
2151
|
}
|
|
@@ -2190,7 +2193,22 @@ function OrderConfirmation() {
|
|
|
2190
2193
|
|
|
2191
2194
|
**Common mistake:** Don't just check URL params and show success immediately!
|
|
2192
2195
|
You MUST call \`waitForOrder(checkoutId)\` to verify the order was created.
|
|
2193
|
-
Also call \`handlePaymentSuccess(checkoutId)\` to clear purchased items from the cart
|
|
2196
|
+
Also call \`handlePaymentSuccess(checkoutId)\` to clear purchased items from the cart.
|
|
2197
|
+
|
|
2198
|
+
### Optional: render full order details on the confirmation page
|
|
2199
|
+
|
|
2200
|
+
Want a richer thank-you page (items, shipping address, totals, the shopper's
|
|
2201
|
+
order note)? After \`waitForOrder\` succeeds, fetch the full buyer-safe order \u2014
|
|
2202
|
+
works for guests too (possession of the checkout id is the credential):
|
|
2203
|
+
|
|
2204
|
+
\`\`\`typescript
|
|
2205
|
+
const order = await client.getOrderByCheckout(checkoutId);
|
|
2206
|
+
// order.items, order.shippingAddress, order.notes, order.subtotal,
|
|
2207
|
+
// order.shippingAmount, order.taxAmount / order.taxBreakdown, order.totalAmount
|
|
2208
|
+
\`\`\`
|
|
2209
|
+
|
|
2210
|
+
Render whatever subset fits your design \u2014 same field shapes as the buyer
|
|
2211
|
+
order-history view (see "Buyer order view" section).`;
|
|
2194
2212
|
}
|
|
2195
2213
|
function getI18nSection() {
|
|
2196
2214
|
return `## Internationalization (i18n)
|
|
@@ -2520,6 +2538,8 @@ dashboard or the admin SDK).
|
|
|
2520
2538
|
|
|
2521
2539
|
\`\`\`typescript
|
|
2522
2540
|
// Publish to a specific vibe-coded site (admin mode):
|
|
2541
|
+
await admin.publishProductToSalesChannel('prod_id', 'vc_conn_id');
|
|
2542
|
+
await admin.publishCouponToSalesChannel('coupon_id', 'vc_conn_id');
|
|
2523
2543
|
await admin.publishCategoryToVibeCodedSite('cat_id', 'conn_id');
|
|
2524
2544
|
await admin.publishTagToVibeCodedSite('tag_id', 'conn_id');
|
|
2525
2545
|
await admin.publishBrandToVibeCodedSite('brand_id', 'conn_id');
|
|
@@ -3315,11 +3335,18 @@ Points are earned automatically by the platform when an order is paid \u2014 the
|
|
|
3315
3335
|
\`\`\`typescript
|
|
3316
3336
|
// requires client.setCustomerToken(auth.token)
|
|
3317
3337
|
const status = await client.getLoyaltyStatus();
|
|
3318
|
-
// {
|
|
3338
|
+
// {
|
|
3339
|
+
// enrolled, pointsBalance, lifetimeEarned,
|
|
3340
|
+
// program: { pointsName, currencyRatio, status } | null,
|
|
3341
|
+
// tier: { id, name, level, pointsMultiplier } | null,
|
|
3342
|
+
// nextTier: { id, name, level, pointsMultiplier, qualificationType, qualificationThreshold } | null,
|
|
3343
|
+
// progressToNextTier, pointsToNextTier,
|
|
3344
|
+
// }
|
|
3319
3345
|
\`\`\`
|
|
3320
3346
|
|
|
3321
3347
|
- \`program === null\` \u2192 the store has no loyalty program; hide the loyalty UI.
|
|
3322
3348
|
- \`program.status !== 'ACTIVE'\` \u2192 program paused/draft; hide the loyalty UI.
|
|
3349
|
+
- \`tier\`/\`nextTier\` are \`null\` when the store hasn't configured tiers, or the customer hasn't qualified for one yet.
|
|
3323
3350
|
|
|
3324
3351
|
## Enroll (only if auto-enroll is off)
|
|
3325
3352
|
|
|
@@ -3327,19 +3354,67 @@ const status = await client.getLoyaltyStatus();
|
|
|
3327
3354
|
await client.enrollInLoyalty(); // same status shape; no-op if already enrolled
|
|
3328
3355
|
\`\`\`
|
|
3329
3356
|
|
|
3357
|
+
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).
|
|
3358
|
+
|
|
3330
3359
|
## Rewards & redemption
|
|
3331
3360
|
|
|
3332
3361
|
\`\`\`typescript
|
|
3333
3362
|
const rewards = await client.getAvailableRewards();
|
|
3334
|
-
// [{ id, name, description, pointsCost, discountValue, minOrderAmount, maxUsesPerUser, isActive }]
|
|
3363
|
+
// [{ id, name, description, pointsCost, type, discountValue, minOrderAmount, maxUsesPerUser, minTierLevel, isActive }]
|
|
3364
|
+
// Already filtered to rewards the customer's current tier qualifies for.
|
|
3335
3365
|
|
|
3336
|
-
const { couponCode, discountValue, pointsBalance } =
|
|
3366
|
+
const { couponCode, discountType, discountValue, pointsBalance } =
|
|
3367
|
+
await client.redeemLoyaltyReward(rewardId);
|
|
3337
3368
|
await client.applyCoupon(cartId, couponCode); // applies via the normal coupon engine
|
|
3338
3369
|
\`\`\`
|
|
3339
3370
|
|
|
3340
|
-
- \`
|
|
3341
|
-
-
|
|
3371
|
+
- \`reward.type\` is \`'FIXED_DISCOUNT'\` (currency amount) or \`'PERCENT_DISCOUNT'\` (0-100 percent) \u2014 the redeem result's \`discountType\` matches.
|
|
3372
|
+
- \`redeemLoyaltyReward\` mints a one-time coupon (\`usageLimit: 1\`). Apply it with the normal \`applyCoupon\` flow.
|
|
3373
|
+
- Throws if the customer has insufficient points, or their tier is below \`reward.minTierLevel\`. If minting fails, points are refunded automatically.
|
|
3342
3374
|
- Disable a reward's redeem button when \`pointsBalance < reward.pointsCost\`.
|
|
3375
|
+
|
|
3376
|
+
## Social share (optional)
|
|
3377
|
+
|
|
3378
|
+
\`\`\`typescript
|
|
3379
|
+
await client.reportSocialShare('instagram'); // platform optional, self-reported, once per customer
|
|
3380
|
+
\`\`\`
|
|
3381
|
+
|
|
3382
|
+
## Referrals (when the store enables them)
|
|
3383
|
+
|
|
3384
|
+
\`getLoyaltyStatus()\` also returns \`referralCode\` (the member's share code, null when referrals are disabled or the customer isn't enrolled) and \`referralWelcomeCoupon\` (the still-unused welcome coupon this customer got for signing up via a referral link).
|
|
3385
|
+
|
|
3386
|
+
\`\`\`typescript
|
|
3387
|
+
// 1. Referrer: build a share link around their code.
|
|
3388
|
+
const { referralCode } = await client.getLoyaltyStatus();
|
|
3389
|
+
const shareUrl = \`https://your-store.com/?ref=\${referralCode}\`;
|
|
3390
|
+
|
|
3391
|
+
// 2. Landing page: PUBLIC lookup \u2014 no customerToken needed.
|
|
3392
|
+
const info = await client.getReferralInfo(refFromQuery);
|
|
3393
|
+
// { valid, referrerFirstName, reward: { name, type, value, minOrderAmount } | null }
|
|
3394
|
+
if (info.valid) {
|
|
3395
|
+
// "Jane sent you a gift: 10% off your first order"
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3398
|
+
// 3. Registration: pass the code \u2014 invalid codes never fail registration
|
|
3399
|
+
// (validated asynchronously server-side with fraud checks).
|
|
3400
|
+
await client.registerCustomer({ email, password, referralCode: refFromQuery });
|
|
3401
|
+
|
|
3402
|
+
// 4. Show the referee their welcome coupon after login:
|
|
3403
|
+
const { referralWelcomeCoupon } = await client.getLoyaltyStatus();
|
|
3404
|
+
if (referralWelcomeCoupon) {
|
|
3405
|
+
await client.applyCoupon(cartId, referralWelcomeCoupon.code);
|
|
3406
|
+
}
|
|
3407
|
+
\`\`\`
|
|
3408
|
+
|
|
3409
|
+
The referrer earns a points bonus after the referee's first qualifying order (held through the program's pending window, like order points). Everything server-side \u2014 no storefront earn calls.
|
|
3410
|
+
|
|
3411
|
+
## Birthday gifts (when the store enables them)
|
|
3412
|
+
|
|
3413
|
+
No dedicated calls \u2014 collect \`birthMonth\`/\`birthDay\` (1-12 / 1-31, **no year**, must be sent together) via \`updateMyProfile()\` and the platform emails a one-time gift coupon ahead of the customer's birthday.
|
|
3414
|
+
|
|
3415
|
+
\`\`\`typescript
|
|
3416
|
+
await client.updateMyProfile({ birthMonth: 4, birthDay: 17 });
|
|
3417
|
+
\`\`\`
|
|
3343
3418
|
`;
|
|
3344
3419
|
}
|
|
3345
3420
|
function getSectionByTopic(topic, connectionId, currency) {
|
|
@@ -3864,6 +3939,7 @@ interface Checkout {
|
|
|
3864
3939
|
appliedSurcharges?: Array<{ key: string; name: string; value: unknown; amount: string }> | null;
|
|
3865
3940
|
customFieldValues?: Record<string, unknown> | null;
|
|
3866
3941
|
couponCode?: string | null;
|
|
3942
|
+
notes?: string | null; // Order-level shopper note \u2014 copied onto the order at completion
|
|
3867
3943
|
lineItems: CheckoutLineItem[]; // Use THIS for order summary, NOT cart.items!
|
|
3868
3944
|
itemCount: number;
|
|
3869
3945
|
availableShippingRates?: ShippingRate[];
|
|
@@ -3932,6 +4008,7 @@ interface SetShippingAddressDto {
|
|
|
3932
4008
|
postalCode: string;
|
|
3933
4009
|
country: string;
|
|
3934
4010
|
phone?: string;
|
|
4011
|
+
notes?: string; // Order notes textarea \u2014 include one on checkout by default! Max 2000 chars, lands on the order
|
|
3935
4012
|
}
|
|
3936
4013
|
|
|
3937
4014
|
interface CreateCheckoutDto {
|
|
@@ -4875,6 +4952,18 @@ interface TaxEstimateResponse {
|
|
|
4875
4952
|
// full shipping address. The country comes from your edge runtime
|
|
4876
4953
|
// (CF-IPCountry / request.geo.country / etc.), NOT the request IP.`;
|
|
4877
4954
|
var LOYALTY_TYPES = `// ---- Loyalty & Rewards (storefront mode only) ----
|
|
4955
|
+
interface LoyaltyTierSummary {
|
|
4956
|
+
id: string;
|
|
4957
|
+
name: string;
|
|
4958
|
+
level: number; // ordering; higher = better tier
|
|
4959
|
+
pointsMultiplier: number;
|
|
4960
|
+
}
|
|
4961
|
+
|
|
4962
|
+
interface LoyaltyNextTierSummary extends LoyaltyTierSummary {
|
|
4963
|
+
qualificationType: 'SPEND' | 'POINTS';
|
|
4964
|
+
qualificationThreshold: number;
|
|
4965
|
+
}
|
|
4966
|
+
|
|
4878
4967
|
interface LoyaltyStatus {
|
|
4879
4968
|
enrolled: boolean;
|
|
4880
4969
|
pointsBalance: number; // redeemable points (pending earns excluded)
|
|
@@ -4884,6 +4973,28 @@ interface LoyaltyStatus {
|
|
|
4884
4973
|
currencyRatio: number; // points needed to redeem 1 unit of store currency
|
|
4885
4974
|
status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
|
|
4886
4975
|
} | null; // null when the store has no loyalty program
|
|
4976
|
+
tier: LoyaltyTierSummary | null; // null if untiered / no tiers configured
|
|
4977
|
+
nextTier: LoyaltyNextTierSummary | null; // null if at the top tier already
|
|
4978
|
+
progressToNextTier: number; // 0..1
|
|
4979
|
+
pointsToNextTier: number | null;
|
|
4980
|
+
referralCode?: string | null; // member's share code; null when referrals disabled / not enrolled
|
|
4981
|
+
referralWelcomeCoupon?: { // unused welcome coupon from signing up via a referral link
|
|
4982
|
+
code: string;
|
|
4983
|
+
type: string; // 'PERCENTAGE' | 'FIXED_AMOUNT'
|
|
4984
|
+
value: number;
|
|
4985
|
+
} | null;
|
|
4986
|
+
}
|
|
4987
|
+
|
|
4988
|
+
// Public referral-link lookup \u2014 NO customerToken needed (safe pre-signup)
|
|
4989
|
+
interface ReferralInfo {
|
|
4990
|
+
valid: boolean; // false for unknown/disabled codes
|
|
4991
|
+
referrerFirstName: string | null; // for "Jane sent you a gift" copy \u2014 no other PII
|
|
4992
|
+
reward: {
|
|
4993
|
+
name: string;
|
|
4994
|
+
type: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
|
|
4995
|
+
value: number;
|
|
4996
|
+
minOrderAmount: number | null;
|
|
4997
|
+
} | null;
|
|
4887
4998
|
}
|
|
4888
4999
|
|
|
4889
5000
|
interface LoyaltyReward {
|
|
@@ -4891,16 +5002,19 @@ interface LoyaltyReward {
|
|
|
4891
5002
|
name: string;
|
|
4892
5003
|
description: string | null;
|
|
4893
5004
|
pointsCost: number;
|
|
4894
|
-
|
|
5005
|
+
type: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
|
|
5006
|
+
discountValue: number; // currency amount (FIXED_DISCOUNT) or 0-100 percent (PERCENT_DISCOUNT)
|
|
4895
5007
|
minOrderAmount: number | null;
|
|
4896
5008
|
maxUsesPerUser: number;
|
|
4897
5009
|
isActive: boolean;
|
|
5010
|
+
minTierLevel: number | null; // minimum tier level required, or null for no restriction
|
|
4898
5011
|
createdAt: string;
|
|
4899
5012
|
updatedAt: string;
|
|
4900
5013
|
}
|
|
4901
5014
|
|
|
4902
5015
|
interface RedeemRewardResult {
|
|
4903
5016
|
couponCode: string; // one-time coupon to apply at checkout
|
|
5017
|
+
discountType: 'FIXED_DISCOUNT' | 'PERCENT_DISCOUNT';
|
|
4904
5018
|
discountValue: number;
|
|
4905
5019
|
pointsSpent: number;
|
|
4906
5020
|
pointsBalance: number; // remaining balance after redemption
|
|
@@ -4910,6 +5024,10 @@ interface RedeemRewardResult {
|
|
|
4910
5024
|
// client.enrollInLoyalty(): Promise<LoyaltyStatus>
|
|
4911
5025
|
// client.getAvailableRewards(): Promise<LoyaltyReward[]>
|
|
4912
5026
|
// client.redeemLoyaltyReward(rewardId: string): Promise<RedeemRewardResult>
|
|
5027
|
+
// client.reportSocialShare(platform?: string): Promise<{ awarded: boolean; points: number }>
|
|
5028
|
+
// client.getReferralInfo(code: string): Promise<ReferralInfo> // PUBLIC \u2014 no customerToken
|
|
5029
|
+
// Referral signup: client.registerCustomer({ ..., referralCode })
|
|
5030
|
+
// Birthday gift data: client.updateMyProfile({ birthMonth, birthDay }) // 1-12 / 1-31, no year, both together
|
|
4913
5031
|
`;
|
|
4914
5032
|
var TYPES_BY_DOMAIN = {
|
|
4915
5033
|
products: PRODUCTS_TYPES,
|
|
@@ -6408,6 +6526,14 @@ function formatCapabilities(caps) {
|
|
|
6408
6526
|
lines.push(
|
|
6409
6527
|
caps.features.hasLoyaltyProgram ? "\u2705 Loyalty program active (points & rewards \u2014 storefront-mode only)" : "\u274C No loyalty program"
|
|
6410
6528
|
);
|
|
6529
|
+
if (caps.features.hasLoyaltyProgram) {
|
|
6530
|
+
lines.push(
|
|
6531
|
+
caps.features.hasReferralProgram ? "\u2705 Referral program enabled (share codes + welcome reward \u2014 storefront-mode only)" : "\u274C Referral program not enabled"
|
|
6532
|
+
);
|
|
6533
|
+
lines.push(
|
|
6534
|
+
caps.features.hasBirthdayRewards ? "\u2705 Birthday gifts enabled (set birthMonth/birthDay via updateMyProfile)" : "\u274C Birthday gifts not enabled"
|
|
6535
|
+
);
|
|
6536
|
+
}
|
|
6411
6537
|
lines.push("");
|
|
6412
6538
|
lines.push("## Connection Settings");
|
|
6413
6539
|
lines.push(
|
|
@@ -6455,7 +6581,7 @@ function formatCapabilities(caps) {
|
|
|
6455
6581
|
}
|
|
6456
6582
|
if (caps.features.hasLoyaltyProgram) {
|
|
6457
6583
|
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(),
|
|
6584
|
+
"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
6585
|
);
|
|
6460
6586
|
}
|
|
6461
6587
|
if (caps.features.hasCheckoutCustomFields) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainerce/mcp-server",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.4",
|
|
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": {
|