@usethrottle/mcp 0.2.1 → 0.3.0

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/lib.js CHANGED
@@ -1471,14 +1471,22 @@ var ACTIONS = [
1471
1471
  scopes: ["quotes:write"],
1472
1472
  input: [
1473
1473
  { name: "customerId", type: "string", required: true, description: "Customer the quote is for." },
1474
- { name: "items", type: "array", required: true, description: "Quote line items: { name, unitPrice, quantity }." },
1474
+ {
1475
+ name: "items",
1476
+ type: "array",
1477
+ required: true,
1478
+ description: "Quote line items: { name, unitPrice, quantity }. Add `recurring: { plan, interval | intervalUnit + intervalCount, totalPayments?, trialDays? }` to make a line a subscription (one per line when the quote is paid, quantity = seats; at most 10). unitPrice is then the per-period price; a free-trial line is charged nothing at acceptance."
1479
+ },
1475
1480
  { name: "expiresAt", type: "string", required: false, description: "ISO 8601 expiry." },
1476
- { name: "netN", type: "number", required: false, description: "Payment terms in days. Omit for pay-in-full." },
1481
+ { name: "netN", type: "number", required: false, description: "Payment terms in days. Omit for pay-in-full. Not allowed when any item is recurring." },
1477
1482
  { name: "notes", type: "string", required: false, description: "Buyer-visible notes." }
1478
1483
  ],
1479
1484
  requests: [{ method: "POST", path: "/api/v1/quotes" }],
1480
1485
  channels: ["mcp", "zapier", "make", "n8n"],
1481
- idempotent: true
1486
+ idempotent: true,
1487
+ guardrails: [
1488
+ "A quote with a recurring item must be pay-in-full: issuing it with net terms or a deposit fails with 422 recurring_terms_unsupported."
1489
+ ]
1482
1490
  },
