@yawlabs/lemonsqueezy-mcp 0.1.1 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +241 -399
  2. package/package.json +2 -2
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,17 +21055,30 @@ 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
- if (res.status === 204 || res.headers.get("content-length") === "0") {
21081
+ if (res.status === 204) {
21069
21082
  return { ok: true, status: res.status };
21070
21083
  }
21071
21084
  const data = await res.json();
@@ -21073,22 +21086,61 @@ 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 {
21111
+ ok: false,
21112
+ status: res.status,
21113
+ data: parsed,
21114
+ error: parsed.errors?.[0]?.detail ?? parsed.error ?? errorBody
21115
+ };
21116
+ } catch {
21117
+ return { ok: false, status: res.status, error: errorBody };
21118
+ }
21088
21119
  }
21089
21120
  const data = await res.json();
21090
21121
  return { ok: true, status: res.status, data };
21091
21122
  }
21123
+ function getHandler(endpoint, idField) {
21124
+ return async (input) => {
21125
+ const query = buildQuery({ include: input.include?.split(",") });
21126
+ return apiGet(`${endpoint}/${input[idField]}${query}`);
21127
+ };
21128
+ }
21129
+ function listHandler(endpoint, filterMap = {}) {
21130
+ return async (input) => {
21131
+ const filter = {};
21132
+ for (const [inputKey, apiKey] of Object.entries(filterMap)) {
21133
+ const val = input[inputKey];
21134
+ if (val !== void 0) filter[apiKey] = String(val);
21135
+ }
21136
+ const query = buildQuery({
21137
+ include: input.include?.split(","),
21138
+ filter,
21139
+ page: { number: input.pageNumber, size: input.pageSize }
21140
+ });
21141
+ return apiGet(`${endpoint}${query}`);
21142
+ };
21143
+ }
21092
21144
  async function apiGet(path) {
21093
21145
  return apiRequest("GET", path);
21094
21146
  }
@@ -21118,14 +21170,11 @@ var checkoutTools = [
21118
21170
  checkoutId: external_exports.string().describe("The checkout ID"),
21119
21171
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,variant')")
21120
21172
  }),
21121
- handler: async (input) => {
21122
- const query = buildQuery({ include: input.include?.split(",") });
21123
- return apiGet(`/checkouts/${input.checkoutId}${query}`);
21124
- }
21173
+ handler: getHandler("/checkouts", "checkoutId")
21125
21174
  },
21126
21175
  {
21127
21176
  name: "ls_list_checkouts",
21128
- description: "List all checkouts, optionally filtered by store or variant.",
21177
+ 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
21178
  annotations: {
21130
21179
  title: "List checkouts",
21131
21180
  readOnlyHint: true,
@@ -21137,20 +21186,10 @@ var checkoutTools = [
21137
21186
  storeId: external_exports.string().optional().describe("Filter by store ID"),
21138
21187
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21139
21188
  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)")
21189
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21190
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21142
21191
  }),
21143
- handler: async (input) => {
21144
- const filter = {};
21145
- if (input.storeId) filter.store_id = input.storeId;
21146
- if (input.variantId) filter.variant_id = input.variantId;
21147
- const query = buildQuery({
21148
- include: input.include?.split(","),
21149
- filter,
21150
- page: { number: input.pageNumber, size: input.pageSize }
21151
- });
21152
- return apiGet(`/checkouts${query}`);
21153
- }
21192
+ handler: listHandler("/checkouts", { storeId: "store_id", variantId: "variant_id" })
21154
21193
  },
21155
21194
  {
21156
21195
  name: "ls_create_checkout",
@@ -21165,21 +21204,21 @@ var checkoutTools = [
21165
21204
  inputSchema: external_exports.object({
21166
21205
  storeId: external_exports.string().describe("The store ID"),
21167
21206
  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)"),
21207
+ customPrice: external_exports.number().int().min(0).optional().describe("Custom price in cents (overrides the variant price)"),
21208
+ enabledVariants: external_exports.array(external_exports.string()).optional().describe("Array of variant IDs to show on the checkout (for products with multiple variants)"),
21170
21209
  email: external_exports.string().optional().describe("Prefill customer email"),
21171
21210
  name: external_exports.string().optional().describe("Prefill customer name"),
21172
21211
  billingAddressCountry: external_exports.string().optional().describe("Prefill billing country (ISO 3166-1 alpha-2)"),
21173
21212
  billingAddressZip: external_exports.string().optional().describe("Prefill billing ZIP/postal code"),
21174
21213
  taxNumber: external_exports.string().optional().describe("Prefill tax/VAT number"),
21175
21214
  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)"),
21215
+ customData: external_exports.record(external_exports.unknown()).optional().describe("Custom data object to attach to the order"),
21177
21216
  expiresAt: external_exports.string().optional().describe("Checkout expiry date (ISO 8601 format)")
21178
21217
  }),
