@brainerce/mcp-server 3.11.1 → 3.12.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.
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
- const stripeProvider = providers.find(p => p.provider === 'stripe');
721
- const growProvider = providers.find(p => p.provider === 'grow');
722
- const paypalProvider = providers.find(p => p.provider === 'paypal');
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
- if ('html' in content) return <div dangerouslySetInnerHTML={{ __html: content.html }} />;
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\`, \`defaultValue\`, \`position\`
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
 
@@ -2528,8 +2562,9 @@ await admin.createTaxRate({ name: 'VAT (Food)', rate: 0, country: 'GB', taxClass
2528
2562
  await admin.mergeTaxClasses(food.id, standardClassId);
2529
2563
  \`\`\`
2530
2564
 
2531
- Storefront (public, no apiKey \u2014 \`storeId\` mode): \`getStoreTaxClasses()\` lists
2532
- the store's classes (storefront-safe fields only) for a transparency badge.
2565
+ Storefront (public, no apiKey \u2014 \`storeId\` mode OR vibe-coded mode \`vc_*\`, gated
2566
+ on the \`products:read\` scope every connection already has): \`getStoreTaxClasses()\`
2567
+ lists the store's classes (storefront-safe fields only) for a transparency badge.
2533
2568
 
2534
2569
  For a buyer-facing tax preview on PDP / PLP / cart, \`estimateTax({ country,
2535
2570
  subtotal })\` returns the tax portion at the Standard rate for the buyer's
@@ -2551,8 +2586,10 @@ A region binds countries \u2192 currency + tax-display mode + enabled payment
2551
2586
  providers. Manage them via the SDK (scopes \`regions:read\` / \`regions:write\`).
2552
2587
  \`detectRegion\` is a pure client-side helper to map a buyer's country to a
2553
2588
  region; pass the resolved \`regionId\` to \`createCheckout\` to associate the
2554
- checkout with a region (recorded for reporting + provider scoping; currency
2555
- follows the cart until FX price conversion lands).
2589
+ checkout with a region (recorded for reporting + provider scoping). FX-at-checkout:
2590
+ presentment-enabled regions (Stripe today) charge in the region currency and the
2591
+ checkout response carries a \`presentment\` overlay with the charged amounts;
2592
+ otherwise the checkout is charged in the store base currency.
2556
2593
 
2557
2594
  \`\`\`typescript
2558
2595
  const eu = await admin.createRegion({
@@ -2565,9 +2602,12 @@ const { data: regions } = await admin.getRegions();
2565
2602
  const region = admin.detectRegion('DE', regions); // \u2192 eu, else default, else null
2566
2603
  \`\`\`
2567
2604
 
2568
- Storefront (public, no apiKey \u2014 \`storeId\` mode): \`getStoreRegions()\` lists
2569
- active regions, \`getStoreRegion(id)\` returns one region + its payment providers.
2570
- Pair with \`detectRegion\` to pick the buyer's region for currency display.
2605
+ Storefront (public, no apiKey \u2014 \`storeId\` mode OR vibe-coded mode \`vc_*\`, gated
2606
+ on the \`products:read\` scope every connection already has): \`getStoreRegions()\`
2607
+ lists active regions, \`getStoreRegion(id)\` returns one region + its payment
2608
+ providers. \`getAutoRegion(country)\` and \`estimateTax({ country, subtotal })\` work
2609
+ in both modes too. Pair with \`detectRegion\` to pick the buyer's region for
2610
+ currency display.
2571
2611
 
2572
2612
  \`\`\`typescript
2573
2613
  const store = new BrainerceClient({ storeId: 'store_123' });
@@ -3191,6 +3231,76 @@ Rules:
3191
3231
  count updates when the bot adds items.
3192
3232
  `;
3193
3233
  }
