@brainerce/mcp-server 3.12.0 → 3.12.2
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 +198 -12
- package/dist/bin/stdio.js +198 -12
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +198 -12
- package/dist/index.mjs +198 -12
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -712,17 +712,19 @@ function getPaymentProvidersSection() {
|
|
|
712
712
|
return `## Payment Provider Detection (DO THIS FIRST on checkout page!)
|
|
713
713
|
|
|
714
714
|
\`\`\`typescript
|
|
715
|
-
const { hasPayments, providers } = await client.getPaymentProviders();
|
|
715
|
+
const { hasPayments, providers, defaultProvider } = await client.getPaymentProviders();
|
|
716
716
|
if (!hasPayments) {
|
|
717
717
|
// Show error: "Payment is not configured for this store"
|
|
718
718
|
return;
|
|
719
719
|
}
|
|
720
|
-
|
|
721
|
-
const
|
|
722
|
-
const
|
|
720
|
+
// Primary vs additive (Shopify-parity): render wallets as express buttons ABOVE the card form.
|
|
721
|
+
const expressMethods = providers.filter(p => p.isAdditive); // e.g. PayPal (WALLET)
|
|
722
|
+
const primary = defaultProvider && !defaultProvider.isAdditive ? defaultProvider : undefined;
|
|
723
723
|
\`\`\`
|
|
724
724
|
|
|
725
|
-
Each provider has: \`id\`, \`provider\` (flexible string \u2014 \`'stripe'\`, \`'grow'\`, \`'paypal'\`, \`'cardcom'\`, \`'morning'\`, \`'takbull'\`, \`'sandbox'\`, and future providers), \`name\`, \`publicKey\`, \`stripeAccountId\` (Stripe only), \`supportedMethods\`, \`testMode\`, \`isDefault
|
|
725
|
+
Each provider has: \`id\`, \`provider\` (flexible string \u2014 \`'stripe'\`, \`'grow'\`, \`'paypal'\`, \`'cardcom'\`, \`'morning'\`, \`'takbull'\`, \`'sandbox'\`, and future providers), \`name\`, \`publicKey\`, \`stripeAccountId\` (Stripe only), \`supportedMethods\`, \`testMode\`, \`isDefault\`, plus the taxonomy fields \`methodType\` (\`'CREDIT_CARD'\` = the single primary card processor that settles the order; \`'WALLET'\`/other = additive), \`isAdditive\`, and \`presentation\` (\`'card_form'\` | \`'express_button'\` | \u2026).
|
|
726
|
+
|
|
727
|
+
**Primary vs. additive:** there is one primary card processor (the \`defaultProvider\`, \`isAdditive: false\`) plus any additive methods (\`isAdditive: true\`, e.g. PayPal). Render additive methods as accelerated-checkout **express buttons above** the card form \u2014 they sit alongside the primary, never replace it. Create the intent with the tapped provider's \`id\`. (Exception: a wallet-only store has no card processor, so its wallet becomes the \`defaultProvider\` and stands alone.)
|
|
726
728
|
|
|
727
729
|
The payment intent returned from \`createPaymentIntent()\` includes a \`clientSdk\` object whose \`renderType\` tells you exactly how to render \u2014 **branch on THAT, not on the provider name**:
|
|
728
730
|
|
|
@@ -1110,11 +1112,22 @@ client-side overlay needed. Swatch colors are language-agnostic.
|
|
|
1110
1112
|
function ProductDescription({ product }: { product: Product }) {
|
|
1111
1113
|
const content = getDescriptionContent(product);
|
|
1112
1114
|
if (!content) return null;
|
|
1113
|
-
|
|
1115
|
+
// Descriptions are merchant HTML and may contain <video> + host-locked
|
|
1116
|
+
// YouTube/Vimeo <iframe> embeds. NEVER render unsanitized \u2014 sanitize and
|
|
1117
|
+
// allowlist video/source + iframe (restricted to youtube/vimeo hosts).
|
|
1118
|
+
if ('html' in content) {
|
|
1119
|
+
return <div dangerouslySetInnerHTML={{ __html: sanitizeProductHtml(content.html) }} />;
|
|
1120
|
+
}
|
|
1114
1121
|
return <p>{content.text}</p>;
|
|
1115
1122
|
}
|
|
1116
1123
|
\`\`\`
|
|
1117
1124
|
|
|
1125
|
+
**Sanitize descriptions.** \`sanitizeProductHtml\` is the host-locked sanitizer the
|
|
1126
|
+
\`create-brainerce-store\` scaffold ships at \`src/lib/sanitize-html.ts\`. If you roll
|
|
1127
|
+
your own, allow \`video\`/\`source\` and \`iframe\` **restricted** to \`www.youtube.com\`,
|
|
1128
|
+
\`www.youtube-nocookie.com\`, \`player.vimeo.com\` (never arbitrary iframes), and add
|
|
1129
|
+
those hosts to your CSP \`frame-src\` or embeds render blank.
|
|
1130
|
+
|
|
1118
1131
|
### Metafields (Custom Product Fields) \u2014 display on product detail!
|
|
1119
1132
|
|
|
1120
1133
|
**IMPORTANT: Render metafield values based on \`mf.type\`!** Don't just display \`mf.value\` as text for all types.
|
|
@@ -1197,7 +1210,28 @@ const { url } = await client.uploadCustomizationFile(file);
|
|
|
1197
1210
|
// Then use the URL in metadata: metadata: { logo: url }
|
|
1198
1211
|
\`\`\`
|
|
1199
1212
|
|
|
1200
|
-
**Customization field properties:** \`key\`, \`name\` (display label), \`type\`, \`required\`, \`minLength\`, \`maxLength\`, \`minValue\`, \`maxValue\`, \`enumValues
|
|
1213
|
+
**Customization field properties:** \`key\`, \`name\` (display label), \`type\`, \`required\`, \`minLength\`, \`maxLength\`, \`minValue\`, \`maxValue\`, \`enumValues\` (array of \`{label, value, swatchColor?, swatchImageUrl?}\`), \`defaultValue\`, \`position\`
|
|
1214
|
+
|
|
1215
|
+
**SELECT / MULTI_SELECT \u2014 use \`option.value\` to submit, \`option.label\` to display:**
|
|
1216
|
+
|
|
1217
|
+
\`\`\`typescript
|
|
1218
|
+
for (const option of field.enumValues ?? []) {
|
|
1219
|
+
// option.value \u2192 what to submit in metadata
|
|
1220
|
+
// option.label \u2192 what to show the customer
|
|
1221
|
+
// option.swatchColor \u2192 optional hex color for color swatches
|
|
1222
|
+
}
|
|
1223
|
+
\`\`\`
|
|
1224
|
+
|
|
1225
|
+
**Display customizations in cart / checkout \u2014 no extra API call needed:**
|
|
1226
|
+
|
|
1227
|
+
CartItem and CheckoutLineItem both include a \`customizations\` object alongside \`metadata\`. Use \`customizations\` for display \u2014 it contains resolved labels, not raw keys.
|
|
1228
|
+
|
|
1229
|
+
\`\`\`typescript
|
|
1230
|
+
// Works for CartItem, CheckoutLineItem, and OrderItem \u2014 same shape
|
|
1231
|
+
const lines = Object.values(item.customizations ?? {})
|
|
1232
|
+
.map(c => \`\${c.label}: \${Array.isArray(c.value) ? c.value.join(', ') : c.value}\`);
|
|
1233
|
+
// e.g. ["Frame color: Gold", "Add-ons: Gift wrap"]
|
|
1234
|
+
\`\`\`
|
|
1201
1235
|
|
|
1202
1236
|
### Downloadable / Digital Products
|
|
1203
1237
|
|
|
@@ -1739,7 +1773,7 @@ The merchant can hide a group entirely for one variant by setting \`maxOverride:
|
|
|
1739
1773
|
|
|
1740
1774
|
### Restaurant features (advanced)
|
|
1741
1775
|
|
|
1742
|
-
|
|
1776
|
+
Scheduled availability windows, nested combos (depth \u2264 3 via \`nestedByModifierId\`), and downsell modifiers (negative \`priceDelta\`) are all built on the same data model. See INTEGRATION-OPTIONAL.md "Restaurant / build-your-own products" for those flows.`;
|
|
1743
1777
|
}
|
|
1744
1778
|
function getProductReviewsSection() {
|
|
1745
1779
|
return `## Product Reviews (\u2605 ratings + JSON-LD for SEO)
|
|
@@ -3229,6 +3263,85 @@ by device) and can also be asked of the AI assistant ("how many visits did I get
|
|
|
3229
3263
|
this month and from where?").
|
|
3230
3264
|
`;
|
|
3231
3265
|
}
|
|
3266
|
+
function getShippingAppSection() {
|
|
3267
|
+
return `## App Store Shipping (Shippo)
|
|
3268
|
+
|
|
3269
|
+
Merchants install Shippo from the Brainerce App Store. After connecting their own Shippo account
|
|
3270
|
+
(OAuth), live carrier rates appear automatically at checkout alongside any manually configured
|
|
3271
|
+
zone rates. **Billing goes directly to the merchant's Shippo account \u2014 Brainerce never charges.**
|
|
3272
|
+
|
|
3273
|
+
### Checkout \u2014 live carrier rates
|
|
3274
|
+
|
|
3275
|
+
No SDK changes needed. Once Shippo is installed and configured, the existing
|
|
3276
|
+
\`getShippingRates()\` call returns both manual zone rates and live Shippo quotes:
|
|
3277
|
+
|
|
3278
|
+
\`\`\`typescript
|
|
3279
|
+
const { rates } = await client.setShippingAddress(checkoutId, { ... });
|
|
3280
|
+
// rates may include:
|
|
3281
|
+
// { id: 'shippo:rate_8f123abc', name: 'USPS Priority Mail', price: '8.50', currency: 'USD', source: 'carrier' }
|
|
3282
|
+
\`\`\`
|
|
3283
|
+
|
|
3284
|
+
Rates prefixed \`shippo:\` are live Shippo quotes. Pass the full \`id\` as \`shippingRateId\`
|
|
3285
|
+
when calling \`selectShippingMethod()\`.
|
|
3286
|
+
|
|
3287
|
+
### Admin \u2014 purchase a shipping label
|
|
3288
|
+
|
|
3289
|
+
After the order is placed, the merchant purchases a label by passing the Shippo rate object_id:
|
|
3290
|
+
|
|
3291
|
+
\`\`\`typescript
|
|
3292
|
+
const label = await admin.createShippingLabel(orderId, {
|
|
3293
|
+
shippoRateObjectId: 'rate_8f123456789abcdef',
|
|
3294
|
+
});
|
|
3295
|
+
console.log(label.labelUrl); // PDF ready to print
|
|
3296
|
+
console.log(label.trackingNumber); // auto-populated on the order
|
|
3297
|
+
\`\`\`
|
|
3298
|
+
|
|
3299
|
+
The \`trackingNumber\` is stored on the \`Order\` and returned in \`getMyOrders()\`
|
|
3300
|
+
so customers can track their shipment automatically.
|
|
3301
|
+
|
|
3302
|
+
**SDK mode:** \`createShippingLabel()\` requires \`apiKey\` (admin mode only).`;
|
|
3303
|
+
}
|
|
3304
|
+
function getLoyaltySection() {
|
|
3305
|
+
return `# Loyalty & Rewards
|
|
3306
|
+
|
|
3307
|
+
Logged-in customers earn points on paid orders and redeem them for a one-time discount coupon at checkout.
|
|
3308
|
+
|
|
3309
|
+
> **Storefront mode only.** These methods work only with \`new BrainerceClient({ storeId })\` + a logged-in \`customerToken\`. There is **no vibe-coded route** \u2014 in \`salesChannelId: 'vc_*'\` mode they throw. Skip loyalty if you connect vibe-coded.
|
|
3310
|
+
|
|
3311
|
+
Points are earned automatically by the platform when an order is paid \u2014 there is no earn call from the storefront. Your job is to **show** balance/rewards and to **redeem**.
|
|
3312
|
+
|
|
3313
|
+
## Status
|
|
3314
|
+
|
|
3315
|
+
\`\`\`typescript
|
|
3316
|
+
// requires client.setCustomerToken(auth.token)
|
|
3317
|
+
const status = await client.getLoyaltyStatus();
|
|
3318
|
+
// { enrolled, pointsBalance, lifetimeEarned, program: { pointsName, currencyRatio, status } | null }
|
|
3319
|
+
\`\`\`
|
|
3320
|
+
|
|
3321
|
+
- \`program === null\` \u2192 the store has no loyalty program; hide the loyalty UI.
|
|
3322
|
+
- \`program.status !== 'ACTIVE'\` \u2192 program paused/draft; hide the loyalty UI.
|
|
3323
|
+
|
|
3324
|
+
## Enroll (only if auto-enroll is off)
|
|
3325
|
+
|
|
3326
|
+
\`\`\`typescript
|
|
3327
|
+
await client.enrollInLoyalty(); // same status shape; no-op if already enrolled
|
|
3328
|
+
\`\`\`
|
|
3329
|
+
|
|
3330
|
+
## Rewards & redemption
|
|
3331
|
+
|
|
3332
|
+
\`\`\`typescript
|
|
3333
|
+
const rewards = await client.getAvailableRewards();
|
|
3334
|
+
// [{ id, name, description, pointsCost, discountValue, minOrderAmount, maxUsesPerUser, isActive }]
|
|
3335
|
+
|
|
3336
|
+
const { couponCode, discountValue, pointsBalance } = await client.redeemLoyaltyReward(rewardId);
|
|
3337
|
+
await client.applyCoupon(cartId, couponCode); // applies via the normal coupon engine
|
|
3338
|
+
\`\`\`
|
|
3339
|
+
|
|
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.
|
|
3342
|
+
- Disable a reward's redeem button when \`pointsBalance < reward.pointsCost\`.
|
|
3343
|
+
`;
|
|
3344
|
+
}
|
|
3232
3345
|
function getSectionByTopic(topic, connectionId, currency) {
|
|
3233
3346
|
const cid = connectionId || "vc_YOUR_CONNECTION_ID";
|
|
3234
3347
|
const cur = currency || "USD";
|
|
@@ -3255,6 +3368,8 @@ function getSectionByTopic(topic, connectionId, currency) {
|
|
|
3255
3368
|
return getInventorySection();
|
|
3256
3369
|
case "discounts":
|
|
3257
3370
|
return getDiscountsSection();
|
|
3371
|
+
case "loyalty":
|
|
3372
|
+
return getLoyaltySection();
|
|
3258
3373
|
case "recommendations":
|
|
3259
3374
|
return getRecommendationsSection();
|
|
3260
3375
|
case "reviews":
|
|
@@ -3288,6 +3403,9 @@ function getSectionByTopic(topic, connectionId, currency) {
|
|
|
3288
3403
|
case "analytics":
|
|
3289
3404
|
case "traffic-analytics":
|
|
3290
3405
|
return getStorefrontAnalyticsSection(cid);
|
|
3406
|
+
case "shipping-app":
|
|
3407
|
+
case "shippo":
|
|
3408
|
+
return getShippingAppSection();
|
|
3291
3409
|
case "all":
|
|
3292
3410
|
return [
|
|
3293
3411
|
"# Brainerce SDK \u2014 full topic dump",
|
|
@@ -3418,6 +3536,7 @@ var GET_SDK_DOCS_SCHEMA = {
|
|
|
3418
3536
|
"order-confirmation",
|
|
3419
3537
|
"inventory",
|
|
3420
3538
|
"discounts",
|
|
3539
|
+
"loyalty",
|
|
3421
3540
|
"recommendations",
|
|
3422
3541
|
"reviews",
|
|
3423
3542
|
"product-customization-fields",
|
|
@@ -3570,11 +3689,18 @@ interface ProductCustomizationField {
|
|
|
3570
3689
|
maxLength?: number | null;
|
|
3571
3690
|
minValue?: number | null; // NUMBER bounds
|
|
3572
3691
|
maxValue?: number | null;
|
|
3573
|
-
enumValues?:
|
|
3692
|
+
enumValues?: CustomizationFieldOption[]; // REQUIRED for SELECT / MULTI_SELECT
|
|
3574
3693
|
defaultValue?: string | null;
|
|
3575
3694
|
position: number; // Render order
|
|
3576
3695
|
}
|
|
3577
3696
|
|
|
3697
|
+
interface CustomizationFieldOption {
|
|
3698
|
+
label: string; // Display label (e.g., "Rose Gold")
|
|
3699
|
+
value: string; // Value stored in CartItem.metadata
|
|
3700
|
+
swatchColor?: string | null; // Optional hex color (e.g., "#B76E79")
|
|
3701
|
+
swatchImageUrl?: string | null; // Optional swatch image URL
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3578
3704
|
interface ProductQueryParams {
|
|
3579
3705
|
page?: number;
|
|
3580
3706
|
limit?: number;
|
|
@@ -3668,6 +3794,7 @@ interface CartItem {
|
|
|
3668
3794
|
image?: ProductImage | string | null;
|
|
3669
3795
|
} | null;
|
|
3670
3796
|
metadata?: Record<string, unknown> | null; // Buyer-submitted customization values, keyed by ProductCustomizationField.key
|
|
3797
|
+
customizations?: Record<string, { label: string; value: string | string[]; type: string }>; // Resolved labels \u2014 use this to display "Color: Silver" without extra getProduct() call
|
|
3671
3798
|
createdAt: string;
|
|
3672
3799
|
updatedAt: string;
|
|
3673
3800
|
}
|
|
@@ -3767,6 +3894,7 @@ interface CheckoutLineItem {
|
|
|
3767
3894
|
product: { id: string; name: string; sku: string; images?: ProductImage[]; };
|
|
3768
3895
|
variant?: { id: string; name?: string | null; sku?: string | null; image?: ProductImage | string | null; } | null;
|
|
3769
3896
|
metadata?: Record<string, unknown> | null; // Copied from CartItem.metadata \u2014 buyer customization values
|
|
3897
|
+
customizations?: Record<string, { label: string; value: string | string[]; type: string }>; // Resolved labels \u2014 same shape as OrderItem.customizations
|
|
3770
3898
|
}
|
|
3771
3899
|
|
|
3772
3900
|
interface CheckoutAddress {
|
|
@@ -4003,7 +4131,10 @@ interface PaymentProviderConfig {
|
|
|
4003
4131
|
stripeAccountId?: string; // Stripe Connect only
|
|
4004
4132
|
supportedMethods: string[];
|
|
4005
4133
|
testMode: boolean;
|
|
4006
|
-
isDefault: boolean;
|
|
4134
|
+
isDefault: boolean; // only a primary (CREDIT_CARD) is ever the default
|
|
4135
|
+
methodType: 'CREDIT_CARD' | 'WALLET' | 'OFFSITE' | 'LOCAL' | 'REDEEMABLE';
|
|
4136
|
+
presentation: 'card_form' | 'express_button' | 'redirect' | 'local_option' | 'redeemable_field';
|
|
4137
|
+
isAdditive: boolean; // wallet/alt method shown ALONGSIDE the primary (e.g. PayPal)
|
|
4007
4138
|
}
|
|
4008
4139
|
type PaymentProvider = PaymentProviderConfig;
|
|
4009
4140
|
|
|
@@ -4743,6 +4874,43 @@ interface TaxEstimateResponse {
|
|
|
4743
4874
|
// Non-binding by design: the authoritative tax runs at checkout against the
|
|
4744
4875
|
// full shipping address. The country comes from your edge runtime
|
|
4745
4876
|
// (CF-IPCountry / request.geo.country / etc.), NOT the request IP.`;
|
|
4877
|
+
var LOYALTY_TYPES = `// ---- Loyalty & Rewards (storefront mode only) ----
|
|
4878
|
+
interface LoyaltyStatus {
|
|
4879
|
+
enrolled: boolean;
|
|
4880
|
+
pointsBalance: number; // redeemable points (pending earns excluded)
|
|
4881
|
+
lifetimeEarned: number;
|
|
4882
|
+
program: {
|
|
4883
|
+
pointsName: string; // e.g. "points", "coins"
|
|
4884
|
+
currencyRatio: number; // points needed to redeem 1 unit of store currency
|
|
4885
|
+
status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
|
|
4886
|
+
} | null; // null when the store has no loyalty program
|
|
4887
|
+
}
|
|
4888
|
+
|
|
4889
|
+
interface LoyaltyReward {
|
|
4890
|
+
id: string;
|
|
4891
|
+
name: string;
|
|
4892
|
+
description: string | null;
|
|
4893
|
+
pointsCost: number;
|
|
4894
|
+
discountValue: number; // fixed amount off, store currency
|
|
4895
|
+
minOrderAmount: number | null;
|
|
4896
|
+
maxUsesPerUser: number;
|
|
4897
|
+
isActive: boolean;
|
|
4898
|
+
createdAt: string;
|
|
4899
|
+
updatedAt: string;
|
|
4900
|
+
}
|
|
4901
|
+
|
|
4902
|
+
interface RedeemRewardResult {
|
|
4903
|
+
couponCode: string; // one-time coupon to apply at checkout
|
|
4904
|
+
discountValue: number;
|
|
4905
|
+
pointsSpent: number;
|
|
4906
|
+
pointsBalance: number; // remaining balance after redemption
|
|
4907
|
+
}
|
|
4908
|
+
|
|
4909
|
+
// client.getLoyaltyStatus(): Promise<LoyaltyStatus>
|
|
4910
|
+
// client.enrollInLoyalty(): Promise<LoyaltyStatus>
|
|
4911
|
+
// client.getAvailableRewards(): Promise<LoyaltyReward[]>
|
|
4912
|
+
// client.redeemLoyaltyReward(rewardId: string): Promise<RedeemRewardResult>
|
|
4913
|
+
`;
|
|
4746
4914
|
var TYPES_BY_DOMAIN = {
|
|
4747
4915
|
products: PRODUCTS_TYPES,
|
|
4748
4916
|
cart: CART_TYPES,
|
|
@@ -4755,7 +4923,8 @@ var TYPES_BY_DOMAIN = {
|
|
|
4755
4923
|
reviews: REVIEWS_TYPES,
|
|
4756
4924
|
"modifier-groups": MODIFIER_GROUPS_TYPES,
|
|
4757
4925
|
content: CONTENT_TYPES,
|
|
4758
|
-
regions: REGIONS_TYPES
|
|
4926
|
+
regions: REGIONS_TYPES,
|
|
4927
|
+
loyalty: LOYALTY_TYPES
|
|
4759
4928
|
};
|
|
4760
4929
|
function getTypesByDomain(domain) {
|
|
4761
4930
|
if (domain === "all") {
|
|
@@ -4789,6 +4958,7 @@ var GET_TYPE_DEFINITIONS_SCHEMA = {
|
|
|
4789
4958
|
"modifier-groups",
|
|
4790
4959
|
"content",
|
|
4791
4960
|
"regions",
|
|
4961
|
+
"loyalty",
|
|
4792
4962
|
"all"
|
|
4793
4963
|
]).describe(
|
|
4794
4964
|
'The domain of types to retrieve. Use "helpers" for helper function signatures and common types like StoreInfo, PaginatedResponse. Use "content" for FAQ / Footer / Header / Announcement / RichText / Page. Use "regions" for Region / TaxClass admin types.'
|
|
@@ -5051,7 +5221,15 @@ const checkout = await client.getCheckout(checkoutId);
|
|
|
5051
5221
|
import { client } from './brainerce';
|
|
5052
5222
|
|
|
5053
5223
|
const { providers, hasPayments, defaultProvider } = await client.getPaymentProviders();
|
|
5054
|
-
// each provider: { id, provider, name, publicKey, supportedMethods, testMode,
|
|
5224
|
+
// each provider: { id, provider, name, publicKey, supportedMethods, testMode,
|
|
5225
|
+
// isDefault, methodType, presentation, isAdditive, clientSdk? }
|
|
5226
|
+
//
|
|
5227
|
+
// methodType splits providers into ONE primary card processor (CREDIT_CARD, the
|
|
5228
|
+
// defaultProvider that settles the order) and additive methods (isAdditive:true,
|
|
5229
|
+
// e.g. PayPal as a WALLET). Render additive methods as express buttons ABOVE the
|
|
5230
|
+
// card form \u2014 they sit alongside the primary, never replace it. Call
|
|
5231
|
+
// createPaymentIntent({ providerId }) with the tapped provider's id. (Wallet-only
|
|
5232
|
+
// store: with no card processor, the wallet becomes defaultProvider and stands alone.)
|
|
5055
5233
|
//
|
|
5056
5234
|
// After createPaymentIntent, the response carries a clientSdk.renderType that
|
|
5057
5235
|
// tells your UI how to render the payment step. The 5 possible values:
|
|
@@ -6227,6 +6405,9 @@ function formatCapabilities(caps) {
|
|
|
6227
6405
|
lines.push(
|
|
6228
6406
|
caps.features.hasCheckoutCustomFields ? "\u2705 Checkout custom fields configured (surcharges may apply)" : "\u274C No checkout custom fields"
|
|
6229
6407
|
);
|
|
6408
|
+
lines.push(
|
|
6409
|
+
caps.features.hasLoyaltyProgram ? "\u2705 Loyalty program active (points & rewards \u2014 storefront-mode only)" : "\u274C No loyalty program"
|
|
6410
|
+
);
|
|
6230
6411
|
lines.push("");
|
|
6231
6412
|
lines.push("## Connection Settings");
|
|
6232
6413
|
lines.push(
|
|
@@ -6272,6 +6453,11 @@ function formatCapabilities(caps) {
|
|
|
6272
6453
|
if (caps.features.hasCoupons) {
|
|
6273
6454
|
suggestions.push('Add a coupon input to the cart. Use get-code-example("coupon-input").');
|
|
6274
6455
|
}
|
|
6456
|
+
if (caps.features.hasLoyaltyProgram) {
|
|
6457
|
+
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."
|
|
6459
|
+
);
|
|
6460
|
+
}
|
|
6275
6461
|
if (caps.features.hasCheckoutCustomFields) {
|
|
6276
6462
|
suggestions.push(
|
|
6277
6463
|
`Checkout custom fields are configured. Build a step between shipping/pickup and payment using getCheckoutCustomFields() + setCheckoutCustomFields(). Render checkout.appliedSurcharges in the order summary so customers see what they're paying for. Use get-code-example("checkout-custom-fields").`
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainerce/mcp-server",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.2",
|
|
4
|
+
"packageManager": "pnpm@9.0.0",
|
|
4
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.",
|
|
5
6
|
"bin": {
|
|
6
7
|
"brainerce-mcp": "dist/bin/stdio.js"
|