21179
21218
  handler: async (input) => {
21180
21219
  const attributes = {};
21181
21220
  if (input.customPrice !== void 0) attributes.custom_price = input.customPrice;
21182
- if (input.enabledVariants) attributes.product_options = { enabled_variants: input.enabledVariants };
21221
+ if (input.enabledVariants !== void 0) attributes.product_options = { enabled_variants: input.enabledVariants };
21183
21222
  if (input.expiresAt !== void 0) attributes.expires_at = input.expiresAt;
21184
21223
  const checkoutData = {};
21185
21224
  if (input.email !== void 0) checkoutData.email = input.email;
@@ -21195,11 +21234,7 @@ var checkoutTools = [
21195
21234
  if (input.taxNumber !== void 0) checkoutData.tax_number = input.taxNumber;
21196
21235
  if (input.discountCode !== void 0) checkoutData.discount_code = input.discountCode;
21197
21236
  if (input.customData !== void 0) {
21198
- try {
21199
- checkoutData.custom = JSON.parse(input.customData);
21200
- } catch {
21201
- checkoutData.custom = input.customData;
21202
- }
21237
+ checkoutData.custom = input.customData;
21203
21238
  }
21204
21239
  if (Object.keys(checkoutData).length > 0) attributes.checkout_data = checkoutData;
21205
21240
  return apiPost("/checkouts", {
@@ -21232,14 +21267,11 @@ var customerTools = [
21232
21267
  customerId: external_exports.string().describe("The customer ID"),
21233
21268
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,orders,subscriptions,license-keys')")
21234
21269
  }),
21235
- handler: async (input) => {
21236
- const query = buildQuery({ include: input.include?.split(",") });
21237
- return apiGet(`/customers/${input.customerId}${query}`);
21238
- }
21270
+ handler: getHandler("/customers", "customerId")
21239
21271
  },
21240
21272
  {
21241
21273
  name: "ls_list_customers",
21242
- description: "List all customers, optionally filtered by store or email.",
21274
+ 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
21275
  annotations: {
21244
21276
  title: "List customers",
21245
21277
  readOnlyHint: true,
@@ -21251,20 +21283,10 @@ var customerTools = [
21251
21283
  storeId: external_exports.string().optional().describe("Filter by store ID"),
21252
21284
  email: external_exports.string().optional().describe("Filter by customer email"),
21253
21285
  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)")
21286
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21287
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21256
21288
  }),
21257
- handler: async (input) => {
21258
- const filter = {};
21259
- if (input.storeId) filter.store_id = input.storeId;
21260
- if (input.email) filter.email = input.email;
21261
- const query = buildQuery({
21262
- include: input.include?.split(","),
21263
- filter,
21264
- page: { number: input.pageNumber, size: input.pageSize }
21265
- });
21266
- return apiGet(`/customers${query}`);
21267
- }
21289
+ handler: listHandler("/customers", { storeId: "store_id", email: "email" })
21268
21290
  },
21269
21291
  {
21270
21292
  name: "ls_create_customer",
@@ -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",
@@ -21380,14 +21402,11 @@ var discountRedemptionTools = [
21380
21402
  discountRedemptionId: external_exports.string().describe("The discount redemption ID"),
21381
21403
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'discount,order')")
21382
21404
  }),
21383
- handler: async (input) => {
21384
- const query = buildQuery({ include: input.include?.split(",") });
21385
- return apiGet(`/discount-redemptions/${input.discountRedemptionId}${query}`);
21386
- }
21405
+ handler: getHandler("/discount-redemptions", "discountRedemptionId")
21387
21406
  },
21388
21407
  {
21389
21408
  name: "ls_list_discount_redemptions",
21390
- description: "List all discount redemptions, optionally filtered by discount or order.",
21409
+ 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
21410
  annotations: {
21392
21411
  title: "List discount redemptions",
21393
21412
  readOnlyHint: true,
@@ -21399,20 +21418,10 @@ var discountRedemptionTools = [
21399
21418
  discountId: external_exports.string().optional().describe("Filter by discount ID"),
21400
21419
  orderId: external_exports.string().optional().describe("Filter by order ID"),
21401
21420
  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)")
21421
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21422
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21404
21423
  }),
21405
- handler: async (input) => {
21406
- const filter = {};
21407
- if (input.discountId) filter.discount_id = input.discountId;
21408
- if (input.orderId) filter.order_id = input.orderId;
21409
- const query = buildQuery({
21410
- include: input.include?.split(","),
21411
- filter,
21412
- page: { number: input.pageNumber, size: input.pageSize }
21413
- });
21414
- return apiGet(`/discount-redemptions${query}`);
21415
- }
21424
+ handler: listHandler("/discount-redemptions", { discountId: "discount_id", orderId: "order_id" })
21416
21425
  }
21417
21426
  ];
21418
21427
 
@@ -21432,14 +21441,11 @@ var discountTools = [
21432
21441
  discountId: external_exports.string().describe("The discount ID"),
21433
21442
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,variants,discount-redemptions')")
21434
21443
  }),
21435
- handler: async (input) => {
21436
- const query = buildQuery({ include: input.include?.split(",") });
21437
- return apiGet(`/discounts/${input.discountId}${query}`);
21438
- }
21444
+ handler: getHandler("/discounts", "discountId")
21439
21445
  },
