ggcheckout-mcp 0.2.4 → 0.4.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 (208) hide show
  1. package/CHANGELOG.md +252 -0
  2. package/README.md +217 -47
  3. package/dist/__e2e__/setup.js +1 -1
  4. package/dist/__e2e__/setup.js.map +1 -1
  5. package/dist/adapters/inbound/tools/billing.tools.d.ts +1 -1
  6. package/dist/adapters/inbound/tools/billing.tools.d.ts.map +1 -1
  7. package/dist/adapters/inbound/tools/billing.tools.js +32 -6
  8. package/dist/adapters/inbound/tools/billing.tools.js.map +1 -1
  9. package/dist/adapters/inbound/tools/checkout.tools.d.ts.map +1 -1
  10. package/dist/adapters/inbound/tools/checkout.tools.js +15 -8
  11. package/dist/adapters/inbound/tools/checkout.tools.js.map +1 -1
  12. package/dist/adapters/inbound/tools/discount.tools.js +1 -1
  13. package/dist/adapters/inbound/tools/discount.tools.js.map +1 -1
  14. package/dist/adapters/inbound/tools/funnel.tools.d.ts.map +1 -1
  15. package/dist/adapters/inbound/tools/funnel.tools.js +89 -51
  16. package/dist/adapters/inbound/tools/funnel.tools.js.map +1 -1
  17. package/dist/adapters/inbound/tools/gateway.tools.d.ts.map +1 -1
  18. package/dist/adapters/inbound/tools/gateway.tools.js +11 -3
  19. package/dist/adapters/inbound/tools/gateway.tools.js.map +1 -1
  20. package/dist/adapters/inbound/tools/members-area.tools.d.ts.map +1 -1
  21. package/dist/adapters/inbound/tools/members-area.tools.js +263 -31
  22. package/dist/adapters/inbound/tools/members-area.tools.js.map +1 -1
  23. package/dist/adapters/inbound/tools/payment.tools.d.ts.map +1 -1
  24. package/dist/adapters/inbound/tools/payment.tools.js +9 -3
  25. package/dist/adapters/inbound/tools/payment.tools.js.map +1 -1
  26. package/dist/adapters/inbound/tools/product.tools.d.ts.map +1 -1
  27. package/dist/adapters/inbound/tools/product.tools.js +115 -29
  28. package/dist/adapters/inbound/tools/product.tools.js.map +1 -1
  29. package/dist/adapters/inbound/tools/rewards.tools.d.ts.map +1 -1
  30. package/dist/adapters/inbound/tools/rewards.tools.js +6 -2
  31. package/dist/adapters/inbound/tools/rewards.tools.js.map +1 -1
  32. package/dist/adapters/inbound/tools/shipping.tools.js +1 -1
  33. package/dist/adapters/inbound/tools/shipping.tools.js.map +1 -1
  34. package/dist/adapters/inbound/tools/store.tools.d.ts.map +1 -1
  35. package/dist/adapters/inbound/tools/store.tools.js +302 -25
  36. package/dist/adapters/inbound/tools/store.tools.js.map +1 -1
  37. package/dist/adapters/inbound/tools/telegram.tools.d.ts.map +1 -1
  38. package/dist/adapters/inbound/tools/telegram.tools.js +8 -1
  39. package/dist/adapters/inbound/tools/telegram.tools.js.map +1 -1
  40. package/dist/adapters/inbound/tools/webhook.tools.d.ts.map +1 -1
  41. package/dist/adapters/inbound/tools/webhook.tools.js +17 -8
  42. package/dist/adapters/inbound/tools/webhook.tools.js.map +1 -1
  43. package/dist/adapters/inbound/tools/whatsapp.tools.d.ts.map +1 -1
  44. package/dist/adapters/inbound/tools/whatsapp.tools.js +3 -1
  45. package/dist/adapters/inbound/tools/whatsapp.tools.js.map +1 -1
  46. package/dist/adapters/outbound/auth.api.d.ts +7 -0
  47. package/dist/adapters/outbound/auth.api.d.ts.map +1 -1
  48. package/dist/adapters/outbound/auth.api.js +18 -2
  49. package/dist/adapters/outbound/auth.api.js.map +1 -1
  50. package/dist/adapters/outbound/billing.api.d.ts +25 -8
  51. package/dist/adapters/outbound/billing.api.d.ts.map +1 -1
  52. package/dist/adapters/outbound/billing.api.js +86 -3
  53. package/dist/adapters/outbound/billing.api.js.map +1 -1
  54. package/dist/adapters/outbound/checkout.api.d.ts +4 -4
  55. package/dist/adapters/outbound/checkout.api.d.ts.map +1 -1
  56. package/dist/adapters/outbound/checkout.api.js +26 -10
  57. package/dist/adapters/outbound/checkout.api.js.map +1 -1
  58. package/dist/adapters/outbound/checkout.api.test.js +58 -11
  59. package/dist/adapters/outbound/checkout.api.test.js.map +1 -1
  60. package/dist/adapters/outbound/funnel.api.d.ts +3 -1
  61. package/dist/adapters/outbound/funnel.api.d.ts.map +1 -1
  62. package/dist/adapters/outbound/funnel.api.js +25 -9
  63. package/dist/adapters/outbound/funnel.api.js.map +1 -1
  64. package/dist/adapters/outbound/http-client.d.ts +12 -0
  65. package/dist/adapters/outbound/http-client.d.ts.map +1 -1
  66. package/dist/adapters/outbound/http-client.js +63 -12
  67. package/dist/adapters/outbound/http-client.js.map +1 -1
  68. package/dist/adapters/outbound/http-client.test.js +2 -2
  69. package/dist/adapters/outbound/http-client.test.js.map +1 -1
  70. package/dist/adapters/outbound/members-area.api.d.ts +55 -2
  71. package/dist/adapters/outbound/members-area.api.d.ts.map +1 -1
  72. package/dist/adapters/outbound/members-area.api.js +89 -1
  73. package/dist/adapters/outbound/members-area.api.js.map +1 -1
  74. package/dist/adapters/outbound/payment.api.d.ts +6 -0
  75. package/dist/adapters/outbound/payment.api.d.ts.map +1 -1
  76. package/dist/adapters/outbound/payment.api.js +17 -3
  77. package/dist/adapters/outbound/payment.api.js.map +1 -1
  78. package/dist/adapters/outbound/product.api.d.ts +39 -7
  79. package/dist/adapters/outbound/product.api.d.ts.map +1 -1
  80. package/dist/adapters/outbound/product.api.js +57 -15
  81. package/dist/adapters/outbound/product.api.js.map +1 -1
  82. package/dist/adapters/outbound/product.api.test.js +14 -1
  83. package/dist/adapters/outbound/product.api.test.js.map +1 -1
  84. package/dist/adapters/outbound/rewards.api.d.ts +5 -1
  85. package/dist/adapters/outbound/rewards.api.d.ts.map +1 -1
  86. package/dist/adapters/outbound/rewards.api.js +5 -1
  87. package/dist/adapters/outbound/rewards.api.js.map +1 -1
  88. package/dist/adapters/outbound/signed-upload.d.ts +10 -0
  89. package/dist/adapters/outbound/signed-upload.d.ts.map +1 -0
  90. package/dist/adapters/outbound/signed-upload.js +29 -0
  91. package/dist/adapters/outbound/signed-upload.js.map +1 -0
  92. package/dist/adapters/outbound/store.api.d.ts +37 -1
  93. package/dist/adapters/outbound/store.api.d.ts.map +1 -1
  94. package/dist/adapters/outbound/store.api.js +88 -7
  95. package/dist/adapters/outbound/store.api.js.map +1 -1
  96. package/dist/adapters/outbound/store.api.test.js +62 -0
  97. package/dist/adapters/outbound/store.api.test.js.map +1 -1
  98. package/dist/adapters/outbound/telegram.api.d.ts +5 -0
  99. package/dist/adapters/outbound/telegram.api.d.ts.map +1 -1
  100. package/dist/adapters/outbound/telegram.api.js +7 -2
  101. package/dist/adapters/outbound/telegram.api.js.map +1 -1
  102. package/dist/adapters/outbound/whatsapp.api.d.ts +5 -0
  103. package/dist/adapters/outbound/whatsapp.api.d.ts.map +1 -1
  104. package/dist/adapters/outbound/whatsapp.api.js +20 -3
  105. package/dist/adapters/outbound/whatsapp.api.js.map +1 -1
  106. package/dist/core/ports/billing.port.d.ts +8 -8
  107. package/dist/core/ports/billing.port.d.ts.map +1 -1
  108. package/dist/core/ports/checkout.port.d.ts +4 -4
  109. package/dist/core/ports/checkout.port.d.ts.map +1 -1
  110. package/dist/core/ports/funnel.port.d.ts +4 -1
  111. package/dist/core/ports/funnel.port.d.ts.map +1 -1
  112. package/dist/core/ports/members-area.port.d.ts +42 -1
  113. package/dist/core/ports/members-area.port.d.ts.map +1 -1
  114. package/dist/core/ports/product.port.d.ts +22 -7
  115. package/dist/core/ports/product.port.d.ts.map +1 -1
  116. package/dist/core/ports/rewards.port.d.ts +0 -1
  117. package/dist/core/ports/rewards.port.d.ts.map +1 -1
  118. package/dist/core/ports/store.port.d.ts +36 -1
  119. package/dist/core/ports/store.port.d.ts.map +1 -1
  120. package/dist/core/services/billing.service.d.ts +14 -7
  121. package/dist/core/services/billing.service.d.ts.map +1 -1
  122. package/dist/core/services/billing.service.js +42 -2
  123. package/dist/core/services/billing.service.js.map +1 -1
  124. package/dist/core/services/checkout.service.d.ts +21 -2
  125. package/dist/core/services/checkout.service.d.ts.map +1 -1
  126. package/dist/core/services/checkout.service.js +102 -14
  127. package/dist/core/services/checkout.service.js.map +1 -1
  128. package/dist/core/services/checkout.service.test.js +124 -67
  129. package/dist/core/services/checkout.service.test.js.map +1 -1
  130. package/dist/core/services/funnel.service.d.ts +8 -1
  131. package/dist/core/services/funnel.service.d.ts.map +1 -1
  132. package/dist/core/services/funnel.service.js +21 -1
  133. package/dist/core/services/funnel.service.js.map +1 -1
  134. package/dist/core/services/funnel.service.test.d.ts +2 -0
  135. package/dist/core/services/funnel.service.test.d.ts.map +1 -0
  136. package/dist/core/services/funnel.service.test.js +82 -0
  137. package/dist/core/services/funnel.service.test.js.map +1 -0
  138. package/dist/core/services/members-area.service.d.ts +48 -2
  139. package/dist/core/services/members-area.service.d.ts.map +1 -1
  140. package/dist/core/services/members-area.service.js +35 -1
  141. package/dist/core/services/members-area.service.js.map +1 -1
  142. package/dist/core/services/product.service.d.ts +95 -6
  143. package/dist/core/services/product.service.d.ts.map +1 -1
  144. package/dist/core/services/product.service.js +280 -13
  145. package/dist/core/services/product.service.js.map +1 -1
  146. package/dist/core/services/product.service.test.js +80 -0
  147. package/dist/core/services/product.service.test.js.map +1 -1
  148. package/dist/core/services/rewards.service.d.ts +0 -1
  149. package/dist/core/services/rewards.service.d.ts.map +1 -1
  150. package/dist/core/services/rewards.service.js +0 -1
  151. package/dist/core/services/rewards.service.js.map +1 -1
  152. package/dist/core/services/store.service.d.ts +46 -1
  153. package/dist/core/services/store.service.d.ts.map +1 -1
  154. package/dist/core/services/store.service.js +115 -0
  155. package/dist/core/services/store.service.js.map +1 -1
  156. package/dist/core/services/store.service.test.d.ts +2 -0
  157. package/dist/core/services/store.service.test.d.ts.map +1 -0
  158. package/dist/core/services/store.service.test.js +62 -0
  159. package/dist/core/services/store.service.test.js.map +1 -0
  160. package/dist/core/types/billing.d.ts +60 -0
  161. package/dist/core/types/billing.d.ts.map +1 -1
  162. package/dist/core/types/checkout.d.ts +43 -4
  163. package/dist/core/types/checkout.d.ts.map +1 -1
  164. package/dist/core/types/funnel.d.ts +57 -10
  165. package/dist/core/types/funnel.d.ts.map +1 -1
  166. package/dist/core/types/members-area.d.ts +69 -0
  167. package/dist/core/types/members-area.d.ts.map +1 -1
  168. package/dist/core/types/payment.d.ts +10 -1
  169. package/dist/core/types/payment.d.ts.map +1 -1
  170. package/dist/core/types/product.d.ts +92 -11
  171. package/dist/core/types/product.d.ts.map +1 -1
  172. package/dist/core/types/rewards.d.ts +4 -0
  173. package/dist/core/types/rewards.d.ts.map +1 -1
  174. package/dist/core/types/store.d.ts +82 -0
  175. package/dist/core/types/store.d.ts.map +1 -1
  176. package/dist/core/types/telegram.d.ts +3 -1
  177. package/dist/core/types/telegram.d.ts.map +1 -1
  178. package/dist/core/types/telegram.js +1 -1
  179. package/dist/core/types/telegram.js.map +1 -1
  180. package/dist/index.js +6 -4
  181. package/dist/index.js.map +1 -1
  182. package/dist/shared/errors.d.ts +11 -1
  183. package/dist/shared/errors.d.ts.map +1 -1
  184. package/dist/shared/errors.js +15 -2
  185. package/dist/shared/errors.js.map +1 -1
  186. package/dist/shared/external-offer-snippet.d.ts +25 -0
  187. package/dist/shared/external-offer-snippet.d.ts.map +1 -0
  188. package/dist/shared/external-offer-snippet.js +114 -0
  189. package/dist/shared/external-offer-snippet.js.map +1 -0
  190. package/dist/shared/local-file.d.ts +32 -0
  191. package/dist/shared/local-file.d.ts.map +1 -0
  192. package/dist/shared/local-file.js +92 -0
  193. package/dist/shared/local-file.js.map +1 -0
  194. package/dist/shared/merge.d.ts +6 -0
  195. package/dist/shared/merge.d.ts.map +1 -0
  196. package/dist/shared/merge.js +22 -0
  197. package/dist/shared/merge.js.map +1 -0
  198. package/dist/shared/sanitizer.d.ts +7 -0
  199. package/dist/shared/sanitizer.d.ts.map +1 -1
  200. package/dist/shared/sanitizer.js +28 -0
  201. package/dist/shared/sanitizer.js.map +1 -1
  202. package/dist/shared/sanitizer.test.js +20 -1
  203. package/dist/shared/sanitizer.test.js.map +1 -1
  204. package/dist/shared/webhook-fixtures.d.ts +33 -4
  205. package/dist/shared/webhook-fixtures.d.ts.map +1 -1
  206. package/dist/shared/webhook-fixtures.js +63 -21
  207. package/dist/shared/webhook-fixtures.js.map +1 -1
  208. package/package.json +6 -5
