@yawlabs/lemonsqueezy-mcp 0.14.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -1
- package/LICENSE +21 -21
- package/README.md +429 -410
- package/bin/lemonsqueezy-mcp.mjs +667 -665
- package/dist/index.js +156 -98
- package/package.json +77 -77
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.0.1] — 2026-09-29
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **`release.sh` reads npm's per-version document and retries the MCP Registry publish.** The "is this version on npm?" checks (the pre-flight token gate, step 5's already-published skip and the step 8 check) now ask `https://registry.npmjs.org/@yawlabs%2Flemonsqueezy-mcp/<version>` with `curl` instead of `npm view`, whose whole-package document Cloudflare's edge can serve stale for up to 5 minutes after a publish. The step 7 propagation wait already curled that URL; it now goes through the same check, so each request is capped at 20 s and only a 200 counts. Step 5 treats npm's E403 "cannot publish over the previously published versions" as already published rather than as a token error, so re-running straight after a failed later step no longer dies there. Step 7 makes up to 4 attempts at `mcp-publisher publish`, 30, 60 and 90 s apart, but only when the registry says it cannot see the version on npm yet, calls the failure transient, or answers HTTP 429, 502, 503 or 504 itself (with a fresh registry login before each retry); a duplicate version counts as done, and any other failure still stops at once.
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
- **The README's Add to Yaw MCP button now sits directly under the title, and the follow badge links to @YawLabs.** The one-click install button and its one-line caption moved above the one-paragraph description, so they are the first thing under the name on npm and GitHub, and the X badge at the bottom points at [@YawLabs](https://x.com/YawLabs) instead of @TokenLimitNews. npm shows the README from the published package, which is why it takes a release to carry this there; the package's code is unchanged from 1.0.0.
|
|
13
|
+
|
|
14
|
+
## [1.0.0] — 2026-09-18
|
|
15
|
+
|
|
16
|
+
**1.0.0 locks the public surface.** [SEMVER.md](./SEMVER.md) now spells out what that surface is: tool names and input fields, MCP annotations, the authority class names and each tool's class, which calls count as destructive, the documented env vars, the `lemonsqueezy://audit-log` resource, and the fields the server adds to responses. From here on its MAJOR / MINOR / PATCH rules apply strictly. `src/tools/tools.test.ts` pins the `destructiveHint: true` set, the `isDestructive`-predicate set, the `readOnlyHint: false` set and the full tool-to-class map, so a change to any of them fails `npm test` until it is made deliberately. The changes marked **Breaking** below were made now, before the lock, because each would need a major version afterwards. Tracked in #2.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Breaking: `ls_deactivate_license` is now destructive (`destructiveHint: true`)** (#40). It revokes an instance's access on every call, whatever the input. `LEMONSQUEEZY_DESTRUCTIVE_RATE_LIMIT` now counts it (`0` blocks it). Its calls are tagged `audit: true`, logged at `LEMONSQUEEZY_LOG=audit` even when they succeed, and recorded in `lemonsqueezy://audit-log`, with the license key masked (see Security). MCP clients that gate destructive tools will now ask before calling it. It stays in class `key`. `ls_activate_license` (additive) and `ls_validate_license` (read-only) are unchanged.
|
|
21
|
+
- **Breaking: the four input-dependent update tools now declare `destructiveHint: true`**: `ls_update_customer`, `ls_update_subscription`, `ls_update_license_key` and `ls_update_webhook`. Each can archive, pause, switch plan, disable or rotate a secret, and MCP defines `false` as "only additive updates". They keep their `isDestructive` predicates, and the server still decides per call from those, so the destructive rate limit and the audit log behave exactly as before for these four. What changes is the static hint MCP clients see, so they may now prompt for confirmation on these tools.
|
|
22
|
+
- **Breaking: `ls_create_usage_record` moves from authority class `mutate` to `recurring`.** Usage reports feed the metered bill, and `mutate` is documented as non-money, while `recurring` already holds the seat-quantity sibling `ls_update_subscription_item`. `LEMONSQUEEZY_DISABLE_CLASSES` lists that include `recurring` now block usage reporting, and lists with only `mutate` no longer do. `recurring:N` budgets in `LEMONSQUEEZY_RATE_LIMIT_PER_CLASS` now count usage reports, so raise yours if an automated metering agent shares it.
|
|
23
|
+
- **`ls_update_subscription` counts more calls as destructive:** any `billingAnchor`, `invoiceImmediately: true`, or any `trialEndsAt` (a date or `null`), on top of the existing pause (`void` / `free`) and plan switch (`variantId`). LemonSqueezy charges immediately on `invoice_immediately`, and a new billing anchor bills a prorated amount, so these are not "billing-neutral" as the old description said. `pause: "resume"`, `cancelled: false`, `invoiceImmediately: false` and `disableProrations` stay non-destructive.
|
|
24
|
+
- **`ls_update_license_key` counts any `expiresAt` change as destructive**, as it already did for any `activationLimit` change: the server cannot tell a shortened expiry from an extended one without a fetch. `disabled: true` still counts; `disabled: false` alone does not.
|
|
25
|
+
- **The Docker image now builds on `node:22-alpine`** (was `node:20-alpine`, past end of life and below `engines.node >=22`). `Containerfile` is regenerated to match.
|
|
26
|
+
- **`npm run test:integration` exits 1 when `LEMONSQUEEZY_TEST_API_KEY` or `LEMONSQUEEZY_TEST_STORE_ID` is unset.** Before, it skipped every suite and exited 0, so a missing credential looked like a pass. `npm test` still skips the integration suites quietly.
|
|
27
|
+
- **`release.sh` checks `npm whoami` before it starts** whenever the workstation will publish, so a dead npm token stops the release before the `v*` tag is pushed instead of after. It also no longer describes a CI release workflow; this repo has none, and the workstation run is the only release path.
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- `ls_update_license_key` accepts `activationLimit: null`, which LemonSqueezy documents as "unlimited". The old description said `0` meant unlimited, which is wrong; the field now says "Pass null for unlimited".
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- **`ls_get_checkout` accepts real checkout IDs.** LemonSqueezy checkout IDs are UUIDs, the one management-API resource that does not use integer IDs, but `checkoutId` was validated as a positive-integer string, so every real checkout was rejected before the request was sent. A read-only probe against a live store caught it; the mocked unit suite could not. An integer `checkoutId` is now rejected locally, where before it passed validation and could only ever 404.
|
|
36
|
+
|
|
37
|
+
### Security
|
|
38
|
+
|
|
39
|
+
- **License keys are masked in audit and log output.** An input key named `licenseKey`, `license_key` or `license-key` (any case) is written as `[REDACTED:last4=XXXX]` when its value is a string of 16 or more characters, and as `[REDACTED]` otherwise. `licenseKeyId`, `license_key_id` and `licenseKeyInstanceId` are left alone. The License API authenticates with the key alone, so it is a bearer credential. This is what lets `ls_deactivate_license` be audited without writing live keys to stderr or the audit resource. Masking goes by key name only, so a key under an arbitrary field such as `customData` is not caught.
|
|
40
|
+
- **An upstream error body with no usable message is logged and returned redacted.** When a JSON error body carries no string `errors[0].detail`, `errors[0].title` or `error`, the whole body is surfaced through the same redactor as audited inputs, rather than raw. A License API error body can embed the caller's key under `license_key.key`. A non-string `error` / `detail` / `title` is no longer taken as the message either, so an object nesting the key cannot skip the redactor.
|
|
41
|
+
|
|
42
|
+
### Documentation
|
|
43
|
+
|
|
44
|
+
- README: the tool catalogue lists all 64 tools, adding the Affiliates section (#42). The release section documents `./release.sh` as the only path (steps 1-8, including the npx smoke test and the MCP Registry publish), with no provenance on a workstation publish and an explicit warning never to run `npm login --auth-type=web` (#43). The `LEMONSQUEEZY_DESTRUCTIVE_RATE_LIMIT` row now lists every destructive call. Also corrected: the retry behaviour, the `LEMONSQUEEZY_API_KEY_COMMAND` tokenizer (no shell), what `pii` actually covers (only the dedicated customer tools; read-class tools still return customer names and emails and accept `include=customer`), the License API tools' boundary (neither the store allowlist nor account separation reaches them), and the redaction rules.
|
|
45
|
+
- SEMVER.md is rewritten for 1.0: the covered surface, and MAJOR / MINOR / PATCH rules for annotations, authority classes, destructive coverage, redaction and the Node floor.
|
|
46
|
+
- CONTRIBUTING.md, `smithery.yaml` and CLAUDE.md are brought in line with the above.
|
|
47
|
+
|
|
48
|
+
### Build
|
|
49
|
+
|
|
50
|
+
- `.gitattributes` forces LF line endings, so a Windows checkout passes Biome and the release gate (#55). The `typeRoots` workaround for `oam check` is reverted, now that oam 0.15.3 fixes the check (#56). Neither changes runtime behaviour.
|
|
51
|
+
|
|
5
52
|
## [0.14.2] — 2026-09-14
|
|
6
53
|
|
|
7
54
|
### Security
|
|
@@ -273,6 +320,8 @@ All notable changes to `@yawlabs/lemonsqueezy-mcp` are documented here. The form
|
|
|
273
320
|
|
|
274
321
|
## [0.10.9] -- 2026-05-22
|
|
275
322
|
|
|
323
|
+
Tagged (`v0.10.9`) but never published to npm and never given a GitHub release; these changes first shipped in 0.10.10.
|
|
324
|
+
|
|
276
325
|
### Changed
|
|
277
326
|
|
|
278
327
|
- **Webhook `events` array now requires at least one entry.** `ls_create_webhook` and `ls_update_webhook` previously let an empty array pass local Zod validation, so a no-op webhook configuration only failed at the LemonSqueezy API as a 422. The new `.min(1)` makes the rejection local with a clearer message; on update, the field stays optional but, when supplied, must be non-empty.
|
|
@@ -434,6 +483,8 @@ All notable changes to `@yawlabs/lemonsqueezy-mcp` are documented here. The form
|
|
|
434
483
|
|
|
435
484
|
## [0.8.0] -- 2026-05-13
|
|
436
485
|
|
|
486
|
+
Never tagged and never published to npm (the version bump is commit `0f010e1`); these changes first shipped in 0.8.1.
|
|
487
|
+
|
|
437
488
|
Distribution-readiness pass -- closes feature gaps against other OSS LemonSqueezy MCP servers ahead of broader distribution.
|
|
438
489
|
|
|
439
490
|
### Added
|
|
@@ -634,7 +685,9 @@ Hardening pass for unattended automation against live billing flows.
|
|
|
634
685
|
|
|
635
686
|
Initial release. 59 tools covering all 17 LemonSqueezy API resources.
|
|
636
687
|
|
|
637
|
-
[Unreleased]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/
|
|
688
|
+
[Unreleased]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/v1.0.1...HEAD
|
|
689
|
+
[1.0.1]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/v1.0.0...v1.0.1
|
|
690
|
+
[1.0.0]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/v0.14.2...v1.0.0
|
|
638
691
|
[0.14.2]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/v0.14.1...v0.14.2
|
|
639
692
|
[0.14.1]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/v0.14.0...v0.14.1
|
|
640
693
|
[0.14.0]: https://github.com/YawLabs/lemonsqueezy-mcp/compare/v0.13.5...v0.14.0
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Yaw Labs
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yaw Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|