21440
21446
  {
21441
21447
  name: "ls_list_discounts",
21442
- description: "List all discounts, optionally filtered by store.",
21448
+ description: "List all discounts, optionally filtered by store. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21443
21449
  annotations: {
21444
21450
  title: "List discounts",
21445
21451
  readOnlyHint: true,
@@ -21450,19 +21456,10 @@ var discountTools = [
21450
21456
  inputSchema: external_exports.object({
21451
21457
  storeId: external_exports.string().optional().describe("Filter by store ID"),
21452
21458
  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)")
21459
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21460
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21455
21461
  }),
21456
- handler: async (input) => {
21457
- const filter = {};
21458
- if (input.storeId) filter.store_id = input.storeId;
21459
- const query = buildQuery({
21460
- include: input.include?.split(","),
21461
- filter,
21462
- page: { number: input.pageNumber, size: input.pageSize }
21463
- });
21464
- return apiGet(`/discounts${query}`);
21465
- }
21462
+ handler: listHandler("/discounts", { storeId: "store_id" })
21466
21463
  },
21467
21464
  {
21468
21465
  name: "ls_create_discount",
@@ -21478,19 +21475,19 @@ var discountTools = [
21478
21475
  storeId: external_exports.string().describe("The store ID to create the discount in"),
21479
21476
  name: external_exports.string().describe("Internal name for the discount"),
21480
21477
  code: external_exports.string().describe("The discount code customers will enter (e.g. 'SAVE20')"),
21481
- amount: external_exports.number().describe(
21478
+ amount: external_exports.number().int().min(1).describe(
21482
21479
  "Discount amount \u2014 in cents for 'fixed' type (e.g. 1000 = $10.00), or percentage for 'percent' type (e.g. 20 = 20%)"
21483
21480
  ),
21484
- amountType: external_exports.string().describe("Discount type: 'percent' or 'fixed'"),
21485
- duration: external_exports.string().optional().describe(
21481
+ amountType: external_exports.enum(["percent", "fixed"]).describe("Discount type: 'percent' or 'fixed'"),
21482
+ duration: external_exports.enum(["once", "repeating", "forever"]).optional().describe(
21486
21483
  "How long the discount applies: 'once' (first payment only), 'repeating' (for N months), or 'forever' (default)"
21487
21484
  ),
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)"),
21485
+ durationInMonths: external_exports.number().int().min(1).optional().describe("Number of months the discount applies (required when duration is 'repeating')"),
21486
+ maxRedemptions: external_exports.number().int().min(0).optional().describe("Maximum number of times this discount can be redeemed (0 = unlimited)"),
21490
21487
  startsAt: external_exports.string().optional().describe("When the discount becomes active (ISO 8601 format)"),
21491
21488
  expiresAt: external_exports.string().optional().describe("When the discount expires (ISO 8601 format)"),
21492
21489
  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)")
21490
+ variantIds: external_exports.array(external_exports.string()).optional().describe("Array of variant IDs this discount applies to (requires isLimitedToProducts: true)")
21494
21491
  }),
21495
21492
  handler: async (input) => {
21496
21493
  const attributes = {
@@ -21510,7 +21507,7 @@ var discountTools = [
21510
21507
  };
21511
21508
  if (input.variantIds?.length) {
21512
21509
  relationships.variants = {
21513
- data: input.variantIds.map((id) => ({ type: "variants", id: String(id) }))
21510
+ data: input.variantIds.map((id) => ({ type: "variants", id }))
21514
21511
  };
21515
21512
  }
21516
21513
  return apiPost("/discounts", {
@@ -21557,14 +21554,11 @@ var fileTools = [
21557
21554
  fileId: external_exports.string().describe("The file ID"),
21558
21555
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'variant')")
21559
21556
  }),
21560
- handler: async (input) => {
21561
- const query = buildQuery({ include: input.include?.split(",") });
21562
- return apiGet(`/files/${input.fileId}${query}`);
21563
- }
21557
+ handler: getHandler("/files", "fileId")
21564
21558
  },
21565
21559
  {
21566
21560
  name: "ls_list_files",
21567
- description: "List all files, optionally filtered by variant.",
21561
+ description: "List all files, optionally filtered by variant. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21568
21562
  annotations: {
21569
21563
  title: "List files",
21570
21564
  readOnlyHint: true,
@@ -21575,19 +21569,10 @@ var fileTools = [
21575
21569
  inputSchema: external_exports.object({
21576
21570
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21577
21571
  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)")
21572
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21573
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21580
21574
  }),
21581
- handler: async (input) => {
21582
- const filter = {};
21583
- if (input.variantId) filter.variant_id = input.variantId;
21584
- const query = buildQuery({
21585
- include: input.include?.split(","),
21586
- filter,
21587
- page: { number: input.pageNumber, size: input.pageSize }
21588
- });
21589
- return apiGet(`/files${query}`);
21590
- }
21575
+ handler: listHandler("/files", { variantId: "variant_id" })
21591
21576
  }
21592
21577
  ];
21593
21578
 
@@ -21607,14 +21592,11 @@ var licenseKeyInstanceTools = [
21607
21592
  licenseKeyInstanceId: external_exports.string().describe("The license key instance ID"),
21608
21593
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'license-key')")
21609
21594
  }),
21610
- handler: async (input) => {
21611
- const query = buildQuery({ include: input.include?.split(",") });
21612
- return apiGet(`/license-key-instances/${input.licenseKeyInstanceId}${query}`);
21613
- }
21595
+ handler: getHandler("/license-key-instances", "licenseKeyInstanceId")
21614
21596
  },
21615
21597
  {
21616
21598
  name: "ls_list_license_key_instances",
21617
- description: "List all license key instances (activations), optionally filtered by license key.",
21599
+ 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
21600
  annotations: {
21619
21601
  title: "List license key instances",
21620
21602
  readOnlyHint: true,
@@ -21625,19 +21607,10 @@ var licenseKeyInstanceTools = [
21625
21607
  inputSchema: external_exports.object({
21626
21608
  licenseKeyId: external_exports.string().optional().describe("Filter by license key ID"),
21627
21609
  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)")
21610
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21611
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21630
21612
  }),
21631
- handler: async (input) => {
21632
- const filter = {};
21633
- if (input.licenseKeyId) filter.license_key_id = input.licenseKeyId;
21634
- const query = buildQuery({
21635
- include: input.include?.split(","),
21636
- filter,
21637
- page: { number: input.pageNumber, size: input.pageSize }
21638
- });
21639
- return apiGet(`/license-key-instances${query}`);
21640
- }
21613
+ handler: listHandler("/license-key-instances", { licenseKeyId: "license_key_id" })
21641
21614
  }
21642
21615
  ];
21643
21616
 
@@ -21659,14 +21632,11 @@ var licenseKeyTools = [
21659
21632
  "Comma-separated related resources to include (e.g. 'store,customer,order,order-item,product,license-key-instances')"
21660
21633
  )
21661
21634
  }),
21662
- handler: async (input) => {
21663
- const query = buildQuery({ include: input.include?.split(",") });
21664
- return apiGet(`/license-keys/${input.licenseKeyId}${query}`);
21665
- }
21635
+ handler: getHandler("/license-keys", "licenseKeyId")
21666
21636
  },
21667
21637
  {
21668
21638
  name: "ls_list_license_keys",
21669
- description: "List all license keys, optionally filtered by store, order, or product.",
21639
+ 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
21640
  annotations: {
21671
21641
  title: "List license keys",
21672
21642
  readOnlyHint: true,
@@ -21682,22 +21652,15 @@ var licenseKeyTools = [
21682
21652
  include: external_exports.string().optional().describe(
21683
21653
  "Comma-separated related resources to include (e.g. 'store,customer,order,order-item,product,license-key-instances')"
21684
21654
  ),
21685
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21686
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21655
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21656
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21687
21657
  }),
21688
- handler: async (input) => {
21689
- const filter = {};
21690
- if (input.storeId) filter.store_id = input.storeId;
21691
- if (input.orderId) filter.order_id = input.orderId;
21692
- if (input.orderItemId) filter.order_item_id = input.orderItemId;
21693
- if (input.productId) filter.product_id = input.productId;
21694
- const query = buildQuery({
21695
- include: input.include?.split(","),
21696
- filter,
21697
- page: { number: input.pageNumber, size: input.pageSize }
21698
- });
21699
- return apiGet(`/license-keys${query}`);
21700
- }
21658
+ handler: listHandler("/license-keys", {
21659
+ storeId: "store_id",
21660
+ orderId: "order_id",
21661
+ orderItemId: "order_item_id",
21662
+ productId: "product_id"
21663
+ })
21701
21664
  },
