@diviops/mcp-server 1.5.19 → 1.5.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/README.md +2 -0
- package/dist/index.js +334 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,8 @@ Additional **conditionally-registered Pro tools** appear only on sites that have
|
|
|
86
86
|
| FluentCart simple product writes (V2) | Pro plugin + FluentCart installed + module enabled | `diviops_fc_product_create`, `diviops_fc_product_update`, `diviops_fc_product_delete` |
|
|
87
87
|
| FluentCart variation read/write (V3) | Pro plugin + FluentCart installed + module enabled | `diviops_fc_variation_list`, `diviops_fc_variation_update` |
|
|
88
88
|
| FluentCart license-settings read/write (V3) | Pro plugin + FluentCart Pro installed + module enabled | `diviops_fc_license_settings_get`, `diviops_fc_license_settings_update` |
|
|
89
|
+
| FluentCart order readback + guarded mark-paid (V3.1) | Pro plugin + FluentCart installed + module enabled | `diviops_fc_order_list`, `diviops_fc_order_get`, `diviops_fc_order_mark_paid` |
|
|
90
|
+
| FluentCart license readback (V3.1) | Pro plugin + FluentCart Pro installed + module enabled | `diviops_fc_license_list`, `diviops_fc_license_get`, `diviops_fc_license_activations_list` |
|
|
89
91
|
|
|
90
92
|
When the gates are not satisfied, the tools simply don't appear on the MCP surface — no error envelope, no missing-capability hint. See the `diviops-fluentcart` skill bundle for the operator-side guide.
|
|
91
93
|
|
package/dist/index.js
CHANGED
|
@@ -3559,6 +3559,340 @@ function registerProTools() {
|
|
|
3559
3559
|
target: "fluentcart",
|
|
3560
3560
|
capabilityKey: "fluentcart_license_settings_update",
|
|
3561
3561
|
});
|
|
3562
|
+
// ── V3.1 — order/license/activation read + guarded mark-paid ───────
|
|
3563
|
+
//
|
|
3564
|
+
// FluentCart commerce-artifact readback surface plus a single
|
|
3565
|
+
// mutating tool: a guarded offline mark-paid that mirrors FCP's
|
|
3566
|
+
// OrderController::markAsPaid. Lifts the local checkout/license
|
|
3567
|
+
// smoke off of eval-file PHP probes.
|
|
3568
|
+
// diviops_fc_order_list — POST /diviops/v1/pro/fluentcart/orders
|
|
3569
|
+
registerProTool("diviops_fc_order_list", {
|
|
3570
|
+
description: "List FluentCart orders for commerce dogfooding / smoke baselines (Pro tier; V3.1; requires FluentCart installed + activated). Returns a paginated summary with order identity (id, status, payment_status), gateway info (payment_method + payment_method_title, mode), totals (currency, total_amount, total_paid), fulfillment_type, type (payment/subscription), customer (customer_id + customer_email), item_count, license_count, and timestamps (created_at, updated_at, completed_at). Filterable by status, payment_status, payment_method, product_id, customer_email, and mode (test/live). Read-only. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }; the success payload is { orders: OrderSummary[], pagination: { page, per_page, total, total_pages }, filters: { ... } }. Error codes: invalid_input (HTTP 400) when status/payment_status/mode is out of range; fluentcart.module_inactive (HTTP 412); fluentcart.query_failed (HTTP 500). Use this alongside diviops_fc_order_get / diviops_fc_license_list to verify a smoke run without raw SQL probes.",
|
|
3571
|
+
inputSchema: {
|
|
3572
|
+
page: z
|
|
3573
|
+
.number()
|
|
3574
|
+
.int()
|
|
3575
|
+
.positive()
|
|
3576
|
+
.optional()
|
|
3577
|
+
.default(1)
|
|
3578
|
+
.describe("Page number, 1-indexed. Default 1."),
|
|
3579
|
+
per_page: z
|
|
3580
|
+
.number()
|
|
3581
|
+
.int()
|
|
3582
|
+
.positive()
|
|
3583
|
+
.optional()
|
|
3584
|
+
.default(20)
|
|
3585
|
+
.describe("Page size. Default 20, clamped to a max of 100."),
|
|
3586
|
+
status: z
|
|
3587
|
+
.enum([
|
|
3588
|
+
"on-hold",
|
|
3589
|
+
"pending",
|
|
3590
|
+
"processing",
|
|
3591
|
+
"completed",
|
|
3592
|
+
"canceled",
|
|
3593
|
+
"refunded",
|
|
3594
|
+
"failed",
|
|
3595
|
+
"draft",
|
|
3596
|
+
])
|
|
3597
|
+
.optional()
|
|
3598
|
+
.describe("Order status filter (fct_orders.status). Match exact values such as 'completed' or 'on-hold'."),
|
|
3599
|
+
payment_status: z
|
|
3600
|
+
.enum([
|
|
3601
|
+
"pending",
|
|
3602
|
+
"paid",
|
|
3603
|
+
"partially_paid",
|
|
3604
|
+
"partially_refunded",
|
|
3605
|
+
"refunded",
|
|
3606
|
+
"failed",
|
|
3607
|
+
])
|
|
3608
|
+
.optional()
|
|
3609
|
+
.describe("Payment status filter (fct_orders.payment_status)."),
|
|
3610
|
+
payment_method: z
|
|
3611
|
+
.string()
|
|
3612
|
+
.optional()
|
|
3613
|
+
.describe("Exact-match payment_method (e.g. 'offline_payment', 'stripe'). Case-sensitive — FluentCart stores gateway slugs verbatim."),
|
|
3614
|
+
product_id: z
|
|
3615
|
+
.number()
|
|
3616
|
+
.int()
|
|
3617
|
+
.positive()
|
|
3618
|
+
.optional()
|
|
3619
|
+
.describe("FluentCart product ID (post_id of the fluent_products CPT entry). Filters to orders with at least one matching order item."),
|
|
3620
|
+
customer_email: z
|
|
3621
|
+
.string()
|
|
3622
|
+
.optional()
|
|
3623
|
+
.describe("Filter to orders whose customer record has this email (exact match)."),
|
|
3624
|
+
mode: z
|
|
3625
|
+
.enum(["test", "live"])
|
|
3626
|
+
.optional()
|
|
3627
|
+
.describe("Filter to test-mode or live-mode orders. Useful for smoke runs to isolate the test gateway corpus."),
|
|
3628
|
+
},
|
|
3629
|
+
annotations: { idempotentHint: true },
|
|
3630
|
+
_meta: { idempotent: "true" },
|
|
3631
|
+
}, async ({ page, per_page, status, payment_status, payment_method, product_id, customer_email, mode, }) => {
|
|
3632
|
+
const body = {};
|
|
3633
|
+
if (page !== undefined)
|
|
3634
|
+
body.page = page;
|
|
3635
|
+
if (per_page !== undefined)
|
|
3636
|
+
body.per_page = per_page;
|
|
3637
|
+
if (status !== undefined)
|
|
3638
|
+
body.status = status;
|
|
3639
|
+
if (payment_status !== undefined)
|
|
3640
|
+
body.payment_status = payment_status;
|
|
3641
|
+
if (payment_method !== undefined)
|
|
3642
|
+
body.payment_method = payment_method;
|
|
3643
|
+
if (product_id !== undefined)
|
|
3644
|
+
body.product_id = product_id;
|
|
3645
|
+
if (customer_email !== undefined)
|
|
3646
|
+
body.customer_email = customer_email;
|
|
3647
|
+
if (mode !== undefined)
|
|
3648
|
+
body.mode = mode;
|
|
3649
|
+
const result = await wp.requestEnveloped("/pro/fluentcart/orders", {
|
|
3650
|
+
method: "POST",
|
|
3651
|
+
body,
|
|
3652
|
+
});
|
|
3653
|
+
return {
|
|
3654
|
+
content: [
|
|
3655
|
+
{
|
|
3656
|
+
type: "text",
|
|
3657
|
+
text: serializeEnvelope(result, "diviops_fc_order_list"),
|
|
3658
|
+
},
|
|
3659
|
+
],
|
|
3660
|
+
};
|
|
3661
|
+
}, { target: "fluentcart", capabilityKey: "fluentcart_order_list" });
|
|
3662
|
+
// diviops_fc_order_get — POST /diviops/v1/pro/fluentcart/orders/{id}
|
|
3663
|
+
registerProTool("diviops_fc_order_get", {
|
|
3664
|
+
description: "Fetch a single FluentCart order with line items, transactions, and related license IDs (Pro tier; V3.1; requires FluentCart installed + activated). Read-only. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }; the success payload is { order: OrderSummary, items: OrderItem[], transactions: Transaction[], license_ids: number[] }. OrderItem includes id, post_id (product CPT post_id), object_id (variation_id), title, quantity, unit_price, line_total, payment_type, fulfillment_type. Transaction includes id, status, payment_method, payment_mode, transaction_type, total, currency, created_at. license_ids carries the IDs of any fct_licenses rows tied to this order (use diviops_fc_license_get to fetch each row's redacted shape). Does NOT expose payment credentials, gateway secrets, or full license keys. Error codes: invalid_input (HTTP 400) when id is not a positive integer; not_found (HTTP 404) when no order matches; fluentcart.module_inactive (HTTP 412); fluentcart.query_failed (HTTP 500).",
|
|
3665
|
+
inputSchema: {
|
|
3666
|
+
id: z
|
|
3667
|
+
.number()
|
|
3668
|
+
.int()
|
|
3669
|
+
.positive()
|
|
3670
|
+
.describe("FluentCart order ID (fct_orders.id; for the local smoke runbook this is the order receipt anchor)."),
|
|
3671
|
+
},
|
|
3672
|
+
annotations: { idempotentHint: true },
|
|
3673
|
+
_meta: { idempotent: "true" },
|
|
3674
|
+
}, async ({ id }) => {
|
|
3675
|
+
const result = await wp.requestEnveloped(`/pro/fluentcart/orders/${id}`, { method: "POST" });
|
|
3676
|
+
return {
|
|
3677
|
+
content: [
|
|
3678
|
+
{
|
|
3679
|
+
type: "text",
|
|
3680
|
+
text: serializeEnvelope(result, "diviops_fc_order_get"),
|
|
3681
|
+
},
|
|
3682
|
+
],
|
|
3683
|
+
};
|
|
3684
|
+
}, { target: "fluentcart", capabilityKey: "fluentcart_order_get" });
|
|
3685
|
+
// diviops_fc_order_mark_paid — POST /diviops/v1/pro/fluentcart/orders/{id}/mark-paid
|
|
3686
|
+
registerProTool("diviops_fc_order_mark_paid", {
|
|
3687
|
+
description: "Guarded local/offline mark-paid for a FluentCart order (Pro tier; V3.1; requires FluentCart installed + activated). Mirrors the canonical `FluentCart\\App\\Http\\Controllers\\OrderController::markAsPaid` sequence — updates the pending offline transaction, flips payment_status to 'paid' (unless partially_refunded), flips order status to 'processing' (and 'completed' for digital fulfillment), then dispatches `OrderPaid` (which fires the `fluent_cart/order_paid` WordPress action, the listener `LicenseGenerationHandler::maybeGenerateLicensesOnPurchaseSuccess` hangs off of) plus `OrderStatusUpdated`. Does NOT directly insert license rows — license generation is a side effect of the dispatched event, exactly like the FCP admin path. Refuses non-offline gateways (anything other than `payment_method='offline_payment'`) with `fluentcart.unsupported_payment_method` (HTTP 422) — this slice is for local/test/COD smokes only. Refuses canceled orders with `fluentcart.order_canceled` (HTTP 422). Already-paid orders are repeat-safe: returns `ok:true` with `data.already_paid: true` (no second event fires). **dry_run defaults to TRUE** for safety; apply requires `dry_run:false` PLUS `confirm_order_id` + `confirm_payment_method` + `confirm_due_amount` matching current state. Dry-run payload: { dry_run:true, plan: { summary, changes[] (payment_status, status, total_paid, transaction), warnings[] }, events: ['fluent_cart/order_paid', 'fluent_cart/order_status_updated'], order_id, licenses_before }. Apply payload: { order: OrderSummary (post-mutation), transaction: TransactionSummary, events_fired: string[], licenses_before, licenses_after, licenses_created, license_ids: number[], licenses: LicenseRedactedSummary[] (no full keys). Error codes: invalid_input (400) when id/confirmation fields are wrong; not_found (404); fluentcart.order_canceled (422); fluentcart.unsupported_payment_method (422); fluentcart.module_inactive (412); fluentcart.command_failed (500). Idempotency: repeat-safe via already_paid sentinel." +
|
|
3688
|
+
" Pass dry_run: false plus the confirm_* fields to apply.",
|
|
3689
|
+
inputSchema: {
|
|
3690
|
+
id: z
|
|
3691
|
+
.number()
|
|
3692
|
+
.int()
|
|
3693
|
+
.positive()
|
|
3694
|
+
.describe("FluentCart order ID (fct_orders.id) to mark paid."),
|
|
3695
|
+
dry_run: z
|
|
3696
|
+
.boolean()
|
|
3697
|
+
.optional()
|
|
3698
|
+
.default(true)
|
|
3699
|
+
.describe("When true (default), return the change plan without mutating state. Apply requires explicit dry_run: false + the confirm_* fields."),
|
|
3700
|
+
confirm_order_id: z
|
|
3701
|
+
.number()
|
|
3702
|
+
.int()
|
|
3703
|
+
.positive()
|
|
3704
|
+
.optional()
|
|
3705
|
+
.describe("Apply-mode confirmation: must equal `id`. Prevents accidentally marking the wrong order paid."),
|
|
3706
|
+
confirm_payment_method: z
|
|
3707
|
+
.string()
|
|
3708
|
+
.optional()
|
|
3709
|
+
.describe("Apply-mode confirmation: must equal the order's current payment_method (e.g. 'offline_payment')."),
|
|
3710
|
+
confirm_due_amount: z
|
|
3711
|
+
.number()
|
|
3712
|
+
.int()
|
|
3713
|
+
.min(0)
|
|
3714
|
+
.optional()
|
|
3715
|
+
.describe("Apply-mode confirmation: must equal (total_amount - total_paid) in stored units (cents). Inspect via diviops_fc_order_get."),
|
|
3716
|
+
mark_paid_note: z
|
|
3717
|
+
.string()
|
|
3718
|
+
.optional()
|
|
3719
|
+
.describe("Optional sanitize_text_field note to attach to the order's `note` column. Mirrors the admin mark-paid form field."),
|
|
3720
|
+
},
|
|
3721
|
+
annotations: { idempotentHint: false },
|
|
3722
|
+
_meta: { idempotent: "conditional" },
|
|
3723
|
+
}, async ({ id, dry_run, confirm_order_id, confirm_payment_method, confirm_due_amount, mark_paid_note, }) => {
|
|
3724
|
+
const body = {};
|
|
3725
|
+
// dry_run defaults to true at the MCP level — pass through whatever
|
|
3726
|
+
// the caller sent so the plugin can apply the same default.
|
|
3727
|
+
if (dry_run !== undefined)
|
|
3728
|
+
body.dry_run = dry_run;
|
|
3729
|
+
else
|
|
3730
|
+
body.dry_run = true;
|
|
3731
|
+
if (confirm_order_id !== undefined)
|
|
3732
|
+
body.confirm_order_id = confirm_order_id;
|
|
3733
|
+
if (confirm_payment_method !== undefined)
|
|
3734
|
+
body.confirm_payment_method = confirm_payment_method;
|
|
3735
|
+
if (confirm_due_amount !== undefined)
|
|
3736
|
+
body.confirm_due_amount = confirm_due_amount;
|
|
3737
|
+
if (mark_paid_note !== undefined)
|
|
3738
|
+
body.mark_paid_note = mark_paid_note;
|
|
3739
|
+
const result = await wp.requestEnveloped(`/pro/fluentcart/orders/${id}/mark-paid`, { method: "POST", body });
|
|
3740
|
+
return {
|
|
3741
|
+
content: [
|
|
3742
|
+
{
|
|
3743
|
+
type: "text",
|
|
3744
|
+
text: serializeEnvelope(result, "diviops_fc_order_mark_paid"),
|
|
3745
|
+
},
|
|
3746
|
+
],
|
|
3747
|
+
};
|
|
3748
|
+
}, { target: "fluentcart", capabilityKey: "fluentcart_order_mark_paid" });
|
|
3749
|
+
// diviops_fc_license_list — POST /diviops/v1/pro/fluentcart/licenses
|
|
3750
|
+
registerProTool("diviops_fc_license_list", {
|
|
3751
|
+
description: "List FluentCart Pro licenses (Pro tier; V3.1; requires FluentCart Pro + Licensing module). Read-only. Filterable by product_id, variation_id, order_id, customer_id, status (active/inactive/disabled/expired/in_trial). License keys are NEVER returned in full — every row carries `redacted_key` only (first 4 + last 4 with ellipsis); use diviops_fc_license_get with explicit secret-handling opt-in if a full key is required for an authorized integration test. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }; the success payload is { licenses: LicenseSummary[], pagination: { page, per_page, total, total_pages }, filters: { ... } }. LicenseSummary includes id, status, product_id, variation_id, order_id, customer_id, subscription_id, limit (0 = unlimited per License::getActivationLimit), activation_count, expiration_date, created_at, updated_at, redacted_key. Error codes: invalid_input (HTTP 400) when status is out of range; fluentcart.module_inactive (HTTP 412); fluentcart.licensing_unavailable (HTTP 412) when FluentCart Pro's Licensing module is absent; fluentcart.query_failed (HTTP 500).",
|
|
3752
|
+
inputSchema: {
|
|
3753
|
+
page: z
|
|
3754
|
+
.number()
|
|
3755
|
+
.int()
|
|
3756
|
+
.positive()
|
|
3757
|
+
.optional()
|
|
3758
|
+
.default(1)
|
|
3759
|
+
.describe("Page number, 1-indexed. Default 1."),
|
|
3760
|
+
per_page: z
|
|
3761
|
+
.number()
|
|
3762
|
+
.int()
|
|
3763
|
+
.positive()
|
|
3764
|
+
.optional()
|
|
3765
|
+
.default(20)
|
|
3766
|
+
.describe("Page size. Default 20, clamped to a max of 100."),
|
|
3767
|
+
product_id: z
|
|
3768
|
+
.number()
|
|
3769
|
+
.int()
|
|
3770
|
+
.positive()
|
|
3771
|
+
.optional()
|
|
3772
|
+
.describe("Filter to licenses for this FluentCart product ID."),
|
|
3773
|
+
variation_id: z
|
|
3774
|
+
.number()
|
|
3775
|
+
.int()
|
|
3776
|
+
.positive()
|
|
3777
|
+
.optional()
|
|
3778
|
+
.describe("Filter to licenses for this FluentCart variation ID."),
|
|
3779
|
+
order_id: z
|
|
3780
|
+
.number()
|
|
3781
|
+
.int()
|
|
3782
|
+
.positive()
|
|
3783
|
+
.optional()
|
|
3784
|
+
.describe("Filter to licenses issued by this order ID."),
|
|
3785
|
+
customer_id: z
|
|
3786
|
+
.number()
|
|
3787
|
+
.int()
|
|
3788
|
+
.positive()
|
|
3789
|
+
.optional()
|
|
3790
|
+
.describe("Filter to licenses owned by this customer ID."),
|
|
3791
|
+
status: z
|
|
3792
|
+
.enum(["active", "inactive", "disabled", "expired", "in_trial"])
|
|
3793
|
+
.optional()
|
|
3794
|
+
.describe("License status (fct_licenses.status). 'active' is the healthy default."),
|
|
3795
|
+
},
|
|
3796
|
+
annotations: { idempotentHint: true },
|
|
3797
|
+
_meta: { idempotent: "true" },
|
|
3798
|
+
}, async ({ page, per_page, product_id, variation_id, order_id, customer_id, status, }) => {
|
|
3799
|
+
const body = {};
|
|
3800
|
+
if (page !== undefined)
|
|
3801
|
+
body.page = page;
|
|
3802
|
+
if (per_page !== undefined)
|
|
3803
|
+
body.per_page = per_page;
|
|
3804
|
+
if (product_id !== undefined)
|
|
3805
|
+
body.product_id = product_id;
|
|
3806
|
+
if (variation_id !== undefined)
|
|
3807
|
+
body.variation_id = variation_id;
|
|
3808
|
+
if (order_id !== undefined)
|
|
3809
|
+
body.order_id = order_id;
|
|
3810
|
+
if (customer_id !== undefined)
|
|
3811
|
+
body.customer_id = customer_id;
|
|
3812
|
+
if (status !== undefined)
|
|
3813
|
+
body.status = status;
|
|
3814
|
+
const result = await wp.requestEnveloped("/pro/fluentcart/licenses", {
|
|
3815
|
+
method: "POST",
|
|
3816
|
+
body,
|
|
3817
|
+
});
|
|
3818
|
+
return {
|
|
3819
|
+
content: [
|
|
3820
|
+
{
|
|
3821
|
+
type: "text",
|
|
3822
|
+
text: serializeEnvelope(result, "diviops_fc_license_list"),
|
|
3823
|
+
},
|
|
3824
|
+
],
|
|
3825
|
+
};
|
|
3826
|
+
}, { target: "fluentcart", capabilityKey: "fluentcart_license_list" });
|
|
3827
|
+
// diviops_fc_license_get — POST /diviops/v1/pro/fluentcart/licenses/{id}
|
|
3828
|
+
registerProTool("diviops_fc_license_get", {
|
|
3829
|
+
description: "Fetch a single FluentCart Pro license by ID (Pro tier; V3.1; requires FluentCart Pro + Licensing module). Read-only by default. The default response redacts the license key to `redacted_key` only (first 4 + last 4 with ellipsis). To surface the full key, pass BOTH `include_license_key: true` AND `confirm_secret_handling: true` — the response then carries `license.license_key` plus `_meta.contains_secret: true` naming the secret field. **Full license keys must never be pasted into PRs, issues, Slack, or any external surface.** Returns the standardized envelope { ok, data?, error: { code, message, hint? } }. Success payload: { license: { id, status, product_id, variation_id, order_id, customer_id, subscription_id, limit, activation_count, expiration_date, created_at, updated_at, redacted_key, license_key? } }. limit semantics: 0 = unlimited per License::getActivationLimit; positive integers are the actual activation cap. Error codes: invalid_input (HTTP 400) when id is non-positive or include_license_key was passed without confirm_secret_handling; not_found (HTTP 404); fluentcart.module_inactive (HTTP 412); fluentcart.licensing_unavailable (HTTP 412); fluentcart.query_failed (HTTP 500).",
|
|
3830
|
+
inputSchema: {
|
|
3831
|
+
id: z
|
|
3832
|
+
.number()
|
|
3833
|
+
.int()
|
|
3834
|
+
.positive()
|
|
3835
|
+
.describe("FluentCart license ID (fct_licenses.id)."),
|
|
3836
|
+
include_license_key: z
|
|
3837
|
+
.boolean()
|
|
3838
|
+
.optional()
|
|
3839
|
+
.describe("Opt-in: include the full unredacted license key in the response. Requires confirm_secret_handling: true. Default: redacted-only."),
|
|
3840
|
+
confirm_secret_handling: z
|
|
3841
|
+
.boolean()
|
|
3842
|
+
.optional()
|
|
3843
|
+
.describe("Required alongside include_license_key: true. Acknowledges that full license keys must not be pasted into reports, PRs, issues, or external chat surfaces."),
|
|
3844
|
+
},
|
|
3845
|
+
annotations: { idempotentHint: true },
|
|
3846
|
+
_meta: { idempotent: "true" },
|
|
3847
|
+
}, async ({ id, include_license_key, confirm_secret_handling, }) => {
|
|
3848
|
+
const body = {};
|
|
3849
|
+
if (include_license_key !== undefined)
|
|
3850
|
+
body.include_license_key = include_license_key;
|
|
3851
|
+
if (confirm_secret_handling !== undefined)
|
|
3852
|
+
body.confirm_secret_handling = confirm_secret_handling;
|
|
3853
|
+
const result = await wp.requestEnveloped(`/pro/fluentcart/licenses/${id}`, { method: "POST", body });
|
|
3854
|
+
return {
|
|
3855
|
+
content: [
|
|
3856
|
+
{
|
|
3857
|
+
type: "text",
|
|
3858
|
+
text: serializeEnvelope(result, "diviops_fc_license_get"),
|
|
3859
|
+
},
|
|
3860
|
+
],
|
|
3861
|
+
};
|
|
3862
|
+
}, { target: "fluentcart", capabilityKey: "fluentcart_license_get" });
|
|
3863
|
+
// diviops_fc_license_activations_list — POST /diviops/v1/pro/fluentcart/licenses/{id}/activations
|
|
3864
|
+
registerProTool("diviops_fc_license_activations_list", {
|
|
3865
|
+
description: "List a FluentCart license's activation rows (Pro tier; V3.1; requires FluentCart Pro + Licensing module). Read-only. Returns one row per `fct_license_activations` entry for the license, including the joined `fct_license_sites.site_url` (the NORMALIZED form — scheme + trailing slash + `www.` prefix stripped per LicenseHelper::sanitizeSiteUrl — not the raw URL the consumer submitted). Filterable by status (active/inactive/deactivated). License keys are NEVER returned by this endpoint. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }; success payload: { license_id, activations: Activation[], count, filters: { status } }. Activation row: id, license_id, site_id, site_url, status, is_local, product_id, variation_id, activation_method, last_update_date, last_update_version, created_at, updated_at. Error codes: invalid_input (HTTP 400); not_found (HTTP 404) when the license doesn't exist; fluentcart.module_inactive (HTTP 412); fluentcart.licensing_unavailable (HTTP 412); fluentcart.query_failed (HTTP 500). Useful for smoke verification (count + site_url presence) and for the activation-cap test described in the diviops-fluentcart skill.",
|
|
3866
|
+
inputSchema: {
|
|
3867
|
+
license_id: z
|
|
3868
|
+
.number()
|
|
3869
|
+
.int()
|
|
3870
|
+
.positive()
|
|
3871
|
+
.describe("FluentCart license ID whose activation rows to list (fct_licenses.id)."),
|
|
3872
|
+
status: z
|
|
3873
|
+
.enum(["active", "inactive", "deactivated"])
|
|
3874
|
+
.optional()
|
|
3875
|
+
.describe("Activation row status filter (fct_license_activations.status)."),
|
|
3876
|
+
},
|
|
3877
|
+
annotations: { idempotentHint: true },
|
|
3878
|
+
_meta: { idempotent: "true" },
|
|
3879
|
+
}, async ({ license_id, status, }) => {
|
|
3880
|
+
const body = {};
|
|
3881
|
+
if (status !== undefined)
|
|
3882
|
+
body.status = status;
|
|
3883
|
+
const result = await wp.requestEnveloped(`/pro/fluentcart/licenses/${license_id}/activations`, { method: "POST", body });
|
|
3884
|
+
return {
|
|
3885
|
+
content: [
|
|
3886
|
+
{
|
|
3887
|
+
type: "text",
|
|
3888
|
+
text: serializeEnvelope(result, "diviops_fc_license_activations_list"),
|
|
3889
|
+
},
|
|
3890
|
+
],
|
|
3891
|
+
};
|
|
3892
|
+
}, {
|
|
3893
|
+
target: "fluentcart",
|
|
3894
|
+
capabilityKey: "fluentcart_license_activations_list",
|
|
3895
|
+
});
|
|
3562
3896
|
}
|
|
3563
3897
|
// ── Start ────────────────────────────────────────────────────────────
|
|
3564
3898
|
async function main() {
|