askell-mcp 0.4.18 → 0.4.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "askell-mcp",
3
- "version": "0.4.18",
3
+ "version": "0.4.20",
4
4
  "mcpName": "io.github.Neschadin/askell-mcp",
5
5
  "description": "MCP server for the Askell payment and subscription API (Bun + stdio)",
6
6
  "author": "Neschadin Oleksandr",
@@ -36,7 +36,7 @@
36
36
  "mcp.json.example"
37
37
  ],
38
38
  "engines": {
39
- "bun": ">=1.4.0"
39
+ "bun": ">=1.4.2"
40
40
  },
41
41
  "publishConfig": {
42
42
  "access": "public",
@@ -747,7 +747,7 @@
747
747
  "V2 Subscription Contracts"
748
748
  ],
749
749
  "summary": "Preview a V2 subscription contract proration",
750
- "description": "Previews the proration impact of updating an existing V2 subscription contract item. With `operation=update_item`, `apply_at` selects when the change takes effect: `now` (default) prorates from `effective_at`, which must not be in the future (a future value returns a 400 with code `future_effective_at_not_supported`); `period_end` previews a change scheduled for the item's next renewal (nothing due now, no lines, `next_billing_estimate` at the new values, and `scheduled_for`). An immediate change to a price with a different billing interval credits the unused current period, charges a full new period from `effective_at` and restarts the item's billing period (single-item contracts only, settled with `invoice_now`). update_item previews also return `next_billing_at_after_change` and `billing_cadence_after_change`. Requires a secret key.",
750
+ "description": "Previews the proration impact of updating an existing V2 subscription contract item. With `operation=update_item`, `apply_at` selects when the change takes effect: `now` (default) prorates from `effective_at`, which must not be in the future (a future value returns a 400 with code `future_effective_at_not_supported`); `period_end` previews a change scheduled for the item's next renewal (nothing due now, no lines, `next_billing_estimate` at the new values, and `scheduled_for`). An immediate change to a price with a different billing interval credits the unused current period, charges a full new period from `effective_at` and restarts the item's billing period (single-item contracts only, settled with `invoice_now`). update_item previews also return `next_billing_at_after_change`, `billing_cadence_after_change` and `applies_on_payment` (send the same `apply_on_payment` as the update: a preview token only validates an update with the same value). Requires a secret key.",
751
751
  "parameters": [
752
752
  {
753
753
  "$ref": "#/components/parameters/V2ContractId"
@@ -794,7 +794,7 @@
794
794
  "V2 Subscription Contracts"
795
795
  ],
796
796
  "summary": "Update a V2 subscription contract item with proration",
797
- "description": "Updates an existing V2 subscription contract item. With `apply_at=now` (default) the change applies immediately and `effective_at` only positions the proration window, so it must not be in the future (a future value returns a 400 with code `future_effective_at_not_supported`). With `apply_at=period_end` nothing is changed or charged now: the change is stored as a scheduled change (returned in `scheduled_change`, with `change_id` null) and applied to the item when its next renewal billing run is created. `effective_at`, `settlement_behavior` and `include_pending_adjustments` cannot be combined with `period_end`. An item with a pending scheduled change rejects further updates with a 409 (`scheduled_change_exists`) until it is canceled. An immediate billing-interval change with an amount due only switches the item once its proration run is collected (`applies_on_payment: true`, item `pending_interval_change`); meanwhile other changes to the item return a 409 (`pending_interval_change`). Requires a secret key.",
797
+ "description": "Updates an existing V2 subscription contract item. With `apply_at=now` (default) the change applies immediately and `effective_at` only positions the proration window, so it must not be in the future (a future value returns a 400 with code `future_effective_at_not_supported`). With `apply_at=period_end` nothing is changed or charged now: the change is stored as a scheduled change (returned in `scheduled_change`, with `change_id` null) and applied to the item when its next renewal billing run is created. `effective_at`, `settlement_behavior` and `include_pending_adjustments` cannot be combined with `period_end`. An item with a pending scheduled change rejects further updates with a 409 (`scheduled_change_exists`) until it is canceled. An immediate billing-interval change with an amount due only switches the item once its proration run is collected (`applies_on_payment: true`, item `pending_interval_change` and `pending_change`); meanwhile other changes to the item return a 409 (`pending_interval_change`). With `apply_on_payment: true` a same-interval change (for example an upgrade) waits for its charge the same way, keeping the item's billing schedule: the item stays on its current values and shows the change in `pending_change`, its renewal is held, other changes to it (and `change-anchor`) return a 409 (`pending_change`), and a terminal payment failure leaves it unchanged. A later manual retry that succeeds still applies it unless the item was changed or its renewal billed in the meantime; the payment is then credited to the contract balance. `apply_on_payment` needs `invoice_now` (400 `apply_on_payment_requires_invoice_now`) and cannot be combined with `period_end` (400 `invalid_apply_at`). Requires a secret key.",
798
798
  "parameters": [
799
799
  {
800
800
  "$ref": "#/components/parameters/V2ContractId"
@@ -3528,7 +3528,12 @@
3528
3528
  "period_end"
3529
3529
  ],
3530
3530
  "default": "now",
3531
- "description": "Only applies to update_item. `now` changes the item immediately with proration; `period_end` schedules the change for the item's next renewal (cannot be combined with `effective_at`, `settlement_behavior` or `include_pending_adjustments`)."
3531
+ "description": "Only applies to update_item. `now` changes the item immediately with proration; `period_end` schedules the change for the item's next renewal (cannot be combined with `effective_at`, `settlement_behavior`, `include_pending_adjustments` or `apply_on_payment`)."
3532
+ },
3533
+ "apply_on_payment": {
3534
+ "type": "boolean",
3535
+ "default": false,
3536
+ "description": "Only applies to update_item with `apply_at=now`. When true, a same-interval change with an amount due switches the item only once its proration run is collected (`applies_on_payment`), settled with `invoice_now` (the default then; `next_invoice` returns a 400 with code `apply_on_payment_requires_invoice_now`). A change with nothing to collect applies at once. A billing-interval change always waits for its payment."
3532
3537
  }
3533
3538
  }