21702
21665
  {
21703
21666
  name: "ls_update_license_key",
@@ -21711,7 +21674,7 @@ var licenseKeyTools = [
21711
21674
  },
21712
21675
  inputSchema: external_exports.object({
21713
21676
  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)"),
21677
+ activationLimit: external_exports.number().int().min(0).optional().describe("Maximum number of activations allowed (0 = unlimited)"),
21715
21678
  disabled: external_exports.boolean().optional().describe("Set to true to disable this license key"),
21716
21679
  expiresAt: external_exports.string().optional().describe("Expiry date (ISO 8601 format). Set to null to remove expiry.")
21717
21680
  }),
@@ -21770,7 +21733,7 @@ var licenseTools = [
21770
21733
  }),
21771
21734
  handler: async (input) => {
21772
21735
  const body = { license_key: input.licenseKey };
21773
- if (input.instanceId) body.instance_id = input.instanceId;
21736
+ if (input.instanceId !== void 0) body.instance_id = input.instanceId;
21774
21737
  return licenseRequest("/licenses/validate", body);
21775
21738
  }
21776
21739
  },
@@ -21813,14 +21776,11 @@ var orderItemTools = [
21813
21776
  orderItemId: external_exports.string().describe("The order item ID"),
21814
21777
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'order,product,variant')")
21815
21778
  }),
21816
- handler: async (input) => {
21817
- const query = buildQuery({ include: input.include?.split(",") });
21818
- return apiGet(`/order-items/${input.orderItemId}${query}`);
21819
- }
21779
+ handler: getHandler("/order-items", "orderItemId")
21820
21780
  },
21821
21781
  {
21822
21782
  name: "ls_list_order_items",
21823
- description: "List all order items, optionally filtered by order or product.",
21783
+ 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
21784
  annotations: {
21825
21785
  title: "List order items",
21826
21786
  readOnlyHint: true,
@@ -21833,21 +21793,10 @@ var orderItemTools = [
21833
21793
  productId: external_exports.string().optional().describe("Filter by product ID"),
21834
21794
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21835
21795
  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)")
21796
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21797
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21838
21798
  }),
21839
- handler: async (input) => {
21840
- const filter = {};
21841
- if (input.orderId) filter.order_id = input.orderId;
21842
- if (input.productId) filter.product_id = input.productId;
21843
- if (input.variantId) filter.variant_id = input.variantId;
21844
- const query = buildQuery({
21845
- include: input.include?.split(","),
21846
- filter,
21847
- page: { number: input.pageNumber, size: input.pageSize }
21848
- });
21849
- return apiGet(`/order-items${query}`);
21850
- }
21799
+ handler: listHandler("/order-items", { orderId: "order_id", productId: "product_id", variantId: "variant_id" })
21851
21800
  }
21852
21801
  ];
21853
21802
 
@@ -21869,14 +21818,11 @@ var orderTools = [
21869
21818
  "Comma-separated related resources to include (e.g. 'store,customer,order-items,subscriptions,license-keys,discount-redemptions')"
21870
21819
  )
21871
21820
  }),
21872
- handler: async (input) => {
21873
- const query = buildQuery({ include: input.include?.split(",") });
21874
- return apiGet(`/orders/${input.orderId}${query}`);
21875
- }
21821
+ handler: getHandler("/orders", "orderId")
21876
21822
  },
21877
21823
  {
21878
21824
  name: "ls_list_orders",
21879
- description: "List all orders, optionally filtered by store, email, or user email.",
21825
+ 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
21826
  annotations: {
21881
21827
  title: "List orders",
21882
21828
  readOnlyHint: true,
@@ -21890,20 +21836,10 @@ var orderTools = [
21890
21836
  include: external_exports.string().optional().describe(
21891
21837
  "Comma-separated related resources to include (e.g. 'store,customer,order-items,subscriptions,license-keys,discount-redemptions')"
21892
21838
  ),
21893
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
21894
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
21839
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21840
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21895
21841
  }),
21896
- handler: async (input) => {
21897
- const filter = {};
21898
- if (input.storeId) filter.store_id = input.storeId;
21899
- if (input.userEmail) filter.user_email = input.userEmail;
21900
- const query = buildQuery({
21901
- include: input.include?.split(","),
21902
- filter,
21903
- page: { number: input.pageNumber, size: input.pageSize }
21904
- });
21905
- return apiGet(`/orders${query}`);
21906
- }
21842
+ handler: listHandler("/orders", { storeId: "store_id", userEmail: "user_email" })
21907
21843
  },
21908
21844
  {
21909
21845
  name: "ls_generate_order_invoice",
@@ -21923,18 +21859,21 @@ var orderTools = [
21923
21859
  state: external_exports.string().optional().describe("Customer state/region"),
21924
21860
  zipCode: external_exports.string().optional().describe("Customer ZIP/postal code"),
21925
21861
  country: external_exports.string().optional().describe("Customer country"),
21926
- notes: external_exports.string().optional().describe("Additional notes to include on the invoice")
21862
+ notes: external_exports.string().optional().describe("Additional notes to include on the invoice"),
21863
+ locale: external_exports.string().optional().describe("Invoice language locale (e.g. 'en', 'fr', 'de')")
21927
21864
  }),
21928
21865
  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);
