askell-mcp 0.4.4 → 0.4.6

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/README.md CHANGED
@@ -127,7 +127,7 @@ Typical agent workflow:
127
127
 
128
128
  - **v1** — legacy paths like `/customers/`, `/subscriptions/` (no `/v2` prefix)
129
129
  - **v2** — current model: catalogs, quotes, checkouts, contracts, billing runs under `/v2/`
130
- - **v2 discounts** — coupons: `GET/POST /v2/subscription-contracts/{id}/discount|apply-code|remove-discount` (one active). Quotes take `promotion_code` and, for an existing buyer, `customer` (id) so combo discounts + promo restrictions apply. Totals already include both. Recurring `finalize` needs a verified payment method even when due-now is 0. Not the v1 `discount` 0–100 field.
130
+ - **v2 discounts** — coupons: `GET/POST /v2/subscription-contracts/{id}/discount|apply-code|remove-discount` (one active). Quotes take `promotion_code` and, for an existing buyer, `customer` (id) so combo discounts + promo restrictions apply. First-period totals already include coupon + combo; `quote.recurring_*` include combo but not the coupon (`discount.recurring_final_amount` while the coupon is active). Recurring `finalize` needs a verified payment method even when due-now is 0. Not the v1 `discount` 0–100 field.
131
131
  - Paths use **trailing slashes**
132
132
  - Prefer **v2** for new integrations; v1 remains for existing ones
133
133
  - Docs: [docs.askell.is](https://docs.askell.is/) · OpenAPI: [v1](https://askell.is/api/swagger/swagger.json) · [v2](https://askell.is/api/swagger/v2/swagger.json)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "askell-mcp",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "MCP server for the Askell payment and subscription API (Bun + stdio)",
5
5
  "author": "Neschadin Oleksandr",
6
6
  "license": "MIT",
@@ -67,6 +67,6 @@
67
67
  },
68
68
  "dependencies": {
69
69
  "@modelcontextprotocol/server": "2.0.0",
70
- "zod": "4.6.1"
70
+ "zod": "4.6.2"
71
71
  }
72
72
  }
@@ -3088,6 +3088,10 @@
3088
3088
  "shipping": {
3089
3089
  "$ref": "#/components/schemas/V2ShippingSelectionInput",
3090
3090
  "description": "The shipping option the customer chose. Required when the offer contains physical products and the account has active shipping options."
3091
+ },
3092
+ "allowed_origin": {
3093
+ "type": "string",
3094
+ "description": "Origin allowed to embed the hosted card form for this checkout in an iframe, for example `https://shop.example`. A single http(s) origin with no path; http is accepted only for `localhost` and loopback addresses (`127.0.0.0/8`, `[::1]`). When set it replaces the account-level checkout origins in the hosted page's `frame-ancestors` policy. Not accepted on checkout-session endpoints, where the sales channel's allowed origins apply."
3091
3095
  }
3092
3096
  }
3093
3097
  }
@@ -3638,6 +3642,10 @@
3638
3642
  },
3639
3643
  "metadata": {
3640
3644
  "$ref": "#/components/schemas/V2Metadata"
3645
+ },
3646
+ "allowed_origin": {
3647
+ "type": "string",
3648
+ "description": "Origin allowed to embed this hosted card form in an iframe, for example `https://shop.example`. A single http(s) origin with no path; http is accepted only for `localhost` and loopback addresses (`127.0.0.0/8`, `[::1]`). Defaults to the checkout's `allowed_origin`, and when set it replaces the account-level checkout origins in the hosted page's `frame-ancestors` policy. Not accepted on checkout-session endpoints, where the sales channel's allowed origins apply."
3641
3649
  }
3642
3650
  }
3643
3651
  },
@@ -3690,6 +3698,10 @@
3690
3698
  "metadata": {
3691
3699
  "$ref": "#/components/schemas/V2Metadata"
3692
3700
  },
3701
+ "allowed_origin": {
3702
+ "type": "string",
3703
+ "description": "Origin allowed to embed this hosted card form, or an empty string when the account-level checkout origins apply."
3704
+ },
3693
3705
  "error_message": {
3694
3706
  "type": "string"
3695
3707
  },
@@ -3767,6 +3779,10 @@
3767
3779
  "metadata": {
3768
3780
  "$ref": "#/components/schemas/V2Metadata"
3769
3781
  },