package/CHANGELOG.md ADDED
@@ -0,0 +1,252 @@
1
+ # Changelog
2
+
3
+ This package is published to npm and the README installs it as `npx -y ggcheckout-mcp`,
4
+ which is unpinned — a new version reaches every existing installation on its next start.
5
+ Read this file before upgrading, and pin a version if a breaking change is not convenient
6
+ right now.
7
+
8
+ ## 0.4.0
9
+
10
+ Checked end to end against a QA account on the Postgres (v2) data path, and product edits
11
+ also against production.
12
+
13
+ ### Release requirement — do not publish before the API has these changes
14
+
15
+ Two tools depend on an open pull request of the API. Published before it, the install (unpinned)
16
+ reaches everyone, and they write a model the API does not read yet:
17
+
18
+ - `set_offer_product_page` and `get_offer_snippets` need the per-product seller page model of
19
+ ggCheckout/saas-checkout#1681 (`productOverrides[product].displayMode` + `externalFlow.pageUrl`).
20
+ Against an API without it, the write is saved but the buyer never reaches the seller's page.
21
+
22
+ `update_module`, `update_section`, `update_lesson`, `delete_module`, `delete_section` and
23
+ `delete_lesson` need the `PATCH`/`DELETE` routes under `/api/members-area/{areaId}/modules/…` of
24
+ ggCheckout/saas-checkout#1685, merged on 2026-10-13. Against an API without them they answer
25
+ "this API has no such route yet", not as a missing item.
26
+
27
+ ### Breaking
28
+
29
+ Every item here changes what an existing call sends or gets back. A 0.x minor bump is a
30
+ breaking release, and with the unpinned install it reaches everyone on the next start.
31
+
32
+ - **`list_rewards` is gone; use `calculate_rewards`.** The route it called was removed along
33
+ with the stored counter it served. `calculate_rewards` answers the same fields, derived from
34
+ paid sales, and carries the milestone list — there is no reward catalogue endpoint.
35
+ `currentRevenue` and `milestones` are in reais, not cents.
36
+ - **`upload_deliverable` takes `fileSize` and no longer takes `fileUrl`**, and attaching is now
37
+ two calls: `upload_deliverable` mints an upload URL, you PUT the bytes to it, and
38
+ **`attach_deliverable`** confirms the upload and links it. See "Routes that had moved".
39
+ - **`reorder_upsells` takes `upsellIds`** (all the ids, in order) instead of `upsells` (whole
40
+ objects). Both reorder tools now return the resulting positions.
41
+ - **`add_credit` answers a new shape** — `{ creditId, amountCents, pixCode, pixQrBase64,
42
+ expiresAt, via }` — and **`amountCents` must be whole cents from 325 to 25000** (R$ 3,25 to
43
+ R$ 250,00). Anything else used to reach the API; it is now refused before the call.
44
+ - **`create_webhook` / `update_webhook` accept only the 15 real event names**, and
45
+ **`test_webhook` simulates only `pix.paid`, `card.paid`, `pix.expired`, `card.expired`**. The
46
+ old suggestions (`payment.created`, `payment.paid`, `payment.refunded`…) are refused.
47
+ - **`insert_token` takes `type` and `target` from `pushinpay`, `utmify`, `emailprovider`,
48
+ `mercadopago`.** Any other value was always refused by the API.
49
+ - **Lower caps:** `get_payments_paginated` `pageSize` 1000 → 100 (the API already reduced it
50
+ silently); `list_credits` `limit` 1000 → 200, the lowest cap of the two statements it reads.
51
+ - **`update_funnel` no longer takes `settings.pixels` or `settings.webhookUrl`.** Nothing
52
+ read them: the quiz page resolves `settings.pixelTokenIds` (ids from `list_tokens`) and
53
+ webhooks are `settings.webhookIds` (ids from `list_webhooks`). A call that still sends
54
+ them is refused by validation instead of being silently ignored.
55
+ - **`list_products` hides deleted products.** `delete_product` is a soft delete and the API
56
+ keeps listing the row with `deleted: true`.
57
+ - `list_store_products` no longer accepts `sortBy: "createdAt"` (the API ignored it), and
58
+ `validate_coupon` takes `orderValue` as integer cents.
59
+ - **`update_checkout` merges the `checkout` object instead of replacing it.** Send only the keys
60
+ to change. An array still replaces the stored one, and a key can no longer be removed by leaving
61
+ it out; set it to `null` instead. The stored `checkout.paymentMethods` is not part of the merge:
62
+ the read does not return every stored value of the methods, so re-sending it could rewrite them
63
+ with less than what is stored. Payment methods change only when the call sends them.
64
+ - **`upload_deliverable` requires `fileType`.**
65
+ - **Empty lists are refused** where the API would do nothing with them: `events` in
66
+ `create_webhook` / `update_webhook` and `order` in `reorder_downsells` need at least one item.
67
+ - **Lesson `content` follows the API's shape** (`create_lesson`, `update_lesson`). Quiz questions
68
+ are `{ id, question, type, options: string[], correctAnswer, explanation, points }`; the old
69
+ `{ text, options: [{ id, text, isCorrect }] }` was stored as sent and no student could be graded
70
+ on it. `textMarkdown`, `videoId`, `videoDuration`, `videoThumbnail`, `videoQualities`,
71
+ `estimatedReadTime`, `fileSize` and `fileType` are gone: the API dropped them with a 200. URLs
72
+ must be absolute, at most 50 questions, `minScore` a whole number from 0 to 100.
73
+ - **Cascading deletes need `confirm: true`** (`delete_module`, `delete_section`, `delete_lesson`).
74
+
75
+ ### Routes that had moved
76
+
77
+ A sweep of every endpoint this client calls against the current API found four with no route
78
+ behind them any more, plus a set of tools whose behaviour had drifted. Each item below was
79
+ confirmed in the API source, and the fixes were exercised against a live account.
80
+
81
+ - **`list_rewards` → `calculate_rewards`** (see Breaking).
82
+ - **`add_credit` works on both billing generations.** The legacy route refuses a migrated
83
+ seller with 409 pointing at the top-up route; the call now follows that refusal, and only
84
+ that one. Takes an optional `idempotencyKey`, which only the new billing reads. A timeout or
85
+ a 502 may still have opened the PIX, so that error now says to look in `list_credits` before
86
+ retrying instead of inviting a second charge.
87
+ - **`list_credits` returns the statement for either generation.** It reads the legacy credits
88
+ and the credit ledger, and answers `{ credits, total, ledger: { entries, nextBefore } }`. One
89
+ side is empty depending on the account, which is the true answer and not an error — before
90
+ this, a migrated seller got an empty list with no indication the data lived elsewhere. If one
91
+ side fails, the other still answers and `creditsError` / `ledgerError` says what failed.
92
+ - **`upload_deliverable` / `delete_deliverable` now call routes that exist.** The paths they
93
+ used (`/api/products/{id}/deliverable/…`) are not part of the API. Attaching a file is now
94
+ two steps: `upload_deliverable` mints an upload URL, you PUT the bytes to it (only
95
+ `Content-Type`, no `Authorization`), then **`attach_deliverable`** confirms the upload and
96
+ links it to the product, keeping any link the product already has. `delete_deliverable`
97
+ unlinks the file and, given `filePath`, deletes the bytes too; it refuses when the file is
98
+ the only deliverable, and a failed byte deletion comes back as `fileDeleteError` beside the
99
+ completed unlink.
100
+ - **`telegram_media_upload` calls `/presign`.** The old path was renamed. It returns
101
+ `{ uploadUrl, filePath, proxyUrl }`; `proxyUrl` is the URL to store in the flow node, because
102
+ the route does not return a public URL. The previously advertised `publicUrl` was always
103
+ undefined.
104
+ - **`reorder_upsells` calls `.../upsells/reorder`.** It used to send whole objects to a route
105
+ that replaces the legacy upsell array instead of reordering, and that route does not exist
106
+ for a product on the new storage, where the call failed as an opaque 502.
107
+ - **`update_product` writes the way each storage expects.** It used to re-send the whole
108
+ stored product. That is still what the old storage needs — its write puts a default into
109
+ every key the body omits (`url: ''`, `deliverableFile: null`, `membersAreaEnabled: false`…),
110
+ so a partial body would wipe the product with a 200 — and its read carries the file and the
111
+ stock lines, so it still goes back whole (minus the live `stockQuantity`). On the new storage
112
+ the read carries neither, so the re-send dropped them and the save was refused; there the
113
+ call now sends the edit plus the one field that satisfies the API's deliverable check (the
114
+ check reads the request body, not the stored product). When the only deliverable is a file or
115
+ stock lines — neither readable there — the edit is refused here with an explanation instead
116
+ of a bare 400. `attach_deliverable` and `delete_deliverable` go through the same write.
117
+ - **`create_webhook` / `update_webhook` validate `events`.** The API stores event names without
118
+ checking them and dispatch matches exactly, so a wrong name is accepted and never fires. The
119
+ names this tool used to suggest (`payment.created`, `payment.paid`, `payment.refunded`) are
120
+ not seller webhook events at all. The real vocabulary is now enforced here, and `test_webhook`
121
+ simulates only the payment-shaped events.
122
+ - **`insert_token` accepts only the four types the API takes**, in `type` and in `target`,
123
+ which the route checks against the same list. `stripe` and `efibank` were advertised and
124
+ always refused.
125
+ - **`list_payments` answers an empty list for a seller with no sales.** The route reports that
126
+ state as 404, which surfaced as an error.
127
+ - **`get_payments_paginated`**: the cursor in the answer is `nextCursor`; `totalCapped: true`
128
+ means the count stopped at its cap and `total` is a floor; a text search may come back with
129
+ `coverageCapped`.
130
+ - **423 is not a thing, 503 is not "the backend is down".** 503 means the rate limiter is
131
+ failing closed and nothing was changed, so it is reported as retryable. 502 means the service
132
+ behind the API did not answer, and a write may or may not have landed, so it says to check
133
+ before repeating one. The wait is read from `Retry-After` or the body's `retry_after`. A
134
+ refusal that carries a `code` now shows it instead of just a status number.
135
+
136
+ ### Tools that an API key cannot use
137
+
138
+ `create_whatsapp_session` answers 403 for an API key by design: the route classes it as
139
+ sensitive. It now says so and what to do instead, rather than surfacing a bare "Forbidden".
140
+
141
+ ### Packaging
142
+
143
+ - Compiled tests no longer ship in the published package (560 files down to 428).
144
+ - `dotenv` is loaded quietly: version 17 announces itself on stdout, which is the MCP protocol
145
+ channel over stdio, and a strict client reads that line as a malformed frame.
146
+
147
+ ### Added
148
+
149
+ - **Offers on the seller's page:** `set_offer_product_page` puts one product of an upsell or
150
+ downsell on the seller's own page (or back on the GG page), mixed with GG pages in the same
151
+ funnel; `get_offer_snippets` returns, read only, the HTML to paste for each product on the
152
+ seller's page. `update_checkout` now merges the `checkout` object, so setting one key keeps the
153
+ rest of the page setup.
154
+ - **Members-area files:** `upload_members_area_file` uploads an image, a lesson video or a file
155
+ (PDF, document, audio) from the machine running the server and returns the URL to use. It reads
156
+ only from the folder set in `GGCHECKOUT_UPLOAD_ROOT` and refuses every upload while that is unset.
157
+ `create_pdf_lessons` creates a batch of PDF lessons; `list_lesson_attachments`,
158
+ `add_lesson_attachment` and `delete_lesson_attachment` manage a lesson's complementary files.
159
+ - **Editing and deleting the course structure:** `update_module`, `update_section`, `update_lesson`,
160
+ `delete_module`, `delete_section`, `delete_lesson` — until now only the dashboard could, through
161
+ server actions an API key cannot call. **They need the API release with the `PATCH`/`DELETE`
162
+ routes under `/api/members-area/{areaId}/modules/…`**; an older deployment answers 404/405.
163
+ - `create_module` and `create_section` take `dripSettings`; `create_section` and `create_lesson`
164
+ take `showTitleOverlay`, `showImageOnly` and `order`, and `create_lesson` a `thumbnailUrl`.
165
+ - `list_stores`, the only way to get the `storeId` every store tool takes. It also returns
166
+ DELETED stores — the listing it comes from never filtered them and the API does not mark
167
+ them — and such a storeId answers 404 in every other store tool, so the description now
168
+ warns to confirm an unfamiliar one with `get_store`.
169
+ - Store management: `create_store`, `get_store`, `update_store`, `delete_store`, store
170
+ categories (`list_store_categories`, `create_store_category`, `update_store_category`,
171
+ `delete_store_category`) and review moderation (`list_store_reviews`,
172
+ `create_store_review`, `update_store_review`, `delete_store_review`). **These need the
173
+ `/api/stores/{storeId}` routes**, available from the GG Checkout release that ships them;
174
+ against an older deployment they answer 404/405.
175
+ - Store builder: `get_store_layout`, `update_store_layout`, `publish_store_layout`,
176
+ `list_store_layout_history`, `restore_store_layout_version`, `get_store_theme`. A store with
177
+ no layout yet — which is every newly created one — has nothing to copy the block shapes
178
+ from, and the route validates them strictly, so the first-save error now spells out an
179
+ accepted `theme` and block shape.
180
+ - `list_funnel_checkouts`: the checkouts and gateways a funnel `pix` component can use.
181
+ - `update_product` takes `stockEnabled`, `unlimitedStock` and `stockQuantity`;
182
+ `create_upsell` / `create_downsell` take an optional `order`.
183
+
184
+ ### Fixed
185
+
186
+ - **`update_checkout` sends only the checkout's identity and what changed.** The checkout API
187
+ keeps every key absent from the body as stored, so the tool no longer echoes the whole
188
+ document it read back (`paymentMethods`, the `checkout` object, `orderBumps`, `url`,
189
+ `fields`, `sellerName`, `currency`, `published`, `createBy`). Echoing it could overwrite
190
+ stored values the read does not carry (re-sent order bumps lost their per-bump original
191
+ price and button text); `paymentMethods`, `checkout` and `orderBumps` only travel when the
192
+ caller changes them.
193
+ - `update_product` with only some fields was refused (400 "Você precisa fornecer um link
194
+ (url)…"): the API validates the body as a whole product. The stored product is now
195
+ re-sent with the edit on top.
196
+ - `create_upsell` / `create_downsell` were refused on v2 accounts (422 "missing field
197
+ sortOrder") and, where accepted, stored an offer with no product to sell. They now write
198
+ `order` and `upsellProductIds` / `downsellProductIds` the way the dashboard does.
199
+ - `update_funnel` with part of `design` or `settings` erased the rest of it. Both are now
200
+ merged into the stored funnel. Steps keep every field the editor stores (`loadingScreen`,
201
+ `allowBack`, `stickyButton`…), and the `level` and `social_proof` components are accepted.
202
+ - `list_upsells` returned the API envelope instead of the list.
203
+ - Store and funnel ids and coupon codes are URL-encoded; store read limits match the API.
204
+
205
+ ## 0.3.0
206
+
207
+ ### Breaking
208
+
209
+ - **`create_checkout` takes `productId` instead of `id`.** The value must be the uid of the
210
+ product the checkout sells — the `productId` returned by `create_product`, or a `uid` from
211
+ `list_products`. The old input was described as a free-form slug, which produced a checkout
212
+ no product claimed: the dashboard rendered it as an orphan card and opening it 404'd.
213
+ Pin `ggcheckout-mcp@0.2.4` if you need the old input name.
214
+ - **Checkout responses expose that foreign key as `productId` too.** `list_checkouts`,
215
+ `get_checkout` and `update_checkout` used to return it under the API's own name, `id`,
216
+ which collided with the checkout's own identifier. The rename is now applied in both
217
+ directions, so one value has one name. The checkout's own id is still `uid`.
218
+
219
+ ### Fixed
220
+
221
+ - Three of the four checkout paths were failing against the live API: the owner field was
222
+ misspelled `uuidOwnwer` throughout the module, so `create_checkout` returned 403 and
223
+ `list_checkouts` / `update_checkout` returned 400.
224
+ - `create_checkout` and `update_checkout` sent `price` in Reais while the API stores and
225
+ charges cents, so a checkout created for `99.90` charged R$0,99. Prices are now converted,
226
+ matching what `create_product` already did.
227
+ - `update_checkout` wiped fields it did not send. The API destructures the body with defaults
228
+ instead of merging, so a title-only edit reset the checkout URL, the buyer form
229
+ configuration, the seller name and the currency. The whole document is now re-sent.
230
+ - `orderBumps` was sent as bare product uids, but the field stores a JSON snapshot per bump;
231
+ every bump created through the MCP was silently dropped when the checkout page parsed it.
232
+ Bumps are now resolved and serialized, so an unknown uid fails the call instead.
233
+ - `create_checkout` reported every failure of its product pre-check as "product not found",
234
+ including timeouts and 5xx. During an outage that told the agent to create a duplicate
235
+ product. Only the API's own 403/404 is now treated as a bad `productId`.
236
+ - `update_checkout` on a checkout with no product pointer returned an opaque
237
+ `Missing required fields: id` from the API; it now fails with an explanation.
238
+ - Ids are URL-escaped before they are interpolated into request paths. A value containing
239
+ `/`, `#` or `?` used to change which endpoint was called — which, for the new product
240
+ pre-check, meant it could validate a different resource than the one being written.
241
+
242
+ ### Changed
243
+
244
+ - `delete_checkout` no longer reads the checkout first. The endpoint takes ownership from the
245
+ authenticated token and ignores the body, so the extra read only spent quota against the
246
+ public, IP-rate-limited route.
247
+ - The business id behind almost every tool (`GET /api/me`) is fetched once per process instead
248
+ of once per call.
249
+
250
+ ## 0.2.4 and earlier
251
+
252
+ Not recorded. See `git log`.