21866
+ const params = new URLSearchParams();
21867
+ if (input.name !== void 0) params.set("name", input.name);
21868
+ if (input.address !== void 0) params.set("address", input.address);
21869
+ if (input.city !== void 0) params.set("city", input.city);
21870
+ if (input.state !== void 0) params.set("state", input.state);
21871
+ if (input.zipCode !== void 0) params.set("zip_code", input.zipCode);
21872
+ if (input.country !== void 0) params.set("country", input.country);
21873
+ if (input.notes !== void 0) params.set("notes", input.notes);
21874
+ if (input.locale !== void 0) params.set("locale", input.locale);
21875
+ const qs = params.toString();
21876
+ return apiPost(`/orders/${input.orderId}/generate-invoice${qs ? `?${qs}` : ""}`);
21938
21877
  }
21939
21878
  },
21940
21879
  {
@@ -21949,7 +21888,7 @@ var orderTools = [
21949
21888
  },
21950
21889
  inputSchema: external_exports.object({
21951
21890
  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)")
21891
+ amount: external_exports.number().int().min(1).describe("Refund amount in cents (e.g. 1000 = $10.00)")
21953
21892
  }),
21954
21893
  handler: async (input) => {
21955
21894
  return apiPost(`/orders/${input.orderId}/refund`, {
@@ -21975,14 +21914,11 @@ var priceTools = [
21975
21914
  priceId: external_exports.string().describe("The price ID"),
21976
21915
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'variant')")
21977
21916
  }),
21978
- handler: async (input) => {
21979
- const query = buildQuery({ include: input.include?.split(",") });
21980
- return apiGet(`/prices/${input.priceId}${query}`);
21981
- }
21917
+ handler: getHandler("/prices", "priceId")
21982
21918
  },
21983
21919
  {
21984
21920
  name: "ls_list_prices",
21985
- description: "List all prices, optionally filtered by variant.",
21921
+ description: "List all prices, optionally filtered by variant. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21986
21922
  annotations: {
21987
21923
  title: "List prices",
21988
21924
  readOnlyHint: true,
@@ -21993,19 +21929,10 @@ var priceTools = [
21993
21929
  inputSchema: external_exports.object({
21994
21930
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
21995
21931
  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)")
21932
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21933
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21998
21934
  }),
21999
- handler: async (input) => {
22000
- const filter = {};
22001
- if (input.variantId) filter.variant_id = input.variantId;
22002
- const query = buildQuery({
22003
- include: input.include?.split(","),
22004
- filter,
22005
- page: { number: input.pageNumber, size: input.pageSize }
22006
- });
22007
- return apiGet(`/prices${query}`);
22008
- }
21935
+ handler: listHandler("/prices", { variantId: "variant_id" })
22009
21936
  }
22010
21937
  ];
22011
21938
 
@@ -22025,14 +21952,11 @@ var productTools = [
22025
21952
  productId: external_exports.string().describe("The product ID"),
22026
21953
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,variants')")
22027
21954
  }),
22028
- handler: async (input) => {
22029
- const query = buildQuery({ include: input.include?.split(",") });
22030
- return apiGet(`/products/${input.productId}${query}`);
22031
- }
21955
+ handler: getHandler("/products", "productId")
22032
21956
  },
22033
21957
  {
22034
21958
  name: "ls_list_products",
22035
- description: "List all products, optionally filtered by store.",
21959
+ description: "List all products, optionally filtered by store. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22036
21960
  annotations: {
22037
21961
  title: "List products",
22038
21962
  readOnlyHint: true,
@@ -22043,19 +21967,10 @@ var productTools = [
22043
21967
  inputSchema: external_exports.object({
22044
21968
  storeId: external_exports.string().optional().describe("Filter by store ID"),
22045
21969
  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)")
21970
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21971
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22048
21972
  }),
22049
- handler: async (input) => {
22050
- const filter = {};
22051
- if (input.storeId) filter.store_id = input.storeId;
22052
- const query = buildQuery({
22053
- include: input.include?.split(","),
22054
- filter,
22055
- page: { number: input.pageNumber, size: input.pageSize }
22056
- });
22057
- return apiGet(`/products${query}`);
22058
- }
21973
+ handler: listHandler("/products", { storeId: "store_id" })
22059
21974
  }
22060
21975
  ];
22061
21976
 
@@ -22077,14 +21992,11 @@ var storeTools = [
22077
21992
  "Comma-separated related resources to include (e.g. 'products,discounts,license-keys,subscriptions,webhooks')"
22078
21993
  )
22079
21994
  }),
22080
- handler: async (input) => {
22081
- const query = buildQuery({ include: input.include?.split(",") });
22082
- return apiGet(`/stores/${input.storeId}${query}`);
22083
- }
21995
+ handler: getHandler("/stores", "storeId")
22084
21996
  },
22085
21997
  {
22086
21998
  name: "ls_list_stores",
22087
- description: "List all stores for the authenticated user.",
21999
+ description: "List all stores for the authenticated user. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22088
22000
  annotations: {
22089
22001
  title: "List stores",
22090
22002
  readOnlyHint: true,
@@ -22096,16 +22008,10 @@ var storeTools = [
22096
22008
  include: external_exports.string().optional().describe(
22097
22009
  "Comma-separated related resources to include (e.g. 'products,discounts,license-keys,subscriptions,webhooks')"
22098
22010
  ),
22099
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22100
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22011
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22012
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22101
22013
  }),
22102
- handler: async (input) => {
22103
- const query = buildQuery({
22104
- include: input.include?.split(","),
22105
- page: { number: input.pageNumber, size: input.pageSize }
22106
- });
22107
- return apiGet(`/stores${query}`);
22108
- }
22014
+ handler: listHandler("/stores")
22109
22015
  }
22110
22016
  ];
22111
22017
 
@@ -22125,14 +22031,11 @@ var subscriptionInvoiceTools = [
22125
22031
  subscriptionInvoiceId: external_exports.string().describe("The subscription invoice ID"),
22126
22032
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,subscription')")
22127
22033
  }),
22128
- handler: async (input) => {
22129
- const query = buildQuery({ include: input.include?.split(",") });
22130
- return apiGet(`/subscription-invoices/${input.subscriptionInvoiceId}${query}`);
22131
- }
22034
+ handler: getHandler("/subscription-invoices", "subscriptionInvoiceId")
22132
22035
  },