3234
+ function getStorefrontAnalyticsSection(connectionId) {
3235
+ return `## Storefront Traffic Analytics (visits, countries, sources)
3236
+
3237
+ Brainerce can track cookieless storefront traffic \u2014 how many people visit the
3238
+ store, from which countries, and from which traffic sources \u2014 and surface it in
3239
+ the merchant dashboard alongside sales (so the merchant gets a REAL conversion
3240
+ rate: visits \u2192 orders).
3241
+
3242
+ Add ONE line to the storefront's root layout (\`<head>\` or end of \`<body>\`):
3243
+
3244
+ \`\`\`html
3245
+ <script defer src="https://api.brainerce.com/t.js" data-channel="${connectionId}"></script>
3246
+ \`\`\`
3247
+
3248
+ That's it \u2014 the pixel auto-sends a pageview beacon on load and on SPA route
3249
+ changes. Stores scaffolded with \`create-brainerce-store\` already include it.
3250
+
3251
+ Privacy: the pixel is cookieless and stores NO personal data \u2014 no cookie, no
3252
+ cross-site/cross-day tracking, and the visitor IP is resolved to a country
3253
+ server-side then discarded. No cookie-consent banner is required for it under
3254
+ GDPR/ePrivacy.
3255
+
3256
+ CSP: if the storefront sets a Content-Security-Policy, allow the script + beacon:
3257
+ - \`script-src\` \u2026 \`https://api.brainerce.com\`
3258
+ - \`connect-src\` \u2026 \`https://api.brainerce.com\`
3259
+
3260
+ The merchant can toggle tracking per sales channel in the dashboard. The data
3261
+ shows up under Dashboard \u2192 Analytics (visits over time, by country, by source,
3262
+ by device) and can also be asked of the AI assistant ("how many visits did I get
3263
+ this month and from where?").
3264
+ `;
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
+ }
3194
3304
  function getSectionByTopic(topic, connectionId, currency) {
3195
3305
  const cid = connectionId || "vc_YOUR_CONNECTION_ID";
3196
3306
  const cur = currency || "USD";
@@ -3247,6 +3357,12 @@ function getSectionByTopic(topic, connectionId, currency) {
3247
3357
  return getBlogSection();
3248
3358
  case "storefront-bot":
3249
3359
  return getStorefrontBotSection(cid);
3360
+ case "analytics":
3361
+ case "traffic-analytics":
3362
+ return getStorefrontAnalyticsSection(cid);
3363
+ case "shipping-app":
3364
+ case "shippo":
3365
+ return getShippingAppSection();
3250
3366
  case "all":
3251
3367
  return [
3252
3368
  "# Brainerce SDK \u2014 full topic dump",
@@ -3315,6 +3431,10 @@ function getSectionByTopic(topic, connectionId, currency) {
3315
3431
  "",
3316
3432
  "---",
3317
3433
  "",
3434
+ getStorefrontAnalyticsSection(cid),
3435
+ "",
3436
+ "---",
3437
+ "",
3318
3438
  getProductCustomizationFieldsSection(),
3319
3439
  "",
3320
3440
  "---",
@@ -3384,6 +3504,7 @@ var GET_SDK_DOCS_SCHEMA = {
3384
3504
  "inquiries",
3385
3505
  "content",
3386
3506
  "storefront-bot",
3507
+ "analytics",
3387
3508
  "all"
3388
3509
  ]).describe("The SDK documentation topic to retrieve"),
3389
3510
  salesChannelId: z.string().optional().describe("Sales channel ID (starts with vc_). Used to personalize setup code."),
@@ -3421,7 +3542,7 @@ interface Product {
3421
3542
  priceMin?: string | null; // Lowest variant price (VARIABLE products) \u2014 same as basePrice for VARIABLE, kept for back-compat and JSON-LD range display.
3422
3543
  priceMax?: string | null; // Highest variant price (VARIABLE products). Use with priceMin for "\u20AA49 \u2013 \u20AA199" range.
3423
3544
  priceVaries?: boolean; // true when variant prices differ \u2014 show "\u20AA49 \u2013 \u20AA199" range.
3424
- // FX DISPLAY overlay (PRD \xA723). Set only when getProducts({ regionId }) was called AND region.currency !== store.currency. basePrice/salePrice above stay in store currency \u2014 these are additive, display-only. The buyer is still charged in store currency at checkout; payment provider handles customer-side FX.
3545
+ // FX DISPLAY overlay (PRD \xA723). Set only when getProducts({ regionId }) was called AND region.currency !== store.currency. basePrice/salePrice above stay in store currency \u2014 these are additive. For presentment-enabled regions (Stripe) the displayPrice uses the same buffered rate the checkout charges (browsed == checkout); for display-only regions it is mid-market and the buyer is charged in store currency at checkout (payment provider handles customer-side FX).
3425
3546
  displayPrice?: string; // basePrice \xD7 daily FX rate, in displayCurrency.
3426
3547
  displaySalePrice?: string; // salePrice \xD7 rate (if salePrice present).
3427
3548
  displayPriceMin?: string; // priceMin \xD7 rate (VARIABLE products).
@@ -3524,11 +3645,18 @@ interface ProductCustomizationField {
3524
3645
  maxLength?: number | null;
3525
3646
  minValue?: number | null; // NUMBER bounds
3526
3647
  maxValue?: number | null;
3527
- enumValues?: string[]; // REQUIRED for SELECT / MULTI_SELECT
3648
+ enumValues?: CustomizationFieldOption[]; // REQUIRED for SELECT / MULTI_SELECT
3528
3649
  defaultValue?: string | null;
3529
3650
  position: number; // Render order
3530
3651
  }
3531
3652
 
3653
+ interface CustomizationFieldOption {
3654
+ label: string; // Display label (e.g., "Rose Gold")
3655
+ value: string; // Value stored in CartItem.metadata
3656
+ swatchColor?: string | null; // Optional hex color (e.g., "#B76E79")
3657
+ swatchImageUrl?: string | null; // Optional swatch image URL
3658
+ }
3659
+
3532
3660
  interface ProductQueryParams {
3533
3661
  page?: number;
3534
3662
  limit?: number;
@@ -3622,6 +3750,7 @@ interface CartItem {
3622
3750
  image?: ProductImage | string | null;
3623
3751
  } | null;
3624
3752
  metadata?: Record<string, unknown> | null; // Buyer-submitted customization values, keyed by ProductCustomizationField.key
3753
+ customizations?: Record<string, { label: string; value: string | string[]; type: string }>; // Resolved labels \u2014 use this to display "Color: Silver" without extra getProduct() call
3625
3754
  createdAt: string;
3626
3755
  updatedAt: string;
3627
3756
  }
@@ -3675,7 +3804,7 @@ interface Checkout {
3675
3804
  status: CheckoutStatus;
3676
3805
  email?: string | null;
3677
3806
  customerId?: string | null;
3678
- regionId?: string | null; // multi-region: recorded for reporting + provider scoping (currency follows the cart until FX lands)
3807
+ regionId?: string | null; // multi-region: recorded for reporting + provider scoping. FX-at-checkout: presentment-enabled regions (Stripe) charge in the region currency \u2014 see the presentment field below; else charged in store base currency
3679
3808
  shippingAddress?: CheckoutAddress | null;
3680
3809
  billingAddress?: CheckoutAddress | null;
3681
3810
  shippingRateId?: string | null;
@@ -3695,6 +3824,18 @@ interface Checkout {
3695
3824
  itemCount: number;
3696
3825
  availableShippingRates?: ShippingRate[];
3697
3826
  reservation?: ReservationInfo;
3827
+ // FX-at-checkout: present ONLY when the region charges in its own currency (presentment-enabled \u2014 Stripe today). The amounts the buyer is actually CHARGED, in presentment.currency; presentment.total equals the payment intent amount. Render these (not total/currency above) when present. Absent = charged in store base currency. The fields above stay the base reference.
3828
+ presentment?: {
3829
+ currency: string; // ISO-4217 charged currency, e.g. "EUR"
3830
+ subtotal: string;
3831
+ discountAmount: string;
3832
+ shippingAmount: string;
3833
+ taxAmount: string;
3834
+ surchargeAmount: string;
3835
+ total: string; // equals the charged amount, to the cent
3836
+ fxChargingRate: string; // base\u2192presentment rate (buffer included)
3837
+ fxBufferPercent: string | null;
3838
+ };
3698
3839
  createdAt: string;
3699
3840
  updatedAt: string;
3700
3841
  }
@@ -3709,6 +3850,7 @@ interface CheckoutLineItem {
3709
3850
  product: { id: string; name: string; sku: string; images?: ProductImage[]; };
3710
3851
  variant?: { id: string; name?: string | null; sku?: string | null; image?: ProductImage | string | null; } | null;
3711
3852
  metadata?: Record<string, unknown> | null; // Copied from CartItem.metadata \u2014 buyer customization values
3853
+ customizations?: Record<string, { label: string; value: string | string[]; type: string }>; // Resolved labels \u2014 same shape as OrderItem.customizations
3712
3854
  }
3713
3855
 
3714
3856
  interface CheckoutAddress {
@@ -3945,7 +4087,10 @@ interface PaymentProviderConfig {
3945
4087
  stripeAccountId?: string; // Stripe Connect only
3946
4088
  supportedMethods: string[];
3947
4089
  testMode: boolean;
3948
- isDefault: boolean;
4090
+ isDefault: boolean; // only a primary (CREDIT_CARD) is ever the default
4091
+ methodType: 'CREDIT_CARD' | 'WALLET' | 'OFFSITE' | 'LOCAL' | 'REDEEMABLE';
4092
+ presentation: 'card_form' | 'express_button' | 'redirect' | 'local_option' | 'redeemable_field';
4093
+ isAdditive: boolean; // wallet/alt method shown ALONGSIDE the primary (e.g. PayPal)
3949
4094
  }
3950
4095
  type PaymentProvider = PaymentProviderConfig;
3951
4096
 
@@ -4072,10 +4217,22 @@ interface CartAppliedDiscount {
4072
4217
  }
4073
4218
 
4074
4219
  // Recommendation types
4220
+ interface RecommendationVariant {
4221
+ id: string; name?: string; price?: string; salePrice?: string;
4222
+ attributes?: Record<string, string>; image?: ProductImage | string; inventory?: InventoryInfo;
4223
+ }
4075
4224
  interface ProductRecommendation {
4076
- id: string; name: string; slug: string; basePrice: string; salePrice?: string;
4225
+ id: string; name: string; slug: string;
4226
+ // For a VARIABLE target, basePrice is the pinned variant's price (when
4227
+ // targetVariantId is set) or the "from {min variant}" range \u2014 never 0.
4228
+ basePrice: string; salePrice?: string;
4077
4229
  images: ProductImage[]; type: 'SIMPLE' | 'VARIABLE'; inventory?: InventoryInfo;
4078
4230
  relationType: string;
4231
+ // Variant context (VARIABLE targets):
4232
+ targetVariantId?: string | null; // merchant-pinned variant, or null
4233
+ requiresVariantSelection?: boolean; // true \u2192 customer must pick from variants
4234
+ pinnedVariant?: { id: string; name?: string; attributes?: Record<string, string> } | null;
4235
+ variants?: RecommendationVariant[]; // present when requiresVariantSelection
4079
4236
  }
4080
4237
  interface ProductRecommendationsResponse {
4081
4238
  crossSells: ProductRecommendation[];
@@ -4109,6 +4266,12 @@ interface CartBundleOfferOfferedProduct {
4109
4266
  salePrice: string | null;
4110
4267
  images: Array<{ url: string }>;
4111
4268
  type: string;
4269
+ // Variant context (VARIABLE offered products):
4270
+ variantId?: string | null; // merchant-pinned variant for this slot
4271
+ requiresVariantSelection?: boolean; // true \u2192 customer must pick from variants
4272
+ pinnedVariant?: { id: string; name?: string; attributes?: Record<string, string> } | null;
4273
+ variants?: RecommendationVariant[]; // present when requiresVariantSelection
4274
+ // originalPrice = pinned/cheapest variant price for VARIABLE (not a 0 parent base).
4112
4275
  originalPrice: string;
4113
4276
  discountedPrice: string;
4114
4277
  }
@@ -4592,10 +4755,12 @@ interface UpdateRegionDto extends Partial<CreateRegionDto> { isActive?: boolean
4592
4755
  // client.detectRegion(country, regions): Region | null \u2014 pure, no network.
4593
4756
  // \u2192 region whose countries includes the code, else the default region, else null.
4594
4757
  // Pass the resolved regionId to createCheckout to associate the checkout with a
4595
- // region (recorded for reporting + provider scoping; currency follows the cart
4596
- // until FX price conversion lands).
4758
+ // region (recorded for reporting + provider scoping). FX-at-checkout:
4759
+ // presentment-enabled regions (Stripe) charge in the region currency and the
4760
+ // response carries a presentment overlay; else charged in store base currency.
4597
4761
  //
4598
- // Storefront (public, no apiKey \u2014 storeId mode):
4762
+ // Storefront (public, no apiKey \u2014 storeId mode OR vibe-coded mode, salesChannelId 'vc_*';
4763
+ // the vc routes are gated on products:read, which every connection already has):
4599
4764
  interface PublicRegion {
4600
4765
  id: string; name: string; slug: string; currency: string;
4601
4766
  countries: string[]; taxInclusive: boolean; isDefault: boolean;
@@ -4647,7 +4812,8 @@ interface AssignTaxClassDto { productIds?: string[]; variantIds?: string[]; cate
4647
4812
  // deleteTaxClass(id), setDefaultTaxClass(id), assignTaxClass(id, dto),
4648
4813
  // mergeTaxClasses(id, targetId)
4649
4814
  //
4650
- // SDK methods (storefront, public \u2014 storeId mode, no apiKey):
4815
+ // SDK methods (storefront, public \u2014 storeId mode OR vibe-coded mode 'vc_*', no apiKey;
4816
+ // the vc routes are gated on products:read, which every connection already has):
4651
4817
  // getStoreRegions(), getStoreRegion(id), getAutoRegion(country)
4652
4818
  // getStoreTaxClasses(), estimateTax({ country?, subtotal })
4653
4819
  //
@@ -4972,7 +5138,15 @@ const checkout = await client.getCheckout(checkoutId);
4972
5138
  import { client } from './brainerce';
4973
5139
 
4974
5140
  const { providers, hasPayments, defaultProvider } = await client.getPaymentProviders();
4975
- // each provider: { id, provider, name, publicKey, supportedMethods, testMode, isDefault, clientSdk? }
5141
+ // each provider: { id, provider, name, publicKey, supportedMethods, testMode,
5142
+ // isDefault, methodType, presentation, isAdditive, clientSdk? }
5143
+ //
5144
+ // methodType splits providers into ONE primary card processor (CREDIT_CARD, the
5145
+ // defaultProvider that settles the order) and additive methods (isAdditive:true,
5146
+ // e.g. PayPal as a WALLET). Render additive methods as express buttons ABOVE the
5147
+ // card form \u2014 they sit alongside the primary, never replace it. Call
5148
+ // createPaymentIntent({ providerId }) with the tapped provider's id. (Wallet-only
5149
+ // store: with no card processor, the wallet becomes defaultProvider and stands alone.)
4976
5150
  //
4977
5151
  // After createPaymentIntent, the response carries a clientSdk.renderType that
4978
5152
  // tells your UI how to render the payment step. The 5 possible values:
package/package.json CHANGED
@@ -1,53 +1,54 @@
1
- {
2
- "name": "@brainerce/mcp-server",
3
- "version": "3.11.1",
4
- "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
- "bin": {
6
- "brainerce-mcp": "dist/bin/stdio.js"
7
- },
8
- "main": "dist/index.js",
9
- "module": "dist/index.mjs",
10
- "types": "dist/index.d.ts",
11
- "exports": {
12
- ".": {
13
- "types": "./dist/index.d.ts",
14
- "require": "./dist/index.js",
15
- "import": "./dist/index.mjs"
16
- }
17
- },
18
- "files": [
19
- "dist",
20
- "README.md"
21
- ],
22
- "scripts": {
23
- "build": "tsup",
24
- "dev": "tsup --watch",
25
- "start:stdio": "node dist/bin/stdio.js",
26
- "start:http": "node dist/bin/http.js",
27
- "prepublishOnly": "npm run build"
28
- },
29
- "dependencies": {
30
- "@modelcontextprotocol/sdk": "^1.27.1",
31
- "zod": "^3.24.0"
32
- },
33
- "devDependencies": {
34
- "@types/node": "^22.0.0",
35
- "tsup": "^8.0.0",
36
- "typescript": "^5.3.0"
37
- },
38
- "engines": {
39
- "node": ">=18"
40
- },
41
- "keywords": [
42
- "brainerce",
43
- "mcp",
44
- "model-context-protocol",
45
- "ai",
46
- "ecommerce",
47
- "lovable",
48
- "cursor",
49
- "claude-code",
50
- "vibe-coding"
51
- ],
52
- "license": "MIT"
53
- }
1
+ {
2
+ "name": "@brainerce/mcp-server",
3
+ "version": "3.12.1",
4
+ "packageManager": "pnpm@9.0.0",
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
+ "bin": {
7
+ "brainerce-mcp": "dist/bin/stdio.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "module": "dist/index.mjs",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "require": "./dist/index.js",
16
+ "import": "./dist/index.mjs"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "start:stdio": "node dist/bin/stdio.js",
27
+ "start:http": "node dist/bin/http.js",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.27.1",
32
+ "zod": "^3.24.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "tsup": "^8.0.0",
37
+ "typescript": "^5.3.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
41
+ },
42
+ "keywords": [
43
+ "brainerce",
44
+ "mcp",
45
+ "model-context-protocol",
46
+ "ai",
47
+ "ecommerce",
48
+ "lovable",
49
+ "cursor",
50
+ "claude-code",
51
+ "vibe-coding"
52
+ ],
53
+ "license": "MIT"
54
+ }