3534
3539
  }
@@ -3705,6 +3710,11 @@
3705
3710
  "default": "now",
3706
3711
  "description": "`now` changes the item immediately with proration; `period_end` keeps the current price until the item's current service period ends and applies the change at the next renewal, with no refund or charge now."
3707
3712
  },
3713
+ "apply_on_payment": {
3714
+ "type": "boolean",
3715
+ "default": false,
3716
+ "description": "With `apply_at=now`, keep the item on its current values until the change's proration run is collected, as a billing-interval change always does: the response returns `applies_on_payment: true` and the item shows the change in `pending_change`, its renewal is held meanwhile, and a terminal payment failure leaves the item unchanged. Settled with `invoice_now` (the default then; `next_invoice` returns a 400 with code `apply_on_payment_requires_invoice_now`); cannot be combined with `apply_at=period_end`. A change with nothing to collect (no proration, a downgrade, or a charge fully covered) applies at once. Defaults to false: the item is switched now and the charge collected afterwards."
3717
+ },
3708
3718
  "idempotency_key": {
3709
3719
  "type": "string",
3710
3720
  "nullable": true
@@ -3891,7 +3901,7 @@
3891
3901
  },
3892
3902
  "applies_on_payment": {
3893
3903
  "type": "boolean",
3894
- "description": "update_item only. True for an immediate billing-interval change with an amount due: the item switches only once that charge is collected."
3904
+ "description": "update_item only. True for an immediate billing-interval change, or a change sent with `apply_on_payment`, with an amount due: the item switches only once that charge is collected."
3895
3905
  }
3896
3906
  }
3897
3907
  },
@@ -4029,7 +4039,7 @@
4029
4039
  },
4030
4040
  "applies_on_payment": {
4031
4041
  "type": "boolean",
4032
- "description": "True when an immediate billing-interval change waits for `billing_run_id` to be collected; until then the item keeps its current price and shows the change in `pending_interval_change`."
4042
+ "description": "True when the change waits for `billing_run_id` to be collected (an immediate billing-interval change, or a change sent with `apply_on_payment`); until then the item keeps its current values and shows the change in `pending_change` (and, for an interval change, in `pending_interval_change`)."
4033
4043
  },
4034
4044
  "billing_run_id": {
4035
4045
  "type": "integer",
@@ -4091,6 +4101,12 @@
4091
4101
  ],
4092
4102
  "description": "Stored on the checkout and copied to the created contract's `metadata` when the checkout is finalized. In a checkout session the session's own metadata wins on a shared key, and the sales channel's `metadata_policy.frontend_allowed_keys` limits the keys the browser may send (with no such list any key is accepted, and an empty list accepts none). Keys Askell uses itself (`askell_source`, `billing_anchor_mode`, `activation_failure`, `email_markers`, `copied_legacy_pauses`, `copied_legacy_extra_data`, `migration_source`, `migration_cadence_mode`, `legacy_subscription_ids`, `seed`) are not copied."
4093
4103
  },