22133
22036
  {
22134
22037
  name: "ls_list_subscription_invoices",
22135
- description: "List all subscription invoices, optionally filtered by store, subscription, or status.",
22038
+ 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
22039
  annotations: {
22137
22040
  title: "List subscription invoices",
22138
22041
  readOnlyHint: true,
@@ -22143,25 +22046,18 @@ var subscriptionInvoiceTools = [
22143
22046
  inputSchema: external_exports.object({
22144
22047
  storeId: external_exports.string().optional().describe("Filter by store ID"),
22145
22048
  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')"),
22049
+ status: external_exports.enum(["pending", "paid", "void", "refunded"]).optional().describe("Filter by invoice status"),
22050
+ refunded: external_exports.boolean().optional().describe("Filter by refunded status"),
22148
22051
  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)")
22052
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22053
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22151
22054
  }),
22152
- handler: async (input) => {
22153
- const filter = {};
22154
- if (input.storeId) filter.store_id = input.storeId;
22155
- if (input.subscriptionId) filter.subscription_id = input.subscriptionId;
22156
- if (input.status) filter.status = input.status;
22157
- if (input.refunded) filter.refunded = input.refunded;
22158
- const query = buildQuery({
22159
- include: input.include?.split(","),
22160
- filter,
22161
- page: { number: input.pageNumber, size: input.pageSize }
22162
- });
22163
- return apiGet(`/subscription-invoices${query}`);
22164
- }
22055
+ handler: listHandler("/subscription-invoices", {
22056
+ storeId: "store_id",
22057
+ subscriptionId: "subscription_id",
22058
+ status: "status",
22059
+ refunded: "refunded"
22060
+ })
22165
22061
  },
22166
22062
  {
22167
22063
  name: "ls_generate_subscription_invoice",
@@ -22181,18 +22077,21 @@ var subscriptionInvoiceTools = [
22181
22077
  state: external_exports.string().optional().describe("Customer state/region"),
22182
22078
  zipCode: external_exports.string().optional().describe("Customer ZIP/postal code"),
22183
22079
  country: external_exports.string().optional().describe("Customer country"),
22184
- notes: external_exports.string().optional().describe("Additional notes to include on the invoice")
22080
+ notes: external_exports.string().optional().describe("Additional notes to include on the invoice"),
22081
+ locale: external_exports.string().optional().describe("Invoice language locale (e.g. 'en', 'fr', 'de')")
22185
22082
  }),
22186
22083
  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);
22084
+ const params = new URLSearchParams();
22085
+ if (input.name !== void 0) params.set("name", input.name);
22086
+ if (input.address !== void 0) params.set("address", input.address);
22087
+ if (input.city !== void 0) params.set("city", input.city);
22088
+ if (input.state !== void 0) params.set("state", input.state);
22089
+ if (input.zipCode !== void 0) params.set("zip_code", input.zipCode);
22090
+ if (input.country !== void 0) params.set("country", input.country);
22091
+ if (input.notes !== void 0) params.set("notes", input.notes);
22092
+ if (input.locale !== void 0) params.set("locale", input.locale);
22093
+ const qs = params.toString();
22094
+ return apiPost(`/subscription-invoices/${input.subscriptionInvoiceId}/generate-invoice${qs ? `?${qs}` : ""}`);
22196
22095
  }
22197
22096
  },
22198
22097
  {
@@ -22207,7 +22106,7 @@ var subscriptionInvoiceTools = [
22207
22106
  },
22208
22107
  inputSchema: external_exports.object({
22209
22108
  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)")
22109
+ amount: external_exports.number().int().min(1).describe("Refund amount in cents (e.g. 1000 = $10.00)")
22211
22110
  }),
22212
22111
  handler: async (input) => {
22213
22112
  return apiPost(`/subscription-invoices/${input.subscriptionInvoiceId}/refund`, {
@@ -22237,14 +22136,11 @@ var subscriptionItemTools = [
22237
22136
  subscriptionItemId: external_exports.string().describe("The subscription item ID"),
22238
22137
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'subscription,price,usage-records')")
22239
22138
  }),
22240
- handler: async (input) => {
22241
- const query = buildQuery({ include: input.include?.split(",") });
22242
- return apiGet(`/subscription-items/${input.subscriptionItemId}${query}`);
22243
- }
22139
+ handler: getHandler("/subscription-items", "subscriptionItemId")
22244
22140
  },
22245
22141
  {
22246
22142
  name: "ls_list_subscription_items",
22247
- description: "List all subscription items, optionally filtered by subscription or price.",
22143
+ 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
22144
  annotations: {
22249
22145
  title: "List subscription items",
22250
22146
  readOnlyHint: true,
@@ -22256,20 +22152,10 @@ var subscriptionItemTools = [
22256
22152
  subscriptionId: external_exports.string().optional().describe("Filter by subscription ID"),
22257
22153
  priceId: external_exports.string().optional().describe("Filter by price ID"),
22258
22154
  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)")
22155
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22156
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22261
22157
  }),
22262
- handler: async (input) => {
22263
- const filter = {};
22264
- if (input.subscriptionId) filter.subscription_id = input.subscriptionId;
22265
- if (input.priceId) filter.price_id = input.priceId;
22266
- const query = buildQuery({
22267
- include: input.include?.split(","),
22268
- filter,
22269
- page: { number: input.pageNumber, size: input.pageSize }
22270
- });
22271
- return apiGet(`/subscription-items${query}`);
22272
- }
22158
+ handler: listHandler("/subscription-items", { subscriptionId: "subscription_id", priceId: "price_id" })
22273
22159
  },