3782
+ "allowed_origin": {
3783
+ "type": "string",
3784
+ "description": "Origin allowed to embed hosted pages for this checkout, or an empty string when the account-level checkout origins apply."
3785
+ },
3770
3786
  "created_at": {
3771
3787
  "type": "string",
3772
3788
  "format": "date-time"
@@ -3998,6 +4014,21 @@
3998
4014
  "original_total_amount": {
3999
4015
  "type": "string",
4000
4016
  "format": "decimal"
4017
+ },
4018
+ "recurring_original_amount": {
4019
+ "type": "string",
4020
+ "format": "decimal",
4021
+ "description": "What a renewal bills without the coupon. The recurring_* totals of the quote do not include the promotion code discount."
4022
+ },
4023
+ "recurring_discount_amount": {
4024
+ "type": "string",
4025
+ "format": "decimal",
4026
+ "description": "The coupon's discount applied to a renewal's recurring lines. Computed regardless of duration: a once coupon lapses after the first payment and a repeating coupon after duration_in_months, so only treat this as the renewal discount while the coupon is active."
4027
+ },
4028
+ "recurring_final_amount": {
4029
+ "type": "string",
4030
+ "format": "decimal",
4031
+ "description": "What a renewal bills with the coupon's discount applied. Only meaningful while the coupon is still active (see duration and duration_in_months)."
4001
4032
  }
4002
4033
  }
4003
4034
  },
@@ -4915,6 +4946,13 @@
4915
4946
  "metadata": {
4916
4947
  "$ref": "#/components/schemas/V2Metadata"
4917
4948
  },
4949
+ "subscriber_page": {
4950
+ "type": "string",
4951
+ "format": "uri",
4952
+ "nullable": true,
4953
+ "readOnly": true,
4954
+ "description": "Absolute URL of the customer-facing subscription management page for this contract."
4955
+ },
4918
4956
  "created_at": {
4919
4957
  "type": "string",
4920
4958
  "format": "date-time"
package/src/server.ts CHANGED
@@ -49,12 +49,14 @@ API layout:
49
49
 
50
50
  V2 discounts — two systems, not v1 Subscription.discount (0-100 on a PlanVariant; never send that to v2):
51
51
  - Coupons: one active per contract. GET /v2/subscription-contracts/{id}/discount/ (also nested as contract.discount). Apply with POST .../apply-code/ {promotion_code}. Remove with POST .../remove-discount/.
52
- - Quotes (POST /v2/subscription-offer-quotes/): pass promotion_code for coupons. When quoting an existing customer, pass customer (numeric id) or combo discounts from their other active contracts and promo-code customer restrictions are skipped. Quoted totals already include coupon + combo; do not subtract again. combo_discounts[] is on the quote response (askell_describe_operation omits response schemas). Combo is automatic, not apply-code.
52
+ - Quotes (POST /v2/subscription-offer-quotes/): pass promotion_code for coupons. When quoting an existing customer, pass customer (numeric id) or combo discounts from their other active contracts and promo-code customer restrictions are skipped. First-period subtotal/tax/total already include coupon + combo. quote.recurring_* include combo, not the coupon — renewal-with-coupon is discount.recurring_final_amount, and only while duration still applies (once → after first payment use recurring_*). combo_discounts[] and discount.recurring_* are on the quote response (askell_describe_operation omits response schemas). Combo is automatic, not apply-code.
53
53
 
54
54
  V2 checkout notes:
55
55
  - checkout_url on V2 checkouts points to the API object URL, not a hosted payment page.
56
+ - GET contract.subscriber_page is the customer-facing subscription management URL (readOnly, nullable). Not checkout_url, not v1 /public/payments/{id}/ (hosted signup). Do not send it on create/patch.
56
57
  - finalize: a recurring offer needs a verified payment method even when due-now/total is 0 (trial or fully discounted first period). Only a free one-time purchase finalizes without one. Live docs still say "unless 0 ISK" — ignore that; bundled OpenAPI is right.
57
58
  - Hosted POST /v2/checkouts/: shipping {option, location_id?} is required when the offer has physical products and the account has active shipping options. No shipping-options list in OpenAPI (ids are account config). Pickup options need location_id. Snapshot is contract.shipping_selection, not on V2Checkout.
59
+ - Hosted iframe (not askell.js): POST /v2/checkouts/ and POST .../payment-method-registrations/ take allowed_origin (one origin, no path; http only localhost/loopback). Replaces account-level frame-ancestors; GET empty string = account-level. Rejected on /v2/checkout-sessions/ (sales-channel allowed_origins[]).
58
60
  - Embedded checkout uses POST /v2/checkout-sessions/ plus browser session-token sub-paths (widget collects address/shipping; see docs, not all in OpenAPI).
59
61
 
60
62
  Auth:
@@ -141,7 +141,7 @@ export function registerAnalysisTools(
141
141
  {
142
142
  title: 'Subscription contract overview (v2)',
143
143
  description:
144
- 'Fetch a v2 subscription contract and recent billing runs filtered by contract id. The contract payload includes `discount` (active coupon) when one is applied, and `shipping_selection` when shipping was chosen at checkout.',
144
+ 'Fetch a v2 subscription contract and recent billing runs filtered by contract id. The contract payload includes `discount` (active coupon) when one is applied, `shipping_selection` when shipping was chosen at checkout, and `subscriber_page` (customer-facing management URL, read-only).',
145
145
  inputSchema: z.object({
146
146
  contractId: z
147
147
  .union([z.string().min(1), z.int()])