@yawlabs/lemonsqueezy-mcp 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +64 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -21013,6 +21013,26 @@ var StdioServerTransport = class {
21013
21013
  // src/api.ts
21014
21014
  var BASE_URL = "https://api.lemonsqueezy.com/v1";
21015
21015
  var REQUEST_TIMEOUT_MS = 3e4;
21016
+ var DEFAULT_RETRY_WAIT_MS = 1e3;
21017
+ var MAX_RETRY_WAIT_MS = 3e4;
21018
+ function parseRetryAfterMs(header) {
21019
+ if (!header) return DEFAULT_RETRY_WAIT_MS;
21020
+ const trimmed = header.trim();
21021
+ const seconds = Number(trimmed);
21022
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
21023
+ const dateMs = Date.parse(trimmed);
21024
+ if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
21025
+ return DEFAULT_RETRY_WAIT_MS;
21026
+ }
21027
+ async function fetchWithRetry(url, init) {
21028
+ const makeCall = () => fetch(url, { ...init, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
21029
+ const res = await makeCall();
21030
+ if (res.status !== 429) return res;
21031
+ const waitMs = parseRetryAfterMs(res.headers.get("retry-after"));
21032
+ if (waitMs > MAX_RETRY_WAIT_MS) return res;
21033
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
21034
+ return makeCall();
21035
+ }
21016
21036
  function getApiKey() {
21017
21037
  const key = process.env.LEMONSQUEEZY_API_KEY;
21018
21038
  if (!key) {
@@ -21057,12 +21077,7 @@ async function apiRequest(method, path, body) {
21057
21077
  const url = path.startsWith("http") ? path : `${BASE_URL}${path}`;
21058
21078
  let res;
21059
21079
  try {
21060
- res = await fetch(url, {
21061
- method,
21062
- headers,
21063
- body: fetchBody,
21064
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21065
- });
21080
+ res = await fetchWithRetry(url, { method, headers, body: fetchBody });
21066
21081
  } catch (err) {
21067
21082
  if (err instanceof Error && err.name === "TimeoutError") {
21068
21083
  return { ok: false, status: 0, error: `Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s` };
@@ -21088,14 +21103,13 @@ async function licenseRequest(path, body) {
21088
21103
  const url = `${BASE_URL}${path}`;
21089
21104
  let res;
21090
21105
  try {
21091
- res = await fetch(url, {
21106
+ res = await fetchWithRetry(url, {
21092
21107
  method: "POST",
21093
21108
  headers: {
21094
21109
  Accept: "application/json",
21095
21110
  "Content-Type": "application/x-www-form-urlencoded"
21096
21111
  },
21097
- body: new URLSearchParams(body),
21098
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21112
+ body: new URLSearchParams(body)
21099
21113
  });
21100
21114
  } catch (err) {
21101
21115
  if (err instanceof Error && err.name === "TimeoutError") {
@@ -21154,6 +21168,44 @@ async function apiDelete(path) {
21154
21168
  return apiRequest("DELETE", path);
21155
21169
  }
21156
21170
 
21171
+ // src/tools/affiliates.ts
21172
+ var affiliateTools = [
21173
+ {
21174
+ name: "ls_get_affiliate",
21175
+ description: "Get a specific affiliate by ID, including commission rate, status, and earnings.",
21176
+ annotations: {
21177
+ title: "Get affiliate",
21178
+ readOnlyHint: true,
21179
+ destructiveHint: false,
21180
+ idempotentHint: true,
21181
+ openWorldHint: true
21182
+ },
21183
+ inputSchema: external_exports.object({
21184
+ affiliateId: external_exports.string().describe("The affiliate ID"),
21185
+ include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,user')")
21186
+ }),
21187
+ handler: getHandler("/affiliates", "affiliateId")
21188
+ },
21189
+ {
21190
+ name: "ls_list_affiliates",
21191
+ description: "List all affiliates for the authenticated user's stores, optionally filtered by user email. Results are paginated \u2014 check meta.page in the response for currentPage, lastPage, and total.",
21192
+ annotations: {
21193
+ title: "List affiliates",
21194
+ readOnlyHint: true,
21195
+ destructiveHint: false,
21196
+ idempotentHint: true,
21197
+ openWorldHint: true
21198
+ },
21199
+ inputSchema: external_exports.object({
21200
+ userEmail: external_exports.string().email().optional().describe("Filter by affiliate's user email"),
21201
+ include: external_exports.string().optional().describe("Comma-separated related resources to include (e.g. 'store,user')"),
21202
+ pageNumber: external_exports.number().int().min(1).optional().describe("Page number (1-indexed)"),
21203
+ pageSize: external_exports.number().int().min(1).max(100).optional().describe("Results per page (1-100)")
21204
+ }),
21205
+ handler: listHandler("/affiliates", { userEmail: "user_email" })
21206
+ }
21207
+ ];
21208
+
21157
21209
  // src/tools/checkouts.ts
21158
21210
  var checkoutTools = [
21159
21211
  {
@@ -22561,7 +22613,7 @@ var webhookTools = [
22561
22613
  ];
22562
22614
 
22563
22615
  // src/index.ts
22564
- var version2 = true ? "0.2.1" : (await null).createRequire(import.meta.url)("../package.json").version;
22616
+ var version2 = true ? "0.3.0" : (await null).createRequire(import.meta.url)("../package.json").version;
22565
22617
  var subcommand = process.argv[2];
22566
22618
  if (subcommand === "version" || subcommand === "--version") {
22567
22619
  console.log(version2);
@@ -22587,7 +22639,8 @@ var allTools = [
22587
22639
  ...licenseKeyInstanceTools,
22588
22640
  ...checkoutTools,
22589
22641
  ...webhookTools,
22590
- ...licenseTools
22642
+ ...licenseTools,
22643
+ ...affiliateTools
22591
22644
  ];
22592
22645
  var server = new McpServer({
22593
22646
  name: "@yawlabs/lemonsqueezy-mcp",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/lemonsqueezy-mcp",
3
- "version": "0.2.1",
3
+ "version": "0.3.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>",