22274
22160
  {
22275
22161
  name: "ls_update_subscription_item",
@@ -22283,7 +22169,7 @@ var subscriptionItemTools = [
22283
22169
  },
22284
22170
  inputSchema: external_exports.object({
22285
22171
  subscriptionItemId: external_exports.string().describe("The subscription item ID to update"),
22286
- quantity: external_exports.number().describe("New quantity for the subscription item")
22172
+ quantity: external_exports.number().int().min(1).describe("New quantity for the subscription item")
22287
22173
  }),
22288
22174
  handler: async (input) => {
22289
22175
  return apiPatch(`/subscription-items/${input.subscriptionItemId}`, {
@@ -22332,14 +22218,11 @@ var subscriptionTools = [
22332
22218
  "Comma-separated related resources to include (e.g. 'store,customer,order,order-item,product,variant,subscription-items,subscription-invoices')"
22333
22219
  )
22334
22220
  }),
22335
- handler: async (input) => {
22336
- const query = buildQuery({ include: input.include?.split(",") });
22337
- return apiGet(`/subscriptions/${input.subscriptionId}${query}`);
22338
- }
22221
+ handler: getHandler("/subscriptions", "subscriptionId")
22339
22222
  },
22340
22223
  {
22341
22224
  name: "ls_list_subscriptions",
22342
- description: "List all subscriptions, optionally filtered by store, order, product, variant, or status.",
22225
+ 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
22226
  annotations: {
22344
22227
  title: "List subscriptions",
22345
22228
  readOnlyHint: true,
@@ -22354,29 +22237,22 @@ var subscriptionTools = [
22354
22237
  productId: external_exports.string().optional().describe("Filter by product ID"),
22355
22238
  variantId: external_exports.string().optional().describe("Filter by variant ID"),
22356
22239
  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)"),
22240
+ status: external_exports.enum(["on_trial", "active", "paused", "past_due", "unpaid", "cancelled", "expired"]).optional().describe("Filter by subscription status"),
22358
22241
  include: external_exports.string().optional().describe(
22359
22242
  "Comma-separated related resources to include (e.g. 'store,customer,order,order-item,product,variant')"
22360
22243
  ),
22361
- pageNumber: external_exports.number().optional().describe("Page number (1-indexed)"),
22362
- pageSize: external_exports.number().optional().describe("Results per page (1-100)")
22244
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22245
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22363
22246
  }),
22364
- handler: async (input) => {
22365
- const filter = {};
22366
- if (input.storeId) filter.store_id = input.storeId;
22367
- if (input.orderId) filter.order_id = input.orderId;
22368
- if (input.orderItemId) filter.order_item_id = input.orderItemId;
22369
- if (input.productId) filter.product_id = input.productId;
22370
- if (input.variantId) filter.variant_id = input.variantId;
22371
- if (input.userEmail) filter.user_email = input.userEmail;
22372
- if (input.status) filter.status = input.status;
22373
- const query = buildQuery({
22374
- include: input.include?.split(","),
22375
- filter,
22376
- page: { number: input.pageNumber, size: input.pageSize }
22377
- });
22378
- return apiGet(`/subscriptions${query}`);
22379
- }
22247
+ handler: listHandler("/subscriptions", {
22248
+ storeId: "store_id",
22249
+ orderId: "order_id",
22250
+ orderItemId: "order_item_id",
22251
+ productId: "product_id",
22252
+ variantId: "variant_id",
22253
+ userEmail: "user_email",
22254
+ status: "status"
22255
+ })
22380
22256
  },
22381
22257
  {
22382
22258
  name: "ls_update_subscription",
@@ -22390,18 +22266,20 @@ var subscriptionTools = [
22390
22266
  },
22391
22267
  inputSchema: external_exports.object({
22392
22268
  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"),
22269
+ variantId: external_exports.string().optional().describe("New variant ID for plan switching"),
22270
+ pause: external_exports.enum(["void", "free", "resume"]).optional().describe("Pause mode: 'void' (pause, skip billing), 'free' (pause, keep access free), or 'resume' to unpause"),
22271
+ cancelled: external_exports.literal(false).optional().describe(
22272
+ "Set to false to un-cancel a subscription before it expires. To cancel, use ls_cancel_subscription instead."
22273
+ ),
22274
+ billingAnchor: external_exports.number().int().min(1).max(28).optional().describe("Day of month (1-28) to anchor billing to"),
22397
22275
  invoiceImmediately: external_exports.boolean().optional().describe("If true, invoice immediately when updating (default false for prorated changes)"),
22398
22276
  disableProrations: external_exports.boolean().optional().describe("If true, disable prorations when changing plans"),
22399
22277
  trialEndsAt: external_exports.string().optional().describe("Set trial end date (ISO 8601 format). Set to null to end trial immediately.")
22400
22278
  }),
22401
22279
  handler: async (input) => {
22402
22280
  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 };
22281
+ if (input.variantId !== void 0) attributes.variant_id = Number(input.variantId);
22282
+ if (input.pause !== void 0) attributes.pause = input.pause === "resume" ? null : { mode: input.pause };
22405
22283
  if (input.cancelled !== void 0) attributes.cancelled = input.cancelled;
22406
22284
  if (input.billingAnchor !== void 0) attributes.billing_anchor = input.billingAnchor;
22407
22285
  if (input.invoiceImmediately !== void 0) attributes.invoice_immediately = input.invoiceImmediately;
@@ -22451,14 +22329,11 @@ var usageRecordTools = [
22451
22329
  usageRecordId: external_exports.string().describe("The usage record ID"),
22452
22330
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'subscription-item')")
22453
22331
  }),
22454
- handler: async (input) => {
22455
- const query = buildQuery({ include: input.include?.split(",") });
22456
- return apiGet(`/usage-records/${input.usageRecordId}${query}`);
22457
- }
22332
+ handler: getHandler("/usage-records", "usageRecordId")
22458
22333
  },