4104
+ "contract_reference": {
4105
+ "type": "string",
4106
+ "nullable": true,
4107
+ "maxLength": 128,
4108
+ "description": "Your reference for the subscription contract this checkout creates, such as your order number. Copied to the contract's `reference` when the contract is created on finalize, so it is in every `subscription_contract.*` webhook, `subscription_contract.created` included, and `GET /api/v2/subscription-contracts/?reference=` finds the contract. Must not contain commas; not unique. Surrounding whitespace is trimmed and a blank value means no reference. Not accepted on checkout-session endpoints: there the seller's backend sets `contract_reference` when it creates the session."
4109
+ },
4094
4110
  "delivery_address": {
4095
4111
  "$ref": "#/components/schemas/V2Address",
4096
4112
  "description": "Optional delivery-address snapshot for physical products or alternate delivery."
@@ -4421,6 +4437,12 @@
4421
4437
  "type": "string",
4422
4438
  "description": "Seller customer reference. If an existing customer has this reference, the session is bound to that customer."
4423
4439
  },
4440
+ "contract_reference": {
4441
+ "type": "string",
4442
+ "nullable": true,
4443
+ "maxLength": 128,
4444
+ "description": "Your reference for the subscription contract this session creates, such as your order number. Copied to the contract's `reference` when the contract is created on finalize, so it is in every `subscription_contract.*` webhook, `subscription_contract.created` included, and `GET /api/v2/subscription-contracts/?reference=` finds the contract. Must not contain commas; not unique. Surrounding whitespace is trimmed and a blank value means no reference. Only settable here, with a secret key: the browser cannot set it and the public session payload does not include it."
4445
+ },
4424
4446
  "metadata": {
4425
4447
  "allOf": [
4426
4448
  {
@@ -4497,6 +4519,11 @@
4497
4519
  },
4498
4520
  "metadata": {
4499
4521
  "$ref": "#/components/schemas/V2Metadata"
4522
+ },
4523
+ "contract_reference": {
4524
+ "type": "string",
4525
+ "nullable": true,
4526
+ "description": "The reference the contract gets when this session's checkout is finalized; `null` when none was given."
4500
4527
  }
4501
4528
  }
4502
4529
  },
@@ -4871,6 +4898,11 @@
4871
4898
  "metadata": {
4872
4899
  "$ref": "#/components/schemas/V2Metadata"
4873
4900
  },
4901
+ "contract_reference": {
4902
+ "type": "string",
4903
+ "nullable": true,
4904
+ "description": "The `contract_reference` given when this checkout was created, or `null`. Always `null` for a checkout created in a checkout session, whose contract takes the session's `contract_reference` instead."
4905
+ },
4874
4906
  "allowed_origin": {
4875
4907
  "type": "string",
4876
4908
  "description": "Origin allowed to embed hosted pages for this checkout, or an empty string when the account-level checkout origins apply."
@@ -5341,7 +5373,7 @@
5341
5373
  "pending_interval_change": {
5342
5374
  "type": "object",
5343
5375
  "nullable": true,
5344
- "description": "An immediate billing-interval change waiting for its charge to be collected; the item switches when the billing run succeeds.",
5376
+ "description": "An immediate billing-interval change waiting for its charge to be collected; the item switches when the billing run succeeds. Null for a same-interval change made with `apply_on_payment`, which only shows in `pending_change`.",
5345
5377
  "properties": {
5346
5378
  "change_id": {
5347
5379
  "type": "integer"
@@ -5381,6 +5413,56 @@
5381
5413
  "format": "date-time"
5382
5414
  }
5383
5415
  }
5416
+ },
5417
+ "pending_change": {
5418
+ "type": "object",
5419
+ "nullable": true,
5420
+ "description": "Any change on the item waiting for its charge to be collected: an immediate billing-interval change, or a same-interval change made with `apply_on_payment`. The item keeps its current values (and its renewal is held) until the billing run succeeds; if it fails terminally the item is left unchanged.",
5421
+ "properties": {
5422
+ "change_id": {
5423
+ "type": "integer"
5424
+ },
5425
+ "billing_run_id": {
5426
+ "type": "integer",
5427
+ "nullable": true
5428
+ },
5429
+ "status": {
5430
+ "type": "string",
5431
+ "enum": [
5432
+ "awaiting_payment"
5433
+ ]
5434
+ },
5435
+ "price_id": {
5436
+ "type": "integer"
5437
+ },
5438
+ "quantity": {
5439
+ "type": "integer"
5440
+ },
5441
+ "discount_percent": {
5442
+ "type": "string",
5443
+ "format": "decimal",
5444
+ "nullable": true
5445
+ },
5446
+ "unit_amount_override": {
5447
+ "type": "string",
5448
+ "format": "decimal",
5449
+ "nullable": true
5450
+ },
5451
+ "effective_at": {
5452
+ "type": "string",
5453
+ "format": "date-time"
5454
+ },
5455
+ "next_billing_at": {
5456
+ "type": "string",
5457
+ "format": "date-time",
5458
+ "nullable": true,
5459
+ "description": "The item's next billing once the change applies: the end of the new period for an interval change, the current renewal otherwise."
5460
+ },
5461
+ "interval_change": {
5462
+ "type": "boolean",
5463
+ "description": "True for a billing-interval change (also shown in `pending_interval_change`), false for a same-interval change made with `apply_on_payment`."
5464
+ }
5465
+ }
5384
5466
  }
5385
5467
  }