1483
1491
  {
1484
1492
  id: "send_quote",
@@ -1585,12 +1593,12 @@ var ACTIONS = [
1585
1593
  {
1586
1594
  id: "send_test_webhook",
1587
1595
  title: "Send a test webhook",
1588
- description: "Send a synthetic signed event to a webhook endpoint to verify signature handling and reachability.",
1596
+ description: "Send a synthetic signed event to a webhook endpoint to verify signature handling and reachability. The event type must be one the endpoint is subscribed to (an endpoint subscribed to all events accepts any); otherwise the call fails with 400 validation_error naming the allowed types.",
1589
1597
  kind: "write",
1590
1598
  scopes: ["webhooks:write"],
1591
1599
  input: [
1592
1600
  { name: "id", type: "string", required: true, description: "Endpoint id." },
1593
- { name: "eventType", type: "string", required: false, description: "Event type to simulate." }
1601
+ { name: "eventType", type: "string", required: false, description: "Event type to simulate. Must be in the endpoint's subscribed events unless it subscribes to all." }
1594
1602
  ],
1595
1603
  requests: [{ method: "POST", path: "/api/v1/webhook-endpoints/:id/test" }],
1596
1604
  channels: ["mcp", "n8n"],
@@ -1696,6 +1704,7 @@ var ThrottleError = class extends Error {
1696
1704
  statusCode;
1697
1705
  details;
1698
1706
  body;
1707
+ requestId;
1699
1708
  constructor(args) {
1700
1709
  super(args.message);
1701
1710
  this.name = "ThrottleError";
@@ -1703,14 +1712,17 @@ var ThrottleError = class extends Error {
1703
1712
  this.statusCode = args.statusCode;
1704
1713
  this.details = args.details;
1705
1714
  this.body = args.body;
1715
+ const fromBody = args.body?.meta?.requestId;
1716
+ const fromHeader = typeof args.responseHeaders?.get === "function" ? args.responseHeaders.get("x-request-id") : args.responseHeaders?.["x-request-id"];
1717
+ this.requestId = args.requestId ?? (typeof fromBody === "string" ? fromBody : void 0) ?? (typeof fromHeader === "string" ? fromHeader : void 0);
1706
1718
  Object.setPrototypeOf(this, new.target.prototype);
1707
1719
  }
1708
1720
  };
1709
1721
 
1710
1722
  // src/client.ts
1711
1723
  var ThrottleApiError = class extends ThrottleError {
1712
- constructor(code, message, statusCode, details) {
1713
- super({ code, message, statusCode, details });
1724
+ constructor(code, message, statusCode, details, responseHeaders) {
1725
+ super({ code, message, statusCode, details, responseHeaders });
1714
1726
  this.name = "ThrottleApiError";
1715
1727
  }
1716
1728
  };
@@ -1776,7 +1788,8 @@ var ThrottleClient = class {
1776
1788
  err?.code ?? `http_${res.status}`,
1777
1789
  err?.message ?? `Request failed (${res.status}): ${text.slice(0, 200)}`,
1778
1790
  res.status,
1779
- err?.details
1791
+ err?.details,
1792
+ res.headers
1780
1793
  );
1781
1794
  }
1782
1795
  return parsed;
@@ -2381,14 +2394,14 @@ var HANDLERS = {
2381
2394
  idempotencyKey: `mcp-manage-subscription-${id}-${action}-${Date.now()}`
2382
2395
  });
2383
2396
  },
2384
- create_quote: async (ctx, args) => (
2385
- // The real route's body shape differs from this tool's flatter,
2386
- // model-facing input: line items are "items" (not "lineItems"), Net-N
2387
- // terms are nested under paymentTerms.netN with an explicit mode (not a
2388
- // flat "netN"), and the buyer-visible note field is "buyerNote" (not
2389
- // "notes"). Confirmed against packages/platform-api/src/validation/quotes.ts's
2390
- // actual zod schema after a live call 400'd with unrecognized_keys.
2391
- ctx.client.post("/api/v1/quotes", {
2397
+ create_quote: async (ctx, args) => {
2398
+ const items = Array.isArray(args.items) ? args.items : [];
2399
+ if (args.netN !== void 0 && items.some((item) => item && item.recurring)) {
2400
+ throw new Error(
2401
+ "create_quote: items with `recurring` need pay-in-full terms \u2014 omit netN. Net terms cannot start a subscription."
2402
+ );
2403
+ }
2404
+ return ctx.client.post("/api/v1/quotes", {
2392
2405
  body: {
2393
2406
  customerId: args.customerId,
2394
2407
  items: args.items,
@@ -2397,8 +2410,8 @@ var HANDLERS = {
2397
2410
  buyerNote: args.notes
2398
2411
  },
2399
2412
  idempotencyKey: `mcp-create-quote-${String(args.customerId)}-${Date.now()}`
2400
- })
2401
- ),
2413
+ });
2414
+ },
2402
2415
  get_sales_timeseries: async (ctx, args) => ctx.client.get(
2403
2416
  "/api/v1/analytics/orders-timeseries",
2404
2417
  {
@@ -2655,6 +2668,14 @@ var ORDER_DISPLAY_STATUSES = new Set(
2655
2668
  );
2656
2669
  var DISPLAY_STATUS = oneOf(ORDER_DISPLAY_STATUSES);
2657
2670
  var RANGE = { from: S, to: S, timezone: S, groupBy: S };
2671
+ var LINE_RECURRING = {
2672
+ plan: S,
2673
+ interval: S,
2674
+ intervalUnit: S,
2675
+ intervalCount: S,
2676
+ totalPayments: S,
2677
+ trialDays: S
2678
+ };
2658
2679
  var LINE_ITEM = {
2659
2680
  id: S,
2660
2681
  type: S,
@@ -2664,7 +2685,9 @@ var LINE_ITEM = {
2664
2685
  discountAmount: S,
2665
2686
  taxAmount: S,
2666
2687
  total: S,
2667
- recurring: S
2688
+ // amount = renewal price on a trial line (whose unitPrice is 0); count = the old display mirror.
2689
+ recurring: { ...LINE_RECURRING, amount: S, count: S },
2690
+ subscriptionId: S
2668
2691
  };
2669
2692
  var ORDER = {
2670
2693
  id: S,
@@ -2688,6 +2711,7 @@ var ORDER = {
2688
2711
  customerId: S,
2689
2712
  customer: CUSTOMER_REF,
2690
2713
  subscriptionId: S,
2714
+ subscriptionIds: [S],
2691
2715
  shippingAddress: ADDRESS,
2692
2716
  billingAddress: ADDRESS,
2693
2717
  fulfillmentSummary: { itemsFulfilled: S, itemsRemaining: S, itemsTotal: S },
@@ -2810,7 +2834,8 @@ var QUOTE = {
2810
2834
  taxAmount: S,
2811
2835
  total: S,
2812
2836
  optional: S,
2813
- optionalSelected: S
2837
+ optionalSelected: S,
2838
+ recurring: LINE_RECURRING
2814
2839
  }]
2815
2840
  }],
2816
2841
  // Who commented and when, never what they wrote.
@@ -2976,7 +3001,22 @@ var OAUTH_PROJECTIONS = {
2976
3001
  trialDays: S,
2977
3002
  currency: S,
2978
3003
  firstChargeAmountMinor: S
2979
- }
3004
+ },
3005
+ hasSubscriptions: S,
3006
+ // One entry per subscription line. No `name`: it is the line's name.
3007
+ subscriptions: [{
3008
+ lineItemId: S,
3009
+ amount: S,
3010
+ quantity: S,
3011
+ interval: S,
3012
+ intervalUnit: S,
3013
+ intervalCount: S,
3014
+ totalPayments: S,
3015
+ trialDays: S,
3016
+ trialEndsAt: S,
3017
+ planChargedToday: S,
3018
+ taxApplies: S
3019
+ }]
2980
3020
  },
2981
3021
  cart: section({
2982
3022
  id: S,
@@ -3117,7 +3157,7 @@ var OAUTH_PROJECTIONS = {
3117
3157
  };
3118
3158
 
3119
3159
  // src/server.ts
3120
- var VERSION = true ? "0.2.1" : "0.0.0-dev";
3160
+ var VERSION = true ? "0.3.0" : "0.0.0-dev";
3121
3161
  function registerableActions(policy) {
3122
3162
  const isProduction = policy.identity.environment.providerEnvironment === "production";
3123
3163
  return actionsForChannel("mcp").filter((action) => {