22459
22334
  {
22460
22335
  name: "ls_list_usage_records",
22461
- description: "List all usage records, optionally filtered by subscription item.",
22336
+ 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
22337
  annotations: {
22463
22338
  title: "List usage records",
22464
22339
  readOnlyHint: true,
@@ -22469,19 +22344,10 @@ var usageRecordTools = [
22469
22344
  inputSchema: external_exports.object({
22470
22345
  subscriptionItemId: external_exports.string().optional().describe("Filter by subscription item ID"),
22471
22346
  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)")
22347
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22348
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22474
22349
  }),
22475
- handler: async (input) => {
22476
- const filter = {};
22477
- if (input.subscriptionItemId) filter.subscription_item_id = input.subscriptionItemId;
22478
- const query = buildQuery({
22479
- include: input.include?.split(","),
22480
- filter,
22481
- page: { number: input.pageNumber, size: input.pageSize }
22482
- });
22483
- return apiGet(`/usage-records${query}`);
22484
- }
22350
+ handler: listHandler("/usage-records", { subscriptionItemId: "subscription_item_id" })
22485
22351
  },
22486
22352
  {
22487
22353
  name: "ls_create_usage_record",
@@ -22495,14 +22361,14 @@ var usageRecordTools = [
22495
22361
  },
22496
22362
  inputSchema: external_exports.object({
22497
22363
  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)")
22364
+ quantity: external_exports.number().int().min(0).describe("The usage quantity to report"),
22365
+ action: external_exports.enum(["increment", "set"]).optional().describe("How to apply the quantity: 'increment' (add to current, default) or 'set' (replace current)")
22500
22366
  }),
22501
22367
  handler: async (input) => {
22502
22368
  const attributes = {
22503
22369
  quantity: input.quantity
22504
22370
  };
22505
- if (input.action) attributes.action = input.action;
22371
+ if (input.action !== void 0) attributes.action = input.action;
22506
22372
  return apiPost("/usage-records", {
22507
22373
  data: {
22508
22374
  type: "usage-records",
@@ -22553,14 +22419,11 @@ var variantTools = [
22553
22419
  variantId: external_exports.string().describe("The variant ID"),
22554
22420
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'product,files')")
22555
22421
  }),
22556
- handler: async (input) => {
22557
- const query = buildQuery({ include: input.include?.split(",") });
22558
- return apiGet(`/variants/${input.variantId}${query}`);
22559
- }
22422
+ handler: getHandler("/variants", "variantId")
22560
22423
  },
22561
22424
  {
22562
22425
  name: "ls_list_variants",
22563
- description: "List all variants, optionally filtered by product.",
22426
+ description: "List all variants, optionally filtered by product. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22564
22427
  annotations: {
22565
22428
  title: "List variants",
22566
22429
  readOnlyHint: true,
@@ -22571,19 +22434,10 @@ var variantTools = [
22571
22434
  inputSchema: external_exports.object({
22572
22435
  productId: external_exports.string().optional().describe("Filter by product ID"),
22573
22436
  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)")
22437
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22438
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22576
22439
  }),
22577
- handler: async (input) => {
22578
- const filter = {};
22579
- if (input.productId) filter.product_id = input.productId;
22580
- const query = buildQuery({
22581
- include: input.include?.split(","),
22582
- filter,
22583
- page: { number: input.pageNumber, size: input.pageSize }
22584
- });
22585
- return apiGet(`/variants${query}`);
22586
- }
22440
+ handler: listHandler("/variants", { productId: "product_id" })
22587
22441
  }
22588
22442
  ];
22589
22443
 
@@ -22603,14 +22457,11 @@ var webhookTools = [
22603
22457
  webhookId: external_exports.string().describe("The webhook ID"),
22604
22458
  include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store')")
22605
22459
  }),
22606
- handler: async (input) => {
22607
- const query = buildQuery({ include: input.include?.split(",") });
22608
- return apiGet(`/webhooks/${input.webhookId}${query}`);
22609
- }
22460
+ handler: getHandler("/webhooks", "webhookId")
22610
22461
  },
22611
22462
  {
22612
22463
  name: "ls_list_webhooks",
22613
- description: "List all webhooks, optionally filtered by store.",
22464
+ description: "List all webhooks, optionally filtered by store. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
22614
22465
  annotations: {
22615
22466
  title: "List webhooks",
22616
22467
  readOnlyHint: true,
@@ -22621,19 +22472,10 @@ var webhookTools = [
22621
22472
  inputSchema: external_exports.object({
22622
22473
  storeId: external_exports.string().optional().describe("Filter by store ID"),
22623
22474
  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)")
22475
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
22476
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
22626
22477
  }),
22627
- handler: async (input) => {
22628
- const filter = {};
22629
- if (input.storeId) filter.store_id = input.storeId;
22630
- const query = buildQuery({
22631
- include: input.include?.split(","),
22632
- filter,
22633
- page: { number: input.pageNumber, size: input.pageSize }
22634
- });
22635
- return apiGet(`/webhooks${query}`);
22636
- }
22478
+ handler: listHandler("/webhooks", { storeId: "store_id" })
22637
22479
  },
22638
22480
  {
22639
22481
  name: "ls_create_webhook",
@@ -22651,7 +22493,7 @@ var webhookTools = [
22651
22493
  events: external_exports.array(external_exports.string()).describe(
22652
22494
  "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
22495
  ),
22654
- secret: external_exports.string().describe("A signing secret for verifying webhook payloads (min 6, max 40 characters)")
22496
+ secret: external_exports.string().min(6).max(40).describe("A signing secret for verifying webhook payloads")
22655
22497
  }),
22656
22498
  handler: async (input) => {
22657
22499
  return apiPost("/webhooks", {
@@ -22719,7 +22561,7 @@ var webhookTools = [
22719
22561
  ];
22720
22562
 
22721
22563
  // src/index.ts
22722
- var version2 = true ? "0.1.1" : (await null).createRequire(import.meta.url)("../package.json").version;
22564
+ var version2 = true ? "0.2.1" : (await null).createRequire(import.meta.url)("../package.json").version;
22723
22565
  var subcommand = process.argv[2];
22724
22566
  if (subcommand === "version" || subcommand === "--version") {
22725
22567
  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.1",
4
4
  "description": "LemonSqueezy MCP server for managing your store from AI assistants",
5
5
  "license": "MIT",
6
6
  "author": "YawLabs <contact@yaw.sh>",
@@ -34,7 +34,7 @@
34
34
  "test:ci": "npm run test",
35
35
  "lint": "biome check src/",
36
36
  "lint:fix": "biome check --write src/",
37
- "prepublishOnly": "npm run build"
37
+ "prepublishOnly": "npm run build && node --test dist/**/*.test.js"
38
38
  },
39
39
  "dependencies": {},
40
40
  "devDependencies": {