5386
5468
  },
@@ -6242,7 +6324,7 @@
6242
6324
  "type": "string",
6243
6325
  "nullable": true,
6244
6326
  "maxLength": 128,
6245
- "description": "The contract's reference in an external system, such as the seller's order number. V2 payment pages set it from their `subscription_reference` URL parameter."
6327
+ "description": "The contract's reference in an external system, such as the seller's order number. V2 payment pages set it from their `subscription_reference` URL parameter, and checkouts from the `contract_reference` given when the checkout session, or a checkout without a session, was created."
6246
6328
  },
6247
6329
  "shipping_selection": {
6248
6330
  "$ref": "#/components/schemas/V2ShippingSelection"
@@ -7575,7 +7657,7 @@
7575
7657
  }
7576
7658
  },
7577
7659
  "V2ProrationConflict": {
7578
- "description": "Conflict, e.g. `scheduled_change_exists`, `pending_interval_change`, `scheduled_change_not_cancelable`, `idempotency_key_conflict`, `preview_stale`, `billing_run_overlap`",
7660
+ "description": "Conflict, e.g. `scheduled_change_exists`, `pending_interval_change`, `pending_change`, `scheduled_change_not_cancelable`, `idempotency_key_conflict`, `preview_stale`, `billing_run_overlap`",
7579
7661
  "content": {
7580
7662
  "application/json": {
7581
7663
  "schema": {
package/src/server.ts CHANGED
@@ -59,14 +59,16 @@ V2 checkout notes:
59
59
  - 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 (plus location / zone_name / weight_band), not on V2Checkout. Rate-table option with no zip/weight rate: 400, shipping_code shipping_not_available. Quote/checkout totals already include shipping_fee when present.
60
60
  - 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[]).
61
61
  - Embedded checkout uses POST /v2/checkout-sessions/ plus browser session-token sub-paths (widget collects address/shipping; see docs, not all in OpenAPI).
62
+ - contract_reference (max 128, no commas, blank or null means none, not unique): the seller backend sets it on POST /v2/checkouts/ (no session) or POST /v2/checkout-sessions/ (secret). Copied to contract.reference when the contract is created, so it is already on subscription_contract.created and GET /v2/subscription-contracts/?reference= returns a list. Do not PATCH reference afterwards — too late for subscription_contract.created. The browser cannot set it: sending contract_reference while creating a checkout in the session is 400, and it is absent from the public session payload and browser responses. A checkout created inside a session has contract_reference null; the contract takes the session's value. GET /v2/checkout-sessions/{token}/ returns the session reference; GET /v2/checkouts/{token}/ returns the checkout's.
62
63
  - Checkout/session metadata is copied onto the contract at finalize except Askell-owned keys (askell_source, billing_anchor_mode, activation_failure, email_markers, copied_legacy_pauses, copied_legacy_extra_data, migration_source, migration_cadence_mode, legacy_subscription_ids, seed). On a shared key the session value wins.
63
64
 
64
65
  V2 contract changes:
65
- - reference: external id, max 128, no commas. Create: blank means none. PATCH null/blank clears. GET /v2/subscription-contracts/?reference= is an exact filter.
66
+ - reference: external id, max 128, no commas, not unique. Create: blank means none. PATCH null/blank clears. GET /v2/subscription-contracts/?reference= is an exact filter. For a checkout-created contract, set contract_reference on the checkout or session (checkout notes); a later PATCH misses subscription_contract.created.
66
67
  - PATCH body is only metadata, reference, payment_processor_override. The operation description also lists delivery_address, accounting_department, accounting_cost_center; V2SubscriptionContractPatch does not include them — do not send them.
67
68
  - PATCH metadata replaces the integration's keys. The Askell-owned keys above keep their current values; sending them does nothing.
68
- - items/update apply_at=now (default): effective_at must not be in the future (400 future_effective_at_not_supported). apply_at=period_end charges nothing now and stores scheduled_change (change_id null); do not send effective_at, settlement_behavior, or include_pending_adjustments with it. A pending scheduled change rejects further item updates with 409 scheduled_change_exists until POST .../scheduled-changes/{scheduledChangeId}/cancel/ (already canceled → replayed: true; applied/failed → 409 scheduled_change_not_cancelable). items/add and items/remove can also 409 (V2ProrationConflict); their operation text does not say so. Webhook families subscription_contract_scheduled_change.* and subscription_contract_item.* are not part of subscription_contract.*. Non-migrated contract events match GET: customer is an object, numeric id is customer_id. A scheduled cancellation sends subscription_contract.ended, not canceled, even though state becomes canceled.
69
- - An immediate billing-interval change with an amount due sets item.pending_interval_change status awaiting_payment (applies_on_payment). The item switches only when that billing run succeeds. Other item edits and change-anchor return 409 pending_interval_change until then. A failed payment abandons the interval change; retrying the run does not apply it.
69
+ - items/update apply_at=now (default): effective_at must not be in the future (400 future_effective_at_not_supported). apply_at=period_end charges nothing now and stores scheduled_change (change_id null); do not send effective_at, settlement_behavior, include_pending_adjustments, or apply_on_payment with it (apply_on_payment → 400 invalid_apply_at). A pending scheduled change rejects further item updates with 409 scheduled_change_exists until POST .../scheduled-changes/{scheduledChangeId}/cancel/ (already canceled → replayed: true; applied/failed → 409 scheduled_change_not_cancelable). items/add and items/remove can also 409 (V2ProrationConflict); their operation text does not say so. Webhook families subscription_contract_scheduled_change.* and subscription_contract_item.* are not part of subscription_contract.*. Non-migrated contract events match GET: customer is an object, numeric id is customer_id. A scheduled cancellation sends subscription_contract.ended, not canceled, even though state becomes canceled.
70
+ - An immediate billing-interval change with an amount due sets item.pending_interval_change and item.pending_change (interval_change true, status awaiting_payment, applies_on_payment). The item switches only when that billing run succeeds. Other item edits and change-anchor return 409 pending_interval_change until then. A failed payment abandons the interval change; retrying the run does not apply it.
71
+ - apply_on_payment (default false; items/update and proration-preview; apply_at=now only): false switches the item now and collects afterwards. true keeps the current values until the proration run is collected, without moving the billing schedule. Same-interval (an upgrade): pending_interval_change is null; the wait is only pending_change (interval_change false, status awaiting_payment). Renewal is held. Other item edits and change-anchor return 409 pending_change — change-anchor's operation text only names pending_interval_change. Needs invoice_now (400 apply_on_payment_requires_invoice_now). Nothing to collect (no proration, a downgrade, or a charge fully covered) applies at once. A terminal failure leaves the item unchanged; a later manual retry that succeeds still applies the change unless the item was changed or its renewal billed in the meantime, in which case the payment is credited to the contract balance. Send the same apply_on_payment on proration-preview: a preview token only validates an update with the same value.
70
72
  - POST .../change-anchor/ moves the next renewal of the contract and every active item. new_billing_anchor_at must be after effective_at and, with proration, at most one billing period later. Does not extend entitlements. Preview with proration-preview operation=change_anchor (new_billing_anchor_at required). Do not PATCH billing_anchor_at.
71
73
 
72
74
  V2 refunds:
@@ -218,7 +218,7 @@ export function registerAnalysisTools(
218
218
  {
219
219
  title: 'Subscription contract overview (v2)',
220
220
  description:
221
- '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, `subscriber_page` (customer-facing management URL, read-only), `reference`, `scheduled_changes`, and per-item `scheduled_change` / `pending_interval_change` (status `awaiting_payment` while an interval change waits for its charge). Result is an error when the contract fetch fails. `failures` lists every call that failed.',
221
+ '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, `subscriber_page` (customer-facing management URL, read-only), `reference`, `scheduled_changes`, and per-item `scheduled_change` / `pending_interval_change` / `pending_change` (status `awaiting_payment` while a change waits for its charge). An interval change sets both; a same-interval `apply_on_payment` change sets only `pending_change` (`pending_interval_change` is null). Result is an error when the contract fetch fails. `failures` lists every call that failed.',
222
222
  inputSchema: z.object({
223
223
  contractId: z
224
224
  .union([z.string().min(1), z.int()])