@yawlabs/lemonsqueezy-mcp 0.1.1 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +161 -131
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -21027,7 +21027,7 @@ function buildQuery(params) {
21027
21027
  if (!params) return "";
21028
21028
  const parts = [];
21029
21029
  if (params.include?.length) {
21030
- parts.push(`include=${encodeURIComponent(params.include.join(","))}`);
21030
+ parts.push(`include=${encodeURIComponent(params.include.map((s) => s.trim()).join(","))}`);
21031
21031
  }
21032
21032
  if (params.filter) {
21033
21033
  for (const [key, value] of Object.entries(params.filter)) {
@@ -21055,15 +21055,28 @@ async function apiRequest(method, path, body) {
21055
21055
  fetchBody = JSON.stringify(body);
21056
21056
  }
21057
21057
  const url = path.startsWith("http") ? path : `${BASE_URL}${path}`;
21058
- const res = await fetch(url, {
21059
- method,
21060
- headers,
21061
- body: fetchBody,
21062
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21063
- });
21058
+ let res;
21059
+ try {
21060
+ res = await fetch(url, {
21061
+ method,
21062
+ headers,
21063
+ body: fetchBody,
21064
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21065
+ });
21066
+ } catch (err) {
21067
+ if (err instanceof Error && err.name === "TimeoutError") {
21068
+ return { ok: false, status: 0, error: `Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s` };
21069
+ }
21070
+ throw err;
21071
+ }
21064
21072
  if (!res.ok) {
21065
21073
  const errorBody = await res.text();
21066
- return { ok: false, status: res.status, error: errorBody };
21074
+ try {
21075
+ const parsed = JSON.parse(errorBody);
21076
+ return { ok: false, status: res.status, data: parsed, error: parsed.errors?.[0]?.detail ?? errorBody };
21077
+ } catch {
21078
+ return { ok: false, status: res.status, error: errorBody };
21079
+ }
21067
21080
  }
21068
21081
  if (res.status === 204 || res.headers.get("content-length") === "0") {
21069
21082
  return { ok: true, status: res.status };
@@ -21073,18 +21086,31 @@ async function apiRequest(method, path, body) {
21073
21086
  }
21074
21087
  async function licenseRequest(path, body) {
21075
21088
  const url = `${BASE_URL}${path}`;
21076
- const res = await fetch(url, {
21077
- method: "POST",
21078
- headers: {
21079
- Accept: "application/json",
21080
- "Content-Type": "application/x-www-form-urlencoded"
21081
- },
21082
- body: new URLSearchParams(body),
21083
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21084
- });
21089
+ let res;
21090
+ try {
21091
+ res = await fetch(url, {
21092
+ method: "POST",
21093
+ headers: {
21094
+ Accept: "application/json",
21095
+ "Content-Type": "application/x-www-form-urlencoded"
21096
+ },
21097
+ body: new URLSearchParams(body),
21098
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21099
+ });
21100
+ } catch (err) {
21101
+ if (err instanceof Error && err.name === "TimeoutError") {
21102
+ return { ok: false, status: 0, error: `Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s` };
21103
+ }
21104
+ throw err;
21105
+ }
21085
21106
  if (!res.ok) {
21086
21107
  const errorBody = await res.text();
21087
- return { ok: false, status: res.status, error: errorBody };
21108
+ try {
21109
+ const parsed = JSON.parse(errorBody);
21110
+ return { ok: false, status: res.status, data: parsed, error: parsed.error ?? errorBody };
21111
+ } catch {
21112
+ return { ok: false, status: res.status, error: errorBody };
21113
+ }
21088
21114
  }
21089
21115
  const data = await res.json();
21090
21116
  return { ok: true, status: res.status, data };
@@ -21125,7 +21151,7 @@ var checkoutTools = [
21125
21151
  },
21126
21152
  {
21127
21153
  name: "ls_list_checkouts",
21128
- description: "List all checkouts, optionally filtered by store or variant.",
21154
+ description: "List all checkouts, optionally filtered by store or variant. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21129
21155
  annotations: {
21130
21156
  title: "List checkouts",
21131
21157
  readOnlyHint: true,
@@ -21137,8 +21163,8 @@ var checkoutTools = [
21137
21163
  storeId: external_exports.string().optional().describe("Filter by store ID"),
21138
21164
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21139
21165
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,variant')"),
21140
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21141
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21166
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21167
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21142
21168
  }),
21143
21169
  handler: async (input) => {
21144
21170
  const filter = {};
@@ -21165,21 +21191,21 @@ var checkoutTools = [
21165
21191
  inputSchema: external_exports.object({
21166
21192
  storeId: external_exports.string().describe("The store ID"),
21167
21193
  variantId: external_exports.string().describe("The variant ID for the product being purchased"),
21168
- customPrice: external_exports.number().optional().describe("Custom price in cents (overrides the variant price)"),
21169
- enabledVariants: external_exports.array(external_exports.number()).optional().describe("Array of variant IDs to show on the checkout (for products with multiple variants)"),
21194
+ customPrice: external_exports.number().int().min(0).optional().describe("Custom price in cents (overrides the variant price)"),
21195
+ enabledVariants: external_exports.array(external_exports.string()).optional().describe("Array of variant IDs to show on the checkout (for products with multiple variants)"),
21170
21196
  email: external_exports.string().optional().describe("Prefill customer email"),
21171
21197
  name: external_exports.string().optional().describe("Prefill customer name"),
21172
21198
  billingAddressCountry: external_exports.string().optional().describe("Prefill billing country (ISO 3166-1 alpha-2)"),
21173
21199
  billingAddressZip: external_exports.string().optional().describe("Prefill billing ZIP/postal code"),
21174
21200
  taxNumber: external_exports.string().optional().describe("Prefill tax/VAT number"),
21175
21201
  discountCode: external_exports.string().optional().describe("Pre-apply a discount code"),
21176
- customData: external_exports.string().optional().describe("Custom JSON data to attach to the order (as a JSON string)"),
21202
+ customData: external_exports.record(external_exports.unknown()).optional().describe("Custom data object to attach to the order"),
21177
21203
  expiresAt: external_exports.string().optional().describe("Checkout expiry date (ISO 8601 format)")
21178
21204
  }),
21179
21205
  handler: async (input) => {
21180
21206
  const attributes = {};
21181
21207
  if (input.customPrice !== void 0) attributes.custom_price = input.customPrice;
21182
- if (input.enabledVariants) attributes.product_options = { enabled_variants: input.enabledVariants };
21208
+ if (input.enabledVariants !== void 0) attributes.product_options = { enabled_variants: input.enabledVariants };
21183
21209
  if (input.expiresAt !== void 0) attributes.expires_at = input.expiresAt;
21184
21210
  const checkoutData = {};
21185
21211
  if (input.email !== void 0) checkoutData.email = input.email;
@@ -21195,11 +21221,7 @@ var checkoutTools = [
21195
21221
  if (input.taxNumber !== void 0) checkoutData.tax_number = input.taxNumber;
21196
21222
  if (input.discountCode !== void 0) checkoutData.discount_code = input.discountCode;
21197
21223
  if (input.customData !== void 0) {
21198
- try {
21199
- checkoutData.custom = JSON.parse(input.customData);
21200
- } catch {
21201
- checkoutData.custom = input.customData;
21202
- }
21224
+ checkoutData.custom = input.customData;
21203
21225
  }
21204
21226
  if (Object.keys(checkoutData).length > 0) attributes.checkout_data = checkoutData;
21205
21227
  return apiPost("/checkouts", {
@@ -21239,7 +21261,7 @@ var customerTools = [
21239
21261
  },
21240
21262
  {
21241
21263
  name: "ls_list_customers",
21242
- description: "List all customers, optionally filtered by store or email.",
21264
+ description: "List all customers, optionally filtered by store or email. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21243
21265
  annotations: {
21244
21266
  title: "List customers",
21245
21267
  readOnlyHint: true,
@@ -21251,8 +21273,8 @@ var customerTools = [
21251
21273
  storeId: external_exports.string().optional().describe("Filter by store ID"),
21252
21274
  email: external_exports.string().optional().describe("Filter by customer email"),
21253
21275
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,orders,subscriptions,license-keys')"),
21254
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21255
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21276
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21277
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21256
21278
  }),
21257
21279
  handler: async (input) => {
21258
21280
  const filter = {};
@@ -21289,9 +21311,9 @@ var customerTools = [
21289
21311
  name: input.name,
21290
21312
  email: input.email
21291
21313
  };
21292
- if (input.city) attributes.city = input.city;
21293
- if (input.region) attributes.region = input.region;
21294
- if (input.country) attributes.country = input.country;
21314
+ if (input.city !== void 0) attributes.city = input.city;
21315
+ if (input.region !== void 0) attributes.region = input.region;
21316
+ if (input.country !== void 0) attributes.country = input.country;
21295
21317
  return apiPost("/customers", {
21296
21318
  data: {
21297
21319
  type: "customers",
@@ -21387,7 +21409,7 @@ var discountRedemptionTools = [
21387
21409
  },
21388
21410
  {
21389
21411
  name: "ls_list_discount_redemptions",
21390
- description: "List all discount redemptions, optionally filtered by discount or order.",
21412
+ description: "List all discount redemptions, optionally filtered by discount or order. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21391
21413
  annotations: {
21392
21414
  title: "List discount redemptions",
21393
21415
  readOnlyHint: true,
@@ -21399,8 +21421,8 @@ var discountRedemptionTools = [
21399
21421
  discountId: external_exports.string().optional().describe("Filter by discount ID"),
21400
21422
  orderId: external_exports.string().optional().describe("Filter by order ID"),
21401
21423
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'discount,order')"),
21402
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21403
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21424
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21425
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21404
21426
  }),
21405
21427
  handler: async (input) => {
21406
21428
  const filter = {};
@@ -21439,7 +21461,7 @@ var discountTools = [
21439
21461
  },
21440
21462
  {
21441
21463
  name: "ls_list_discounts",
21442
- description: "List all discounts, optionally filtered by store.",
21464
+ description: "List all discounts, optionally filtered by store. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21443
21465
  annotations: {
21444
21466
  title: "List discounts",
21445
21467
  readOnlyHint: true,
@@ -21450,8 +21472,8 @@ var discountTools = [
21450
21472
  inputSchema: external_exports.object({
21451
21473
  storeId: external_exports.string().optional().describe("Filter by store ID"),
21452
21474
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,variants,discount-redemptions')"),
21453
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21454
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21475
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21476
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21455
21477
  }),
21456
21478
  handler: async (input) => {
21457
21479
  const filter = {};
@@ -21478,19 +21500,19 @@ var discountTools = [
21478
21500
  storeId: external_exports.string().describe("The store ID to create the discount in"),
21479
21501
  name: external_exports.string().describe("Internal name for the discount"),
21480
21502
  code: external_exports.string().describe("The discount code customers will enter (e.g. 'SAVE20')"),
21481
- amount: external_exports.number().describe(
21503
+ amount: external_exports.number().int().min(1).describe(
21482
21504
  "Discount amount \u2014 in cents for 'fixed' type (e.g. 1000 = $10.00), or percentage for 'percent' type (e.g. 20 = 20%)"
21483
21505
  ),
21484
- amountType: external_exports.string().describe("Discount type: 'percent' or 'fixed'"),
21485
- duration: external_exports.string().optional().describe(
21506
+ amountType: external_exports.enum(["percent", "fixed"]).describe("Discount type: 'percent' or 'fixed'"),
21507
+ duration: external_exports.enum(["once", "repeating", "forever"]).optional().describe(
21486
21508
  "How long the discount applies: 'once' (first payment only), 'repeating' (for N months), or 'forever' (default)"
21487
21509
  ),
21488
- durationInMonths: external_exports.number().optional().describe("Number of months the discount applies (required when duration is 'repeating')"),
21489
- maxRedemptions: external_exports.number().optional().describe("Maximum number of times this discount can be redeemed (0 = unlimited)"),
21510
+ durationInMonths: external_exports.number().int().min(1).optional().describe("Number of months the discount applies (required when duration is 'repeating')"),
21511
+ maxRedemptions: external_exports.number().int().min(0).optional().describe("Maximum number of times this discount can be redeemed (0 = unlimited)"),
21490
21512
  startsAt: external_exports.string().optional().describe("When the discount becomes active (ISO 8601 format)"),
21491
21513
  expiresAt: external_exports.string().optional().describe("When the discount expires (ISO 8601 format)"),
21492
21514
  isLimitedToProducts: external_exports.boolean().optional().describe("If true, the discount only applies to specific variants (set via variantIds)"),
21493
- variantIds: external_exports.array(external_exports.number()).optional().describe("Array of variant IDs this discount applies to (requires isLimitedToProducts: true)")
21515
+ variantIds: external_exports.array(external_exports.string()).optional().describe("Array of variant IDs this discount applies to (requires isLimitedToProducts: true)")
21494
21516
  }),
21495
21517
  handler: async (input) => {
21496
21518
  const attributes = {
@@ -21510,7 +21532,7 @@ var discountTools = [
21510
21532
  };
21511
21533
  if (input.variantIds?.length) {
21512
21534
  relationships.variants = {
21513
- data: input.variantIds.map((id) => ({ type: "variants", id: String(id) }))
21535
+ data: input.variantIds.map((id) => ({ type: "variants", id }))
21514
21536
  };
21515
21537
  }
21516
21538
  return apiPost("/discounts", {
@@ -21564,7 +21586,7 @@ var fileTools = [
21564
21586
  },
21565
21587
  {
21566
21588
  name: "ls_list_files",
21567
- description: "List all files, optionally filtered by variant.",
21589
+ description: "List all files, optionally filtered by variant. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21568
21590
  annotations: {
21569
21591
  title: "List files",
21570
21592
  readOnlyHint: true,
@@ -21575,8 +21597,8 @@ var fileTools = [
21575
21597
  inputSchema: external_exports.object({
21576
21598
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21577
21599
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'variant')"),
21578
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21579
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21600
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21601
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21580
21602
  }),
21581
21603
  handler: async (input) => {
21582
21604
  const filter = {};
@@ -21614,7 +21636,7 @@ var licenseKeyInstanceTools = [
21614
21636
  },
21615
21637
  {
21616
21638
  name: "ls_list_license_key_instances",
21617
- description: "List all license key instances (activations), optionally filtered by license key.",
21639
+ description: "List all license key instances (activations), optionally filtered by license key. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21618
21640
  annotations: {
21619
21641
  title: "List license key instances",
21620
21642
  readOnlyHint: true,
@@ -21625,8 +21647,8 @@ var licenseKeyInstanceTools = [
21625
21647
  inputSchema: external_exports.object({
21626
21648
  licenseKeyId: external_exports.string().optional().describe("Filter by license key ID"),
21627
21649
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'license-key')"),
21628
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21629
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21650
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21651
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21630
21652
  }),
21631
21653
  handler: async (input) => {
21632
21654
  const filter = {};
@@ -21666,7 +21688,7 @@ var licenseKeyTools = [
21666
21688
  },
21667
21689
  {
21668
21690
  name: "ls_list_license_keys",
21669
- description: "List all license keys, optionally filtered by store, order, or product.",
21691
+ description: "List all license keys, optionally filtered by store, order, or product. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21670
21692
  annotations: {
21671
21693
  title: "List license keys",
21672
21694
  readOnlyHint: true,
@@ -21682,8 +21704,8 @@ var licenseKeyTools = [
21682
21704
  include: external_exports.string().optional().describe(
21683
21705
  "Comma-separated related resources to include (e.g. 'store,customer,order,order-item,product,license-key-instances')"
21684
21706
  ),
21685
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21686
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21707
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21708
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21687
21709
  }),
21688
21710
  handler: async (input) => {
21689
21711
  const filter = {};
@@ -21711,7 +21733,7 @@ var licenseKeyTools = [
21711
21733
  },
21712
21734
  inputSchema: external_exports.object({
21713
21735
  licenseKeyId: external_exports.string().describe("The license key ID to update"),
21714
- activationLimit: external_exports.number().optional().describe("Maximum number of activations allowed (0 = unlimited)"),
21736
+ activationLimit: external_exports.number().int().min(0).optional().describe("Maximum number of activations allowed (0 = unlimited)"),
21715
21737
  disabled: external_exports.boolean().optional().describe("Set to true to disable this license key"),
21716
21738
  expiresAt: external_exports.string().optional().describe("Expiry date (ISO 8601 format). Set to null to remove expiry.")
21717
21739
  }),
@@ -21770,7 +21792,7 @@ var licenseTools = [
21770
21792
  }),
21771
21793
  handler: async (input) => {
21772
21794
  const body = { license_key: input.licenseKey };
21773
- if (input.instanceId) body.instance_id = input.instanceId;
21795
+ if (input.instanceId !== void 0) body.instance_id = input.instanceId;
21774
21796
  return licenseRequest("/licenses/validate", body);
21775
21797
  }
21776
21798
  },
@@ -21820,7 +21842,7 @@ var orderItemTools = [
21820
21842
  },
21821
21843
  {
21822
21844
  name: "ls_list_order_items",
21823
- description: "List all order items, optionally filtered by order or product.",
21845
+ description: "List all order items, optionally filtered by order or product. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21824
21846
  annotations: {
21825
21847
  title: "List order items",
21826
21848
  readOnlyHint: true,
@@ -21833,8 +21855,8 @@ var orderItemTools = [
21833
21855
  productId: external_exports.string().optional().describe("Filter by product ID"),
21834
21856
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21835
21857
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'order,product,variant')"),
21836
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21837
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21858
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21859
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21838
21860
  }),
21839
21861
  handler: async (input) => {
21840
21862
  const filter = {};
@@ -21876,7 +21898,7 @@ var orderTools = [
21876
21898
  },
21877
21899
  {
21878
21900
  name: "ls_list_orders",
21879
- description: "List all orders, optionally filtered by store, email, or user email.",
21901
+ description: "List all orders, optionally filtered by store or user email. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21880
21902
  annotations: {
21881
21903
  title: "List orders",
21882
21904
  readOnlyHint: true,
@@ -21890,8 +21912,8 @@ var orderTools = [
21890
21912
  include: external_exports.string().optional().describe(
21891
21913
  "Comma-separated related resources to include (e.g. 'store,customer,order-items,subscriptions,license-keys,discount-redemptions')"
21892
21914
  ),
21893
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21894
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21915
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21916
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21895
21917
  }),
21896
21918
  handler: async (input) => {
21897
21919
  const filter = {};
@@ -21923,18 +21945,21 @@ var orderTools = [
21923
21945
  state: external_exports.string().optional().describe("Customer state/region"),
21924
21946
  zipCode: external_exports.string().optional().describe("Customer ZIP/postal code"),
21925
21947
  country: external_exports.string().optional().describe("Customer country"),
21926
- notes: external_exports.string().optional().describe("Additional notes to include on the invoice")
21948
+ notes: external_exports.string().optional().describe("Additional notes to include on the invoice"),
21949
+ locale: external_exports.string().optional().describe("Invoice language locale (e.g. 'en', 'fr', 'de')")
21927
21950
  }),
21928
21951
  handler: async (input) => {
21929
- const body = {};
21930
- if (input.name !== void 0) body.name = input.name;
21931
- if (input.address !== void 0) body.address = input.address;
21932
- if (input.city !== void 0) body.city = input.city;
21933
- if (input.state !== void 0) body.state = input.state;
21934
- if (input.zipCode !== void 0) body.zip_code = input.zipCode;
21935
- if (input.country !== void 0) body.country = input.country;
21936
- if (input.notes !== void 0) body.notes = input.notes;
21937
- return apiPost(`/orders/${input.orderId}/generate-invoice`, body);
21952
+ const params = new URLSearchParams();
21953
+ if (input.name !== void 0) params.set("name", input.name);
21954
+ if (input.address !== void 0) params.set("address", input.address);
21955
+ if (input.city !== void 0) params.set("city", input.city);
21956
+ if (input.state !== void 0) params.set("state", input.state);
21957
+ if (input.zipCode !== void 0) params.set("zip_code", input.zipCode);
21958
+ if (input.country !== void 0) params.set("country", input.country);
21959
+ if (input.notes !== void 0) params.set("notes", input.notes);
21960
+ if (input.locale !== void 0) params.set("locale", input.locale);
21961
+ const qs = params.toString();
21962
+ return apiPost(`/orders/${input.orderId}/generate-invoice${qs ? `?${qs}` : ""}`);
21938
21963
  }
21939
21964
  },
21940
21965
  {
@@ -21949,7 +21974,7 @@ var orderTools = [
21949
21974
  },
21950
21975
  inputSchema: external_exports.object({
21951
21976
  orderId: external_exports.string().describe("The order ID to refund"),
21952
- amount: external_exports.number().describe("Refund amount in cents (e.g. 1000 = $10.00)")
21977
+ amount: external_exports.number().int().min(1).describe("Refund amount in cents (e.g. 1000 = $10.00)")
21953
21978
  }),
21954
21979
  handler: async (input) => {
21955
21980
  return apiPost(`/orders/${input.orderId}/refund`, {
@@ -21982,7 +22007,7 @@ var priceTools = [
21982
22007
  },
21983
22008
  {
21984
22009
  name: "ls_list_prices",
21985
- description: "List all prices, optionally filtered by variant.",
22010
+ description: "List all prices, optionally filtered by variant. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21986
22011
  annotations: {
21987
22012
  title: "List prices",
21988
22013
  readOnlyHint: true,
@@ -21993,8 +22018,8 @@ var priceTools = [
21993
22018
  inputSchema: external_exports.object({
21994
22019
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21995
22020
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'variant')"),
21996
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21997
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22021
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22022
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21998
22023
  }),
21999
22024
  handler: async (input) => {
22000
22025
  const filter = {};
@@ -22032,7 +22057,7 @@ var productTools = [
22032
22057
  },
22033
22058
  {
22034
22059
  name: "ls_list_products",
22035
- description: "List all products, optionally filtered by store.",
22060
+ description: "List all products, optionally filtered by store. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22036
22061
  annotations: {
22037
22062
  title: "List products",
22038
22063
  readOnlyHint: true,
@@ -22043,8 +22068,8 @@ var productTools = [
22043
22068
  inputSchema: external_exports.object({
22044
22069
  storeId: external_exports.string().optional().describe("Filter by store ID"),
22045
22070
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,variants')"),
22046
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22047
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22071
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22072
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22048
22073
  }),
22049
22074
  handler: async (input) => {
22050
22075
  const filter = {};
@@ -22084,7 +22109,7 @@ var storeTools = [
22084
22109
  },
22085
22110
  {
22086
22111
  name: "ls_list_stores",
22087
- description: "List all stores for the authenticated user.",
22112
+ description: "List all stores for the authenticated user. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22088
22113
  annotations: {
22089
22114
  title: "List stores",
22090
22115
  readOnlyHint: true,
@@ -22096,8 +22121,8 @@ var storeTools = [
22096
22121
  include: external_exports.string().optional().describe(
22097
22122
  "Comma-separated related resources to include (e.g. 'products,discounts,license-keys,subscriptions,webhooks')"
22098
22123
  ),
22099
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22100
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22124
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22125
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22101
22126
  }),
22102
22127
  handler: async (input) => {
22103
22128
  const query = buildQuery({
@@ -22132,7 +22157,7 @@ var subscriptionInvoiceTools = [
22132
22157
  },
22133
22158
  {
22134
22159
  name: "ls_list_subscription_invoices",
22135
- description: "List all subscription invoices, optionally filtered by store, subscription, or status.",
22160
+ description: "List all subscription invoices, optionally filtered by store, subscription, or status. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22136
22161
  annotations: {
22137
22162
  title: "List subscription invoices",
22138
22163
  readOnlyHint: true,
@@ -22143,18 +22168,18 @@ var subscriptionInvoiceTools = [
22143
22168
  inputSchema: external_exports.object({
22144
22169
  storeId: external_exports.string().optional().describe("Filter by store ID"),
22145
22170
  subscriptionId: external_exports.string().optional().describe("Filter by subscription ID"),
22146
- status: external_exports.string().optional().describe("Filter by status (pending, paid, void, refunded)"),
22147
- refunded: external_exports.string().optional().describe("Filter by refunded status ('true' or 'false')"),
22171
+ status: external_exports.enum(["pending", "paid", "void", "refunded"]).optional().describe("Filter by invoice status"),
22172
+ refunded: external_exports.boolean().optional().describe("Filter by refunded status"),
22148
22173
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,subscription')"),
22149
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22150
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22174
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22175
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22151
22176
  }),
22152
22177
  handler: async (input) => {
22153
22178
  const filter = {};
22154
22179
  if (input.storeId) filter.store_id = input.storeId;
22155
22180
  if (input.subscriptionId) filter.subscription_id = input.subscriptionId;
22156
22181
  if (input.status) filter.status = input.status;
22157
- if (input.refunded) filter.refunded = input.refunded;
22182
+ if (input.refunded !== void 0) filter.refunded = String(input.refunded);
22158
22183
  const query = buildQuery({
22159
22184
  include: input.include?.split(","),
22160
22185
  filter,
@@ -22181,18 +22206,21 @@ var subscriptionInvoiceTools = [
22181
22206
  state: external_exports.string().optional().describe("Customer state/region"),
22182
22207
  zipCode: external_exports.string().optional().describe("Customer ZIP/postal code"),
22183
22208
  country: external_exports.string().optional().describe("Customer country"),
22184
- notes: external_exports.string().optional().describe("Additional notes to include on the invoice")
22209
+ notes: external_exports.string().optional().describe("Additional notes to include on the invoice"),
22210
+ locale: external_exports.string().optional().describe("Invoice language locale (e.g. 'en', 'fr', 'de')")
22185
22211
  }),
22186
22212
  handler: async (input) => {
22187
- const body = {};
22188
- if (input.name !== void 0) body.name = input.name;
22189
- if (input.address !== void 0) body.address = input.address;
22190
- if (input.city !== void 0) body.city = input.city;
22191
- if (input.state !== void 0) body.state = input.state;
22192
- if (input.zipCode !== void 0) body.zip_code = input.zipCode;
22193
- if (input.country !== void 0) body.country = input.country;
22194
- if (input.notes !== void 0) body.notes = input.notes;
22195
- return apiPost(`/subscription-invoices/${input.subscriptionInvoiceId}/generate-invoice`, body);
22213
+ const params = new URLSearchParams();
22214
+ if (input.name !== void 0) params.set("name", input.name);
22215
+ if (input.address !== void 0) params.set("address", input.address);
22216
+ if (input.city !== void 0) params.set("city", input.city);
22217
+ if (input.state !== void 0) params.set("state", input.state);
22218
+ if (input.zipCode !== void 0) params.set("zip_code", input.zipCode);
22219
+ if (input.country !== void 0) params.set("country", input.country);
22220
+ if (input.notes !== void 0) params.set("notes", input.notes);
22221
+ if (input.locale !== void 0) params.set("locale", input.locale);
22222
+ const qs = params.toString();
22223
+ return apiPost(`/subscription-invoices/${input.subscriptionInvoiceId}/generate-invoice${qs ? `?${qs}` : ""}`);
22196
22224
  }
22197
22225
  },
22198
22226
  {
@@ -22207,7 +22235,7 @@ var subscriptionInvoiceTools = [
22207
22235
  },
22208
22236
  inputSchema: external_exports.object({
22209
22237
  subscriptionInvoiceId: external_exports.string().describe("The subscription invoice ID to refund"),
22210
- amount: external_exports.number().describe("Refund amount in cents (e.g. 1000 = $10.00)")
22238
+ amount: external_exports.number().int().min(1).describe("Refund amount in cents (e.g. 1000 = $10.00)")
22211
22239
  }),
22212
22240
  handler: async (input) => {
22213
22241
  return apiPost(`/subscription-invoices/${input.subscriptionInvoiceId}/refund`, {
@@ -22244,7 +22272,7 @@ var subscriptionItemTools = [
22244
22272
  },
22245
22273
  {
22246
22274
  name: "ls_list_subscription_items",
22247
- description: "List all subscription items, optionally filtered by subscription or price.",
22275
+ description: "List all subscription items, optionally filtered by subscription or price. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22248
22276
  annotations: {
22249
22277
  title: "List subscription items",
22250
22278
  readOnlyHint: true,
@@ -22256,8 +22284,8 @@ var subscriptionItemTools = [
22256
22284
  subscriptionId: external_exports.string().optional().describe("Filter by subscription ID"),
22257
22285
  priceId: external_exports.string().optional().describe("Filter by price ID"),
22258
22286
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'subscription,price,usage-records')"),
22259
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22260
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22287
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22288
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22261
22289
  }),
22262
22290
  handler: async (input) => {
22263
22291
  const filter = {};
@@ -22283,7 +22311,7 @@ var subscriptionItemTools = [
22283
22311
  },
22284
22312
  inputSchema: external_exports.object({
22285
22313
  subscriptionItemId: external_exports.string().describe("The subscription item ID to update"),
22286
- quantity: external_exports.number().describe("New quantity for the subscription item")
22314
+ quantity: external_exports.number().int().min(1).describe("New quantity for the subscription item")
22287
22315
  }),
22288
22316
  handler: async (input) => {
22289
22317
  return apiPatch(`/subscription-items/${input.subscriptionItemId}`, {
@@ -22339,7 +22367,7 @@ var subscriptionTools = [
22339
22367
  },
22340
22368
  {
22341
22369
  name: "ls_list_subscriptions",
22342
- description: "List all subscriptions, optionally filtered by store, order, product, variant, or status.",
22370
+ description: "List all subscriptions, optionally filtered by store, order, product, variant, or status. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22343
22371
  annotations: {
22344
22372
  title: "List subscriptions",
22345
22373
  readOnlyHint: true,
@@ -22354,12 +22382,12 @@ var subscriptionTools = [
22354
22382
  productId: external_exports.string().optional().describe("Filter by product ID"),
22355
22383
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
22356
22384
  userEmail: external_exports.string().optional().describe("Filter by user email"),
22357
- status: external_exports.string().optional().describe("Filter by status (on_trial, active, paused, past_due, unpaid, cancelled, expired)"),
22385
+ status: external_exports.enum(["on_trial", "active", "paused", "past_due", "unpaid", "cancelled", "expired"]).optional().describe("Filter by subscription status"),
22358
22386
  include: external_exports.string().optional().describe(
22359
22387
  "Comma-separated related resources to include (e.g. 'store,customer,order,order-item,product,variant')"
22360
22388
  ),
22361
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22362
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22389
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22390
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22363
22391
  }),
22364
22392
  handler: async (input) => {
22365
22393
  const filter = {};
@@ -22390,18 +22418,20 @@ var subscriptionTools = [
22390
22418
  },
22391
22419
  inputSchema: external_exports.object({
22392
22420
  subscriptionId: external_exports.string().describe("The subscription ID to update"),
22393
- variantId: external_exports.number().optional().describe("New variant ID for plan switching"),
22394
- pause: external_exports.string().optional().describe("Pause mode: 'void' (pause immediately, no invoice) or 'free' (pause immediately, no charge)"),
22395
- cancelled: external_exports.boolean().optional().describe("Set to false to resume a cancelled subscription (before it expires)"),
22396
- billingAnchor: external_exports.number().optional().describe("Day of month (1-28) to anchor billing to"),
22421
+ variantId: external_exports.string().optional().describe("New variant ID for plan switching"),
22422
+ pause: external_exports.enum(["void", "free", "resume"]).optional().describe("Pause mode: 'void' (pause, skip billing), 'free' (pause, keep access free), or 'resume' to unpause"),
22423
+ cancelled: external_exports.literal(false).optional().describe(
22424
+ "Set to false to un-cancel a subscription before it expires. To cancel, use ls_cancel_subscription instead."
22425
+ ),
22426
+ billingAnchor: external_exports.number().int().min(1).max(28).optional().describe("Day of month (1-28) to anchor billing to"),
22397
22427
  invoiceImmediately: external_exports.boolean().optional().describe("If true, invoice immediately when updating (default false for prorated changes)"),
22398
22428
  disableProrations: external_exports.boolean().optional().describe("If true, disable prorations when changing plans"),
22399
22429
  trialEndsAt: external_exports.string().optional().describe("Set trial end date (ISO 8601 format). Set to null to end trial immediately.")
22400
22430
  }),
22401
22431
  handler: async (input) => {
22402
22432
  const attributes = {};
22403
- if (input.variantId !== void 0) attributes.variant_id = input.variantId;
22404
- if (input.pause !== void 0) attributes.pause = input.pause === "" ? null : { mode: input.pause };
22433
+ if (input.variantId !== void 0) attributes.variant_id = Number(input.variantId);
22434
+ if (input.pause !== void 0) attributes.pause = input.pause === "resume" ? null : { mode: input.pause };
22405
22435
  if (input.cancelled !== void 0) attributes.cancelled = input.cancelled;
22406
22436
  if (input.billingAnchor !== void 0) attributes.billing_anchor = input.billingAnchor;
22407
22437
  if (input.invoiceImmediately !== void 0) attributes.invoice_immediately = input.invoiceImmediately;
@@ -22458,7 +22488,7 @@ var usageRecordTools = [
22458
22488
  },
22459
22489
  {
22460
22490
  name: "ls_list_usage_records",
22461
- description: "List all usage records, optionally filtered by subscription item.",
22491
+ description: "List all usage records, optionally filtered by subscription item. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22462
22492
  annotations: {
22463
22493
  title: "List usage records",
22464
22494
  readOnlyHint: true,
@@ -22469,8 +22499,8 @@ var usageRecordTools = [
22469
22499
  inputSchema: external_exports.object({
22470
22500
  subscriptionItemId: external_exports.string().optional().describe("Filter by subscription item ID"),
22471
22501
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'subscription-item')"),
22472
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22473
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22502
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22503
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22474
22504
  }),
22475
22505
  handler: async (input) => {
22476
22506
  const filter = {};
@@ -22495,14 +22525,14 @@ var usageRecordTools = [
22495
22525
  },
22496
22526
  inputSchema: external_exports.object({
22497
22527
  subscriptionItemId: external_exports.string().describe("The subscription item ID to report usage for"),
22498
- quantity: external_exports.number().describe("The usage quantity to report"),
22499
- action: external_exports.string().optional().describe("How to apply the quantity: 'increment' (add to current, default) or 'set' (replace current)")
22528
+ quantity: external_exports.number().int().min(0).describe("The usage quantity to report"),
22529
+ action: external_exports.enum(["increment", "set"]).optional().describe("How to apply the quantity: 'increment' (add to current, default) or 'set' (replace current)")
22500
22530
  }),
22501
22531
  handler: async (input) => {
22502
22532
  const attributes = {
22503
22533
  quantity: input.quantity
22504
22534
  };
22505
- if (input.action) attributes.action = input.action;
22535
+ if (input.action !== void 0) attributes.action = input.action;
22506
22536
  return apiPost("/usage-records", {
22507
22537
  data: {
22508
22538
  type: "usage-records",
@@ -22560,7 +22590,7 @@ var variantTools = [
22560
22590
  },
22561
22591
  {
22562
22592
  name: "ls_list_variants",
22563
- description: "List all variants, optionally filtered by product.",
22593
+ description: "List all variants, optionally filtered by product. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22564
22594
  annotations: {
22565
22595
  title: "List variants",
22566
22596
  readOnlyHint: true,
@@ -22571,8 +22601,8 @@ var variantTools = [
22571
22601
  inputSchema: external_exports.object({
22572
22602
  productId: external_exports.string().optional().describe("Filter by product ID"),
22573
22603
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'product,files')"),
22574
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22575
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22604
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22605
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22576
22606
  }),
22577
22607
  handler: async (input) => {
22578
22608
  const filter = {};
@@ -22610,7 +22640,7 @@ var webhookTools = [
22610
22640
  },
22611
22641
  {
22612
22642
  name: "ls_list_webhooks",
22613
- description: "List all webhooks, optionally filtered by store.",
22643
+ description: "List all webhooks, optionally filtered by store. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22614
22644
  annotations: {
22615
22645
  title: "List webhooks",
22616
22646
  readOnlyHint: true,
@@ -22621,8 +22651,8 @@ var webhookTools = [
22621
22651
  inputSchema: external_exports.object({
22622
22652
  storeId: external_exports.string().optional().describe("Filter by store ID"),
22623
22653
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store')"),
22624
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22625
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22654
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22655
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22626
22656
  }),
22627
22657
  handler: async (input) => {
22628
22658
  const filter = {};
@@ -22651,7 +22681,7 @@ var webhookTools = [
22651
22681
  events: external_exports.array(external_exports.string()).describe(
22652
22682
  "Event types to subscribe to (e.g. ['order_created', 'subscription_created', 'subscription_updated', 'subscription_cancelled', 'subscription_payment_success', 'subscription_payment_failed', 'license_key_created'])"
22653
22683
  ),
22654
- secret: external_exports.string().describe("A signing secret for verifying webhook payloads (min 6, max 40 characters)")
22684
+ secret: external_exports.string().min(6).max(40).describe("A signing secret for verifying webhook payloads")
22655
22685
  }),
22656
22686
  handler: async (input) => {
22657
22687
  return apiPost("/webhooks", {
@@ -22719,7 +22749,7 @@ var webhookTools = [
22719
22749
  ];
22720
22750
 
22721
22751
  // src/index.ts
22722
- var version2 = true ? "0.1.1" : (await null).createRequire(import.meta.url)("../package.json").version;
22752
+ var version2 = true ? "0.2.0" : (await null).createRequire(import.meta.url)("../package.json").version;
22723
22753
  var subcommand = process.argv[2];
22724
22754
  if (subcommand === "version" || subcommand === "--version") {
22725
22755
  console.log(version2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/lemonsqueezy-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "LemonSqueezy MCP server for managing your store from AI assistants",
5
5
  "license": "MIT",
6
6
  "author": "YawLabs <contact@yaw.sh>",