@ar-agents/mercadopago 0.3.0 → 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.
- package/AGENTS.md +9 -0
- package/CHANGELOG.md +71 -0
- package/dist/index.cjs +689 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +279 -2
- package/dist/index.d.ts +279 -2
- package/dist/index.js +689 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -712,6 +712,188 @@ var MercadoPagoClient = class {
|
|
|
712
712
|
`/instore/orders/qr/seller/collectors/${encodeURIComponent(userId)}/pos/${encodeURIComponent(externalPosId)}/qrs`
|
|
713
713
|
);
|
|
714
714
|
}
|
|
715
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
716
|
+
// Subscription Plans (preapproval_plan — reusable plans, v0.4)
|
|
717
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
718
|
+
/**
|
|
719
|
+
* Create a reusable subscription plan. Customers later subscribe to it via
|
|
720
|
+
* `subscribeToPlan` (which creates a preapproval pointing at the plan).
|
|
721
|
+
*
|
|
722
|
+
* Use this when you have fixed tiers (Básico/Pro/Enterprise). For custom
|
|
723
|
+
* per-customer amounts, skip plans and use `createPreapproval` directly.
|
|
724
|
+
*/
|
|
725
|
+
async createSubscriptionPlan(params) {
|
|
726
|
+
const body = {
|
|
727
|
+
reason: params.reason,
|
|
728
|
+
back_url: params.backUrl,
|
|
729
|
+
auto_recurring: {
|
|
730
|
+
frequency: params.frequency,
|
|
731
|
+
frequency_type: params.frequencyType,
|
|
732
|
+
transaction_amount: params.amount,
|
|
733
|
+
currency_id: params.currency,
|
|
734
|
+
...params.freeTrialFrequency !== void 0 && params.freeTrialFrequencyType !== void 0 ? {
|
|
735
|
+
free_trial: {
|
|
736
|
+
frequency: params.freeTrialFrequency,
|
|
737
|
+
frequency_type: params.freeTrialFrequencyType
|
|
738
|
+
}
|
|
739
|
+
} : {}
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
if (params.externalReference) body.external_reference = params.externalReference;
|
|
743
|
+
return this.request("POST", "/preapproval_plan", body);
|
|
744
|
+
}
|
|
745
|
+
async getSubscriptionPlan(id) {
|
|
746
|
+
return this.request("GET", `/preapproval_plan/${id}`);
|
|
747
|
+
}
|
|
748
|
+
async listSubscriptionPlans(params = {}) {
|
|
749
|
+
const query = {
|
|
750
|
+
limit: params.limit ?? 30,
|
|
751
|
+
offset: params.offset ?? 0
|
|
752
|
+
};
|
|
753
|
+
if (params.status) query["status"] = params.status;
|
|
754
|
+
return this.request("GET", "/preapproval_plan/search", void 0, { query });
|
|
755
|
+
}
|
|
756
|
+
async updateSubscriptionPlan(id, patch) {
|
|
757
|
+
const body = {};
|
|
758
|
+
if (patch.reason !== void 0) body.reason = patch.reason;
|
|
759
|
+
if (patch.status !== void 0) body.status = patch.status;
|
|
760
|
+
if (patch.backUrl !== void 0) body.back_url = patch.backUrl;
|
|
761
|
+
if (patch.amount !== void 0) {
|
|
762
|
+
body.auto_recurring = { transaction_amount: patch.amount };
|
|
763
|
+
}
|
|
764
|
+
return this.request("PUT", `/preapproval_plan/${id}`, body);
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Subscribe a customer to an existing plan. Returns a Preapproval with
|
|
768
|
+
* `init_point` URL where the buyer completes the first payment.
|
|
769
|
+
*/
|
|
770
|
+
async subscribeToPlan(params) {
|
|
771
|
+
const body = {
|
|
772
|
+
preapproval_plan_id: params.planId,
|
|
773
|
+
payer_email: params.payerEmail
|
|
774
|
+
};
|
|
775
|
+
if (params.cardTokenId) body.card_token_id = params.cardTokenId;
|
|
776
|
+
if (params.externalReference) body.external_reference = params.externalReference;
|
|
777
|
+
return this.request("POST", "/preapproval", body, {
|
|
778
|
+
classifyContext: { payerEmail: params.payerEmail }
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* List the auto-charge attempts (authorized_payments) under a preapproval.
|
|
783
|
+
* Useful for "show me the cobros of the last 6 months for this client".
|
|
784
|
+
*/
|
|
785
|
+
async listSubscriptionPayments(preapprovalId, params = {}) {
|
|
786
|
+
const query = {
|
|
787
|
+
preapproval_id: preapprovalId,
|
|
788
|
+
limit: params.limit ?? 30,
|
|
789
|
+
offset: params.offset ?? 0
|
|
790
|
+
};
|
|
791
|
+
return this.request(
|
|
792
|
+
"GET",
|
|
793
|
+
`/authorized_payments/search`,
|
|
794
|
+
void 0,
|
|
795
|
+
{ query, classifyContext: { preapprovalId } }
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
799
|
+
// Stores + POS (for QR payments self-serve setup, v0.4)
|
|
800
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
801
|
+
/** Create a store for the seller. POSes (for QR) live under stores. */
|
|
802
|
+
async createStore(userId, params) {
|
|
803
|
+
const body = {
|
|
804
|
+
name: params.name,
|
|
805
|
+
external_id: params.externalId
|
|
806
|
+
};
|
|
807
|
+
if (params.location) {
|
|
808
|
+
body.location = {
|
|
809
|
+
...params.location.addressLine ? { address_line: params.location.addressLine } : {},
|
|
810
|
+
...params.location.cityName ? { city_name: params.location.cityName } : {},
|
|
811
|
+
...params.location.stateName ? { state_name: params.location.stateName } : {},
|
|
812
|
+
...params.location.countryId ? { country_id: params.location.countryId } : {},
|
|
813
|
+
...params.location.latitude !== void 0 ? { latitude: params.location.latitude } : {},
|
|
814
|
+
...params.location.longitude !== void 0 ? { longitude: params.location.longitude } : {}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
return this.request("POST", `/users/${encodeURIComponent(userId)}/stores`, body);
|
|
818
|
+
}
|
|
819
|
+
async listStores(userId, params = {}) {
|
|
820
|
+
const query = {
|
|
821
|
+
limit: params.limit ?? 50,
|
|
822
|
+
offset: params.offset ?? 0
|
|
823
|
+
};
|
|
824
|
+
return this.request("GET", `/users/${encodeURIComponent(userId)}/stores/search`, void 0, { query });
|
|
825
|
+
}
|
|
826
|
+
/** Create a POS under a store. The POS's `external_id` is what `createQrPayment` uses. */
|
|
827
|
+
async createPos(params) {
|
|
828
|
+
const body = {
|
|
829
|
+
name: params.name,
|
|
830
|
+
external_id: params.externalId,
|
|
831
|
+
store_id: params.storeId,
|
|
832
|
+
category: params.category ?? 621102
|
|
833
|
+
// "Other Food and Beverage Services" — generic default
|
|
834
|
+
};
|
|
835
|
+
if (params.fixedAmount !== void 0) body.fixed_amount = params.fixedAmount;
|
|
836
|
+
return this.request("POST", "/pos", body);
|
|
837
|
+
}
|
|
838
|
+
async listPos(params = {}) {
|
|
839
|
+
const query = {
|
|
840
|
+
limit: params.limit ?? 50,
|
|
841
|
+
offset: params.offset ?? 0
|
|
842
|
+
};
|
|
843
|
+
if (params.storeId !== void 0) query["store_id"] = String(params.storeId);
|
|
844
|
+
return this.request("GET", "/pos", void 0, { query });
|
|
845
|
+
}
|
|
846
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
847
|
+
// Disputes (read-only, v0.4)
|
|
848
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
849
|
+
async listPaymentDisputes(paymentId) {
|
|
850
|
+
return this.request("GET", `/v1/payments/${paymentId}/disputes`, void 0, {
|
|
851
|
+
classifyContext: { paymentId }
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
async getDispute(paymentId, disputeId) {
|
|
855
|
+
return this.request(
|
|
856
|
+
"GET",
|
|
857
|
+
`/v1/payments/${paymentId}/disputes/${disputeId}`,
|
|
858
|
+
void 0,
|
|
859
|
+
{ classifyContext: { paymentId } }
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
863
|
+
// Identification Types + Issuers (lookup helpers, v0.4)
|
|
864
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
865
|
+
/** List valid identification types for the seller's site. AR returns DNI/CI/LE/LC/Otro/Pasaporte/CUIT/CUIL. */
|
|
866
|
+
async listIdentificationTypes() {
|
|
867
|
+
return this.request("GET", "/v1/identification_types");
|
|
868
|
+
}
|
|
869
|
+
/** List card issuers for a payment method. Useful with `bin` for installments. */
|
|
870
|
+
async listIssuers(params) {
|
|
871
|
+
const query = {
|
|
872
|
+
payment_method_id: params.paymentMethodId
|
|
873
|
+
};
|
|
874
|
+
if (params.bin) query["bin"] = params.bin;
|
|
875
|
+
return this.request("GET", "/v1/payment_methods/card_issuers", void 0, { query });
|
|
876
|
+
}
|
|
877
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
878
|
+
// Webhooks management (v0.4)
|
|
879
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
880
|
+
/** List configured webhook subscriptions. */
|
|
881
|
+
async listWebhooks() {
|
|
882
|
+
return this.request("GET", "/v1/webhooks");
|
|
883
|
+
}
|
|
884
|
+
/** Create a webhook subscription for a topic. */
|
|
885
|
+
async createWebhook(params) {
|
|
886
|
+
return this.request("POST", "/v1/webhooks", {
|
|
887
|
+
url: params.url,
|
|
888
|
+
topic: params.topic
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
async updateWebhook(id, patch) {
|
|
892
|
+
return this.request("PUT", `/v1/webhooks/${id}`, patch);
|
|
893
|
+
}
|
|
894
|
+
async deleteWebhook(id) {
|
|
895
|
+
await this.request("DELETE", `/v1/webhooks/${id}`);
|
|
896
|
+
}
|
|
715
897
|
};
|
|
716
898
|
function deterministicIdempotencyKey(...parts) {
|
|
717
899
|
const payload = parts.filter((p) => p !== void 0 && p !== null).map(String).join("|");
|
|
@@ -749,8 +931,30 @@ var DEFAULT_DESCRIPTIONS = {
|
|
|
749
931
|
// ── Saved-card charging (v0.3) ───────────────────────────────────────────
|
|
750
932
|
charge_saved_card: "Charge a previously-saved card for a returning customer. Requires customer_id + card_id (from list_customer_cards) AND a fresh CVV the user provides this session. AR Mercado Pago does NOT support CVV-less charges via the public API \u2014 every charge needs CVV. Idempotent on (card_id, amount, external_reference): retries dedupe automatically. Returns the resulting Payment.",
|
|
751
933
|
// ── QR in-store (v0.3) ───────────────────────────────────────────────────
|
|
752
|
-
create_qr_payment: "Generate a dynamic in-store QR for a buyer to scan with any AR wallet (Modo, BNA+, Cuenta DNI, Naranja X, Mercado Pago, etc. \u2014 interop is mandated by Transferencias 3.0). Requires a pre-configured POS external_id (one
|
|
753
|
-
cancel_qr_payment: "Cancel a pending QR order on a POS. Necessary if the buyer never scans \u2014 otherwise the next create_qr_payment on the same POS returns 409."
|
|
934
|
+
create_qr_payment: "Generate a dynamic in-store QR for a buyer to scan with any AR wallet (Modo, BNA+, Cuenta DNI, Naranja X, Mercado Pago, etc. \u2014 interop is mandated by Transferencias 3.0). Requires a pre-configured POS external_id (use create_pos to set one up first if needed). Returns the qr_data string + a base64 PNG data URL ready to display. The QR expires in `expires_in_seconds` (default 600). MP fires `point_integration_wh` then `payment` webhooks when scanned.",
|
|
935
|
+
cancel_qr_payment: "Cancel a pending QR order on a POS. Necessary if the buyer never scans \u2014 otherwise the next create_qr_payment on the same POS returns 409.",
|
|
936
|
+
// ── Subscription Plans (v0.4) ────────────────────────────────────────────
|
|
937
|
+
create_subscription_plan: "Create a REUSABLE subscription plan (preapproval_plan). Different from create_subscription: a plan defines price + frequency once, then customers subscribe to it via subscribe_to_plan. Use plans for SaaS-style billing (B\xE1sico/Pro/Enterprise tiers). For per-customer custom amounts, use create_subscription directly.",
|
|
938
|
+
list_subscription_plans: "List all subscription plans defined for this MP account. Useful before create_subscription_plan to check if one already exists, or for surfacing options to a customer.",
|
|
939
|
+
update_subscription_plan: "Update a subscription plan's reason / amount / status / back_url. Existing customer subscriptions to the plan are NOT automatically updated \u2014 only NEW subscribers get the new pricing.",
|
|
940
|
+
subscribe_to_plan: "Subscribe a customer to an existing reusable plan. Returns a Preapproval with init_point URL where the customer completes first payment. Cleaner than create_subscription when you have fixed tiers.",
|
|
941
|
+
list_subscription_payments: "List the auto-charge attempts (authorized_payments) under a subscription. Useful for 'show me the cobros del \xFAltimo mes for this client' or to debug a failing recurring charge.",
|
|
942
|
+
// ── Stores + POS (v0.4) ──────────────────────────────────────────────────
|
|
943
|
+
create_store: "Create a store under the seller's MP account. Stores are the parent entity for POSes (which generate QR payments). Required ONE-TIME setup before create_pos. Pass a unique external_id and a display name.",
|
|
944
|
+
list_stores: "List all stores configured for this MP account. Use this to find an existing store_id before create_pos, or to surface store options to the agent.",
|
|
945
|
+
create_pos: "Create a POS (Point of Sale) under a store. The POS's external_id is what create_qr_payment uses. Each physical checkout / counter / agent typically has its own POS. Categories are MP-defined (default 621102 = Other Food and Beverage Services).",
|
|
946
|
+
list_pos: "List all POSes for the seller (or filtered by store_id). Use to find an existing POS before create_qr_payment, or to surface options.",
|
|
947
|
+
// ── Disputes (v0.4 — read-only) ──────────────────────────────────────────
|
|
948
|
+
list_payment_disputes: "List all disputes / chargebacks raised against a payment. Read-only \u2014 resolution is dashboard-only. Surface the dashboard URL `https://www.mercadopago.com.ar/disputes/{dispute_id}` to the user when they need to respond.",
|
|
949
|
+
get_dispute: "Get details of a specific dispute including reason, amount, resolution status. Read-only.",
|
|
950
|
+
// ── Lookup helpers (v0.4) ────────────────────────────────────────────────
|
|
951
|
+
list_identification_types: "List valid identification types for the seller's site. AR returns: DNI, CI, LE, LC, Otro, Pasaporte, CUIT, CUIL with their min/max length. Useful to validate an identification before passing to create_payment.",
|
|
952
|
+
list_issuers: "List card issuers (banks) that support a payment_method_id. Optionally filter by `bin` (first 6 digits of the card) for accurate issuer detection. Useful with calculate_installments \u2014 issuer-specific promos (e.g., Naranja Galicia 6 cuotas sin inter\xE9s) only appear when the issuer is identified.",
|
|
953
|
+
// ── Webhooks management (v0.4) ───────────────────────────────────────────
|
|
954
|
+
list_webhooks: "List all webhook subscriptions configured for this MP application. Use to see what topics + URLs are wired before adding new ones.",
|
|
955
|
+
create_webhook: "Subscribe a webhook URL to a MP topic (payment, subscription_authorized_payment, subscription_preapproval, merchant_order, point_integration_wh). MP will POST to this URL when events of that topic fire.",
|
|
956
|
+
update_webhook: "Update a webhook's URL or topic. Useful when you change deployment URLs without resubscribing from scratch.",
|
|
957
|
+
delete_webhook: "Delete a webhook subscription. MP stops POSTing to it immediately."
|
|
754
958
|
};
|
|
755
959
|
function mercadoPagoTools(client, options) {
|
|
756
960
|
const desc = (name) => options.descriptions?.[name] ?? DEFAULT_DESCRIPTIONS[name];
|
|
@@ -1360,6 +1564,390 @@ function mercadoPagoTools(client, options) {
|
|
|
1360
1564
|
await client.cancelQrPayment(String(me.id), external_pos_id);
|
|
1361
1565
|
return { external_pos_id, cancelled: true };
|
|
1362
1566
|
}
|
|
1567
|
+
}),
|
|
1568
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1569
|
+
// Subscription Plans (v0.4)
|
|
1570
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1571
|
+
create_subscription_plan: tool({
|
|
1572
|
+
description: desc("create_subscription_plan"),
|
|
1573
|
+
inputSchema: z.object({
|
|
1574
|
+
reason: z.string().min(3).max(120).describe("Plan name shown at checkout"),
|
|
1575
|
+
amount_ars: z.number().positive(),
|
|
1576
|
+
frequency_months: z.number().int().min(1).max(12),
|
|
1577
|
+
back_url: z.string().url().describe("HTTPS URL where MP redirects after first payment"),
|
|
1578
|
+
external_reference: z.string().optional(),
|
|
1579
|
+
free_trial_days: z.number().int().min(1).max(60).optional().describe("Free trial period in days before first charge")
|
|
1580
|
+
}),
|
|
1581
|
+
execute: async (input) => {
|
|
1582
|
+
const plan = await client.createSubscriptionPlan({
|
|
1583
|
+
reason: input.reason,
|
|
1584
|
+
amount: input.amount_ars,
|
|
1585
|
+
currency: "ARS",
|
|
1586
|
+
frequency: input.frequency_months,
|
|
1587
|
+
frequencyType: "months",
|
|
1588
|
+
backUrl: input.back_url,
|
|
1589
|
+
...input.external_reference !== void 0 ? { externalReference: input.external_reference } : {},
|
|
1590
|
+
...input.free_trial_days !== void 0 ? { freeTrialFrequency: input.free_trial_days, freeTrialFrequencyType: "days" } : {}
|
|
1591
|
+
});
|
|
1592
|
+
return {
|
|
1593
|
+
plan_id: plan.id,
|
|
1594
|
+
status: plan.status,
|
|
1595
|
+
reason: plan.reason,
|
|
1596
|
+
amount: plan.auto_recurring.transaction_amount,
|
|
1597
|
+
currency: plan.auto_recurring.currency_id,
|
|
1598
|
+
frequency: `${plan.auto_recurring.frequency} ${plan.auto_recurring.frequency_type}`,
|
|
1599
|
+
external_reference: plan.external_reference,
|
|
1600
|
+
next_step: "Use subscribe_to_plan to enroll customers in this plan, or share its ID for them to subscribe via your frontend."
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
}),
|
|
1604
|
+
list_subscription_plans: tool({
|
|
1605
|
+
description: desc("list_subscription_plans"),
|
|
1606
|
+
inputSchema: z.object({
|
|
1607
|
+
status: z.string().optional(),
|
|
1608
|
+
limit: z.number().int().min(1).max(100).optional()
|
|
1609
|
+
}),
|
|
1610
|
+
execute: async (input) => {
|
|
1611
|
+
const result = await client.listSubscriptionPlans({
|
|
1612
|
+
...input.status !== void 0 ? { status: input.status } : {},
|
|
1613
|
+
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
1614
|
+
});
|
|
1615
|
+
return {
|
|
1616
|
+
total: result.paging.total,
|
|
1617
|
+
plans: result.results.map((p) => ({
|
|
1618
|
+
plan_id: p.id,
|
|
1619
|
+
reason: p.reason,
|
|
1620
|
+
status: p.status,
|
|
1621
|
+
amount: p.auto_recurring.transaction_amount,
|
|
1622
|
+
currency: p.auto_recurring.currency_id,
|
|
1623
|
+
frequency: `${p.auto_recurring.frequency} ${p.auto_recurring.frequency_type}`
|
|
1624
|
+
}))
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
}),
|
|
1628
|
+
update_subscription_plan: tool({
|
|
1629
|
+
description: desc("update_subscription_plan"),
|
|
1630
|
+
inputSchema: z.object({
|
|
1631
|
+
plan_id: z.string(),
|
|
1632
|
+
reason: z.string().optional(),
|
|
1633
|
+
amount_ars: z.number().positive().optional(),
|
|
1634
|
+
status: z.enum(["active", "cancelled"]).optional(),
|
|
1635
|
+
back_url: z.string().url().optional()
|
|
1636
|
+
}),
|
|
1637
|
+
execute: async (input) => {
|
|
1638
|
+
const updated = await client.updateSubscriptionPlan(input.plan_id, {
|
|
1639
|
+
...input.reason !== void 0 ? { reason: input.reason } : {},
|
|
1640
|
+
...input.amount_ars !== void 0 ? { amount: input.amount_ars } : {},
|
|
1641
|
+
...input.status !== void 0 ? { status: input.status } : {},
|
|
1642
|
+
...input.back_url !== void 0 ? { backUrl: input.back_url } : {}
|
|
1643
|
+
});
|
|
1644
|
+
return {
|
|
1645
|
+
plan_id: updated.id,
|
|
1646
|
+
status: updated.status,
|
|
1647
|
+
reason: updated.reason,
|
|
1648
|
+
amount: updated.auto_recurring.transaction_amount,
|
|
1649
|
+
message: input.amount_ars !== void 0 ? "Updated. Existing subscribers keep their old amount; only NEW subscribers get the new pricing." : "Plan updated."
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
}),
|
|
1653
|
+
subscribe_to_plan: tool({
|
|
1654
|
+
description: desc("subscribe_to_plan"),
|
|
1655
|
+
inputSchema: z.object({
|
|
1656
|
+
plan_id: z.string(),
|
|
1657
|
+
customer_email: z.string().email(),
|
|
1658
|
+
external_reference: z.string().optional()
|
|
1659
|
+
}),
|
|
1660
|
+
execute: async (input) => {
|
|
1661
|
+
const sub = await client.subscribeToPlan({
|
|
1662
|
+
planId: input.plan_id,
|
|
1663
|
+
payerEmail: input.customer_email,
|
|
1664
|
+
...input.external_reference !== void 0 ? { externalReference: input.external_reference } : {}
|
|
1665
|
+
});
|
|
1666
|
+
return {
|
|
1667
|
+
subscription_id: sub.id,
|
|
1668
|
+
status: sub.status,
|
|
1669
|
+
payer_email: sub.payer_email,
|
|
1670
|
+
init_point_url: sub.init_point,
|
|
1671
|
+
next_step: "Send init_point_url to the customer for first payment with card+CVV."
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
}),
|
|
1675
|
+
list_subscription_payments: tool({
|
|
1676
|
+
description: desc("list_subscription_payments"),
|
|
1677
|
+
inputSchema: z.object({
|
|
1678
|
+
subscription_id: z.string(),
|
|
1679
|
+
limit: z.number().int().min(1).max(100).optional()
|
|
1680
|
+
}),
|
|
1681
|
+
execute: async (input) => {
|
|
1682
|
+
const result = await client.listSubscriptionPayments(input.subscription_id, {
|
|
1683
|
+
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
1684
|
+
});
|
|
1685
|
+
return {
|
|
1686
|
+
subscription_id: input.subscription_id,
|
|
1687
|
+
total: result.paging.total,
|
|
1688
|
+
payments: result.results.map((p) => ({
|
|
1689
|
+
authorized_payment_id: p.id,
|
|
1690
|
+
payment_id: p.payment_id ?? null,
|
|
1691
|
+
status: p.status,
|
|
1692
|
+
amount: p.transaction_amount ?? null,
|
|
1693
|
+
currency: p.currency_id ?? null,
|
|
1694
|
+
debit_date: p.debit_date ?? null,
|
|
1695
|
+
next_retry_date: p.next_retry_date ?? null,
|
|
1696
|
+
retry_attempt: p.retry_attempt ?? 0,
|
|
1697
|
+
reason: p.reason ?? null
|
|
1698
|
+
}))
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
}),
|
|
1702
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1703
|
+
// Stores + POS (v0.4)
|
|
1704
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1705
|
+
create_store: tool({
|
|
1706
|
+
description: desc("create_store"),
|
|
1707
|
+
inputSchema: z.object({
|
|
1708
|
+
name: z.string().min(1).max(80),
|
|
1709
|
+
external_id: z.string().min(1).max(64).describe("Unique within the seller's stores"),
|
|
1710
|
+
address_line: z.string().optional(),
|
|
1711
|
+
city_name: z.string().optional(),
|
|
1712
|
+
state_name: z.string().optional()
|
|
1713
|
+
}),
|
|
1714
|
+
execute: async (input) => {
|
|
1715
|
+
const me = await client.getMe();
|
|
1716
|
+
const store = await client.createStore(String(me.id), {
|
|
1717
|
+
name: input.name,
|
|
1718
|
+
externalId: input.external_id,
|
|
1719
|
+
...input.address_line || input.city_name || input.state_name ? {
|
|
1720
|
+
location: {
|
|
1721
|
+
...input.address_line ? { addressLine: input.address_line } : {},
|
|
1722
|
+
...input.city_name ? { cityName: input.city_name } : {},
|
|
1723
|
+
...input.state_name ? { stateName: input.state_name } : {},
|
|
1724
|
+
countryId: "AR"
|
|
1725
|
+
}
|
|
1726
|
+
} : {}
|
|
1727
|
+
});
|
|
1728
|
+
return {
|
|
1729
|
+
store_id: store.id,
|
|
1730
|
+
name: store.name,
|
|
1731
|
+
external_id: store.external_id,
|
|
1732
|
+
next_step: "Use create_pos with this store_id to add a Point of Sale where create_qr_payment can issue QRs."
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
}),
|
|
1736
|
+
list_stores: tool({
|
|
1737
|
+
description: desc("list_stores"),
|
|
1738
|
+
inputSchema: z.object({
|
|
1739
|
+
limit: z.number().int().min(1).max(100).optional()
|
|
1740
|
+
}),
|
|
1741
|
+
execute: async (input) => {
|
|
1742
|
+
const me = await client.getMe();
|
|
1743
|
+
const result = await client.listStores(String(me.id), {
|
|
1744
|
+
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
1745
|
+
});
|
|
1746
|
+
return {
|
|
1747
|
+
total: result.paging.total,
|
|
1748
|
+
stores: result.results.map((s) => ({
|
|
1749
|
+
store_id: s.id,
|
|
1750
|
+
name: s.name ?? null,
|
|
1751
|
+
external_id: s.external_id ?? null
|
|
1752
|
+
}))
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
}),
|
|
1756
|
+
create_pos: tool({
|
|
1757
|
+
description: desc("create_pos"),
|
|
1758
|
+
inputSchema: z.object({
|
|
1759
|
+
name: z.string().min(1).max(80),
|
|
1760
|
+
external_id: z.string().min(1).max(64).describe("Unique within the store. This is what create_qr_payment uses."),
|
|
1761
|
+
store_id: z.string().describe("From create_store / list_stores"),
|
|
1762
|
+
category: z.number().int().optional().describe("MP category code, default 621102 (other food/beverage)"),
|
|
1763
|
+
fixed_amount: z.boolean().optional().describe("True for static QR with fixed amount; false (default) for dynamic per-order QR")
|
|
1764
|
+
}),
|
|
1765
|
+
execute: async (input) => {
|
|
1766
|
+
const pos = await client.createPos({
|
|
1767
|
+
name: input.name,
|
|
1768
|
+
externalId: input.external_id,
|
|
1769
|
+
storeId: input.store_id,
|
|
1770
|
+
...input.category !== void 0 ? { category: input.category } : {},
|
|
1771
|
+
...input.fixed_amount !== void 0 ? { fixedAmount: input.fixed_amount } : {}
|
|
1772
|
+
});
|
|
1773
|
+
return {
|
|
1774
|
+
pos_id: pos.id,
|
|
1775
|
+
external_id: pos.external_id,
|
|
1776
|
+
store_id: pos.store_id,
|
|
1777
|
+
name: pos.name,
|
|
1778
|
+
next_step: "Use create_qr_payment with this external_id to start issuing dynamic QRs from this POS."
|
|
1779
|
+
};
|
|
1780
|
+
}
|
|
1781
|
+
}),
|
|
1782
|
+
list_pos: tool({
|
|
1783
|
+
description: desc("list_pos"),
|
|
1784
|
+
inputSchema: z.object({
|
|
1785
|
+
store_id: z.string().optional(),
|
|
1786
|
+
limit: z.number().int().min(1).max(100).optional()
|
|
1787
|
+
}),
|
|
1788
|
+
execute: async (input) => {
|
|
1789
|
+
const result = await client.listPos({
|
|
1790
|
+
...input.store_id !== void 0 ? { storeId: input.store_id } : {},
|
|
1791
|
+
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
1792
|
+
});
|
|
1793
|
+
return {
|
|
1794
|
+
total: result.paging.total,
|
|
1795
|
+
pos: result.results.map((p) => ({
|
|
1796
|
+
pos_id: p.id,
|
|
1797
|
+
external_id: p.external_id ?? null,
|
|
1798
|
+
store_id: p.store_id ?? null,
|
|
1799
|
+
name: p.name ?? null
|
|
1800
|
+
}))
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
}),
|
|
1804
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1805
|
+
// Disputes (v0.4 — read-only)
|
|
1806
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1807
|
+
list_payment_disputes: tool({
|
|
1808
|
+
description: desc("list_payment_disputes"),
|
|
1809
|
+
inputSchema: z.object({ payment_id: z.string() }),
|
|
1810
|
+
execute: async ({ payment_id }) => {
|
|
1811
|
+
const disputes = await client.listPaymentDisputes(payment_id);
|
|
1812
|
+
return {
|
|
1813
|
+
payment_id,
|
|
1814
|
+
count: disputes.length,
|
|
1815
|
+
disputes: disputes.map((d) => ({
|
|
1816
|
+
dispute_id: d.id,
|
|
1817
|
+
status: d.status,
|
|
1818
|
+
amount: d.amount ?? null,
|
|
1819
|
+
reason: d.reason ?? null,
|
|
1820
|
+
date_created: d.date_created ?? null,
|
|
1821
|
+
dashboard_url: `https://www.mercadopago.com.ar/disputes/${d.id}`
|
|
1822
|
+
}))
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
}),
|
|
1826
|
+
get_dispute: tool({
|
|
1827
|
+
description: desc("get_dispute"),
|
|
1828
|
+
inputSchema: z.object({
|
|
1829
|
+
payment_id: z.string(),
|
|
1830
|
+
dispute_id: z.string()
|
|
1831
|
+
}),
|
|
1832
|
+
execute: async ({ payment_id, dispute_id }) => {
|
|
1833
|
+
const d = await client.getDispute(payment_id, dispute_id);
|
|
1834
|
+
return {
|
|
1835
|
+
dispute_id: d.id,
|
|
1836
|
+
status: d.status,
|
|
1837
|
+
amount: d.amount ?? null,
|
|
1838
|
+
reason: d.reason ?? null,
|
|
1839
|
+
reason_description: d.reason_description ?? null,
|
|
1840
|
+
resolution: d.resolution ?? null,
|
|
1841
|
+
date_created: d.date_created ?? null,
|
|
1842
|
+
dashboard_url: `https://www.mercadopago.com.ar/disputes/${d.id}`
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
}),
|
|
1846
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1847
|
+
// Lookup helpers (v0.4)
|
|
1848
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1849
|
+
list_identification_types: tool({
|
|
1850
|
+
description: desc("list_identification_types"),
|
|
1851
|
+
inputSchema: z.object({}),
|
|
1852
|
+
execute: async () => {
|
|
1853
|
+
const types = await client.listIdentificationTypes();
|
|
1854
|
+
return {
|
|
1855
|
+
count: types.length,
|
|
1856
|
+
types: types.map((t) => ({
|
|
1857
|
+
id: t.id,
|
|
1858
|
+
name: t.name,
|
|
1859
|
+
type: t.type,
|
|
1860
|
+
min_length: t.min_length ?? null,
|
|
1861
|
+
max_length: t.max_length ?? null
|
|
1862
|
+
}))
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
}),
|
|
1866
|
+
list_issuers: tool({
|
|
1867
|
+
description: desc("list_issuers"),
|
|
1868
|
+
inputSchema: z.object({
|
|
1869
|
+
payment_method_id: z.string().describe("E.g. 'visa', 'master', 'naranja'"),
|
|
1870
|
+
bin: z.string().min(6).max(8).optional().describe("First 6-8 digits of card for precise issuer detection")
|
|
1871
|
+
}),
|
|
1872
|
+
execute: async (input) => {
|
|
1873
|
+
const issuers = await client.listIssuers({
|
|
1874
|
+
paymentMethodId: input.payment_method_id,
|
|
1875
|
+
...input.bin !== void 0 ? { bin: input.bin } : {}
|
|
1876
|
+
});
|
|
1877
|
+
return {
|
|
1878
|
+
payment_method_id: input.payment_method_id,
|
|
1879
|
+
count: issuers.length,
|
|
1880
|
+
issuers: issuers.map((i) => ({
|
|
1881
|
+
issuer_id: i.id,
|
|
1882
|
+
name: i.name,
|
|
1883
|
+
status: i.status ?? null
|
|
1884
|
+
}))
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
}),
|
|
1888
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1889
|
+
// Webhooks management (v0.4)
|
|
1890
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1891
|
+
list_webhooks: tool({
|
|
1892
|
+
description: desc("list_webhooks"),
|
|
1893
|
+
inputSchema: z.object({}),
|
|
1894
|
+
execute: async () => {
|
|
1895
|
+
const hooks = await client.listWebhooks();
|
|
1896
|
+
return {
|
|
1897
|
+
count: hooks.length,
|
|
1898
|
+
webhooks: hooks.map((h) => ({
|
|
1899
|
+
webhook_id: h.id,
|
|
1900
|
+
url: h.url ?? null,
|
|
1901
|
+
topic: h.topic ?? null,
|
|
1902
|
+
status: h.status ?? null,
|
|
1903
|
+
date_created: h.date_created ?? null
|
|
1904
|
+
}))
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1907
|
+
}),
|
|
1908
|
+
create_webhook: tool({
|
|
1909
|
+
description: desc("create_webhook"),
|
|
1910
|
+
inputSchema: z.object({
|
|
1911
|
+
url: z.string().url(),
|
|
1912
|
+
topic: z.string().describe("E.g. 'payment', 'subscription_authorized_payment', 'subscription_preapproval', 'merchant_order', 'point_integration_wh'")
|
|
1913
|
+
}),
|
|
1914
|
+
execute: async ({ url, topic }) => {
|
|
1915
|
+
const hook = await client.createWebhook({ url, topic });
|
|
1916
|
+
return {
|
|
1917
|
+
webhook_id: hook.id,
|
|
1918
|
+
url: hook.url ?? url,
|
|
1919
|
+
topic: hook.topic ?? topic,
|
|
1920
|
+
status: hook.status ?? null
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
}),
|
|
1924
|
+
update_webhook: tool({
|
|
1925
|
+
description: desc("update_webhook"),
|
|
1926
|
+
inputSchema: z.object({
|
|
1927
|
+
webhook_id: z.string(),
|
|
1928
|
+
url: z.string().url().optional(),
|
|
1929
|
+
topic: z.string().optional()
|
|
1930
|
+
}),
|
|
1931
|
+
execute: async (input) => {
|
|
1932
|
+
const hook = await client.updateWebhook(input.webhook_id, {
|
|
1933
|
+
...input.url !== void 0 ? { url: input.url } : {},
|
|
1934
|
+
...input.topic !== void 0 ? { topic: input.topic } : {}
|
|
1935
|
+
});
|
|
1936
|
+
return {
|
|
1937
|
+
webhook_id: hook.id,
|
|
1938
|
+
url: hook.url ?? null,
|
|
1939
|
+
topic: hook.topic ?? null,
|
|
1940
|
+
status: hook.status ?? null
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
}),
|
|
1944
|
+
delete_webhook: tool({
|
|
1945
|
+
description: desc("delete_webhook"),
|
|
1946
|
+
inputSchema: z.object({ webhook_id: z.string() }),
|
|
1947
|
+
execute: async ({ webhook_id }) => {
|
|
1948
|
+
await client.deleteWebhook(webhook_id);
|
|
1949
|
+
return { webhook_id, deleted: true };
|
|
1950
|
+
}
|
|
1363
1951
|
})
|
|
1364
1952
|
};
|
|
1365
1953
|
}
|
|
@@ -1580,6 +2168,105 @@ z.object({
|
|
|
1580
2168
|
user_type: z.string().nullable().optional(),
|
|
1581
2169
|
status: z.object({ user_type: z.string().nullable().optional() }).passthrough().nullable().optional()
|
|
1582
2170
|
}).passthrough();
|
|
2171
|
+
z.object({
|
|
2172
|
+
id: z.string(),
|
|
2173
|
+
status: z.string(),
|
|
2174
|
+
reason: z.string(),
|
|
2175
|
+
back_url: z.string().url().optional(),
|
|
2176
|
+
external_reference: z.string().nullable().optional(),
|
|
2177
|
+
date_created: z.string(),
|
|
2178
|
+
last_modified: z.string(),
|
|
2179
|
+
auto_recurring: AutoRecurringSchema
|
|
2180
|
+
}).passthrough();
|
|
2181
|
+
z.object({
|
|
2182
|
+
id: z.union([z.string(), z.number()]).transform(String),
|
|
2183
|
+
name: z.string().optional(),
|
|
2184
|
+
external_id: z.string().optional(),
|
|
2185
|
+
date_creation: z.string().optional(),
|
|
2186
|
+
location: z.object({
|
|
2187
|
+
address_line: z.string().optional(),
|
|
2188
|
+
city_name: z.string().optional(),
|
|
2189
|
+
state_name: z.string().optional(),
|
|
2190
|
+
country_id: z.string().optional(),
|
|
2191
|
+
latitude: z.number().optional(),
|
|
2192
|
+
longitude: z.number().optional()
|
|
2193
|
+
}).passthrough().optional()
|
|
2194
|
+
}).passthrough();
|
|
2195
|
+
z.object({
|
|
2196
|
+
id: z.union([z.string(), z.number()]).transform(String),
|
|
2197
|
+
name: z.string().optional(),
|
|
2198
|
+
external_id: z.string().optional(),
|
|
2199
|
+
store_id: z.union([z.string(), z.number()]).optional(),
|
|
2200
|
+
category: z.number().int().optional(),
|
|
2201
|
+
fixed_amount: z.boolean().optional(),
|
|
2202
|
+
qr: z.object({
|
|
2203
|
+
template_image: z.string().optional(),
|
|
2204
|
+
image: z.string().optional()
|
|
2205
|
+
}).passthrough().optional(),
|
|
2206
|
+
date_creation: z.string().optional()
|
|
2207
|
+
}).passthrough();
|
|
2208
|
+
z.object({
|
|
2209
|
+
id: z.union([z.string(), z.number()]).transform(String),
|
|
2210
|
+
status: z.string(),
|
|
2211
|
+
resource: z.string().optional(),
|
|
2212
|
+
resource_id: z.union([z.string(), z.number()]).optional(),
|
|
2213
|
+
amount: z.number().optional(),
|
|
2214
|
+
date_created: z.string().optional(),
|
|
2215
|
+
reason: z.string().optional(),
|
|
2216
|
+
resolution: z.object({
|
|
2217
|
+
reason: z.string().optional(),
|
|
2218
|
+
result: z.string().optional(),
|
|
2219
|
+
date: z.string().optional()
|
|
2220
|
+
}).passthrough().optional(),
|
|
2221
|
+
/** Documents the buyer / seller submitted as evidence. */
|
|
2222
|
+
documents: z.array(z.unknown()).optional(),
|
|
2223
|
+
/** Buyer's stated complaint. */
|
|
2224
|
+
reason_description: z.string().optional()
|
|
2225
|
+
}).passthrough();
|
|
2226
|
+
z.object({
|
|
2227
|
+
id: z.union([z.string(), z.number()]).transform(String),
|
|
2228
|
+
preapproval_id: z.string().optional(),
|
|
2229
|
+
status: z.string(),
|
|
2230
|
+
payment_id: z.union([z.string(), z.number()]).nullable().optional(),
|
|
2231
|
+
transaction_amount: z.number().optional(),
|
|
2232
|
+
currency_id: z.string().optional(),
|
|
2233
|
+
date_created: z.string().optional(),
|
|
2234
|
+
debit_date: z.string().optional(),
|
|
2235
|
+
next_retry_date: z.string().nullable().optional(),
|
|
2236
|
+
retry_attempt: z.number().optional(),
|
|
2237
|
+
reason: z.string().optional()
|
|
2238
|
+
}).passthrough();
|
|
2239
|
+
z.object({
|
|
2240
|
+
id: z.string(),
|
|
2241
|
+
name: z.string(),
|
|
2242
|
+
type: z.string(),
|
|
2243
|
+
min_length: z.number().optional(),
|
|
2244
|
+
max_length: z.number().optional()
|
|
2245
|
+
}).passthrough();
|
|
2246
|
+
z.object({
|
|
2247
|
+
id: z.union([z.string(), z.number()]).transform(String),
|
|
2248
|
+
name: z.string(),
|
|
2249
|
+
secure_thumbnail: z.string().nullable().optional(),
|
|
2250
|
+
thumbnail: z.string().nullable().optional(),
|
|
2251
|
+
processing_mode: z.string().optional(),
|
|
2252
|
+
status: z.string().optional()
|
|
2253
|
+
}).passthrough();
|
|
2254
|
+
z.enum([
|
|
2255
|
+
"payment",
|
|
2256
|
+
"subscription_authorized_payment",
|
|
2257
|
+
"subscription_preapproval",
|
|
2258
|
+
"merchant_order",
|
|
2259
|
+
"point_integration_wh",
|
|
2260
|
+
"stop_delivery_op_wh"
|
|
2261
|
+
]);
|
|
2262
|
+
z.object({
|
|
2263
|
+
id: z.union([z.string(), z.number()]).transform(String),
|
|
2264
|
+
url: z.string().url().optional(),
|
|
2265
|
+
status: z.string().optional(),
|
|
2266
|
+
topic: z.string().optional(),
|
|
2267
|
+
date_created: z.string().optional(),
|
|
2268
|
+
date_modified: z.string().optional()
|
|
2269
|
+
}).passthrough();
|
|
1583
2270
|
|
|
1584
2271
|
// src/webhook.ts
|
|
1585
2272
|
function parseWebhookEvent(body, searchParams) {
|