@ar-agents/mercadopago 0.6.0 → 0.7.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/dist/index.js CHANGED
@@ -1023,6 +1023,215 @@ var MercadoPagoClient = class {
1023
1023
  async getSettlement(id) {
1024
1024
  return this.request("GET", `/v1/account/release_money/${id}`);
1025
1025
  }
1026
+ // ──────────────────────────────────────────────────────────────────────────
1027
+ // v0.7 — Customer + Card extensions (close gaps)
1028
+ // ──────────────────────────────────────────────────────────────────────────
1029
+ /**
1030
+ * Update a customer's profile (name, last name, address, etc.). MP merges
1031
+ * the patch — fields you don't send remain unchanged.
1032
+ */
1033
+ async updateCustomer(id, patch) {
1034
+ return this.request("PUT", `/v1/customers/${id}`, patch);
1035
+ }
1036
+ /**
1037
+ * Add a saved card to a customer using a card token (one-time, get from
1038
+ * MP's frontend Cardform). The card is then chargeable with charge_saved_card.
1039
+ */
1040
+ async createCustomerCard(customerId, cardToken) {
1041
+ return this.request(
1042
+ "POST",
1043
+ `/v1/customers/${customerId}/cards`,
1044
+ { token: cardToken }
1045
+ );
1046
+ }
1047
+ // ──────────────────────────────────────────────────────────────────────────
1048
+ // v0.7 — Subscription extensions
1049
+ // ──────────────────────────────────────────────────────────────────────────
1050
+ /**
1051
+ * Update an existing subscription. Common patches:
1052
+ * - `transaction_amount` to change the recurring amount
1053
+ * - `card_token_id` to switch payment method (e.g., expired card)
1054
+ * - `status: "cancelled" | "paused"` (alternative to dedicated cancel/pause endpoints)
1055
+ * - `reason` to update the description shown to the buyer
1056
+ */
1057
+ async updatePreapproval(id, patch) {
1058
+ return this.request("PUT", `/preapproval/${id}`, patch);
1059
+ }
1060
+ /**
1061
+ * Search subscriptions across the seller's account. Common filters:
1062
+ * `status` (pending/authorized/paused/cancelled), `payer_email`,
1063
+ * `external_reference`. Paginated.
1064
+ */
1065
+ async searchPreapprovals(params = {}) {
1066
+ const query = {};
1067
+ if (params.status) query.status = params.status;
1068
+ if (params.payerEmail) query.payer_email = params.payerEmail;
1069
+ if (params.externalReference) query.external_reference = params.externalReference;
1070
+ if (params.preapproval_plan_id) query.preapproval_plan_id = params.preapproval_plan_id;
1071
+ if (params.limit !== void 0) query.limit = params.limit;
1072
+ if (params.offset !== void 0) query.offset = params.offset;
1073
+ const result = await this.request("GET", "/preapproval/search", void 0, { query });
1074
+ return {
1075
+ results: result.results ?? [],
1076
+ paging: result.paging ?? { limit: params.limit ?? 25, offset: params.offset ?? 0, total: 0 }
1077
+ };
1078
+ }
1079
+ // ──────────────────────────────────────────────────────────────────────────
1080
+ // v0.7 — Merchant Orders (parent of Payments grouped under a Preference)
1081
+ // ──────────────────────────────────────────────────────────────────────────
1082
+ /**
1083
+ * Get a merchant_order with all its associated payments + shipments.
1084
+ * Useful for reconciling "which payments belong to which preference"
1085
+ * — typical webhook handler use case.
1086
+ */
1087
+ async getMerchantOrder(id) {
1088
+ return this.request("GET", `/merchant_orders/${id}`);
1089
+ }
1090
+ /**
1091
+ * Search merchant_orders by external_reference, preference_id, or status.
1092
+ */
1093
+ async searchMerchantOrders(params = {}) {
1094
+ const query = {};
1095
+ if (params.preferenceId) query.preference_id = params.preferenceId;
1096
+ if (params.externalReference) query.external_reference = params.externalReference;
1097
+ if (params.status) query.status = params.status;
1098
+ if (params.limit !== void 0) query.limit = params.limit;
1099
+ if (params.offset !== void 0) query.offset = params.offset;
1100
+ const result = await this.request("GET", "/merchant_orders/search", void 0, { query });
1101
+ return {
1102
+ elements: result.elements ?? [],
1103
+ paging: result.paging ?? { limit: params.limit ?? 25, offset: params.offset ?? 0, total: 0 }
1104
+ };
1105
+ }
1106
+ /**
1107
+ * Update a merchant_order — typically to add items or update shipping.
1108
+ */
1109
+ async updateMerchantOrder(id, patch) {
1110
+ return this.request("PUT", `/merchant_orders/${id}`, patch);
1111
+ }
1112
+ // ──────────────────────────────────────────────────────────────────────────
1113
+ // v0.7 — Stores + POS CRUD completion
1114
+ // ──────────────────────────────────────────────────────────────────────────
1115
+ async getStore(userId, storeId) {
1116
+ return this.request("GET", `/users/${userId}/stores/${storeId}`);
1117
+ }
1118
+ async updateStore(userId, storeId, patch) {
1119
+ return this.request("PUT", `/users/${userId}/stores/${storeId}`, patch);
1120
+ }
1121
+ async deleteStore(userId, storeId) {
1122
+ await this.request("DELETE", `/users/${userId}/stores/${storeId}`);
1123
+ }
1124
+ async getPos(posId) {
1125
+ return this.request("GET", `/pos/${posId}`);
1126
+ }
1127
+ async updatePos(posId, patch) {
1128
+ return this.request("PUT", `/pos/${posId}`, patch);
1129
+ }
1130
+ async deletePos(posId) {
1131
+ await this.request("DELETE", `/pos/${posId}`);
1132
+ }
1133
+ // ──────────────────────────────────────────────────────────────────────────
1134
+ // v0.7 — Bank Accounts (the CBUs the seller has registered for payouts)
1135
+ // ──────────────────────────────────────────────────────────────────────────
1136
+ /**
1137
+ * List bank accounts registered by the seller. The default is the one
1138
+ * that receives `release_money` settlements.
1139
+ */
1140
+ async listBankAccounts() {
1141
+ const result = await this.request(
1142
+ "GET",
1143
+ "/users/me/bank_accounts"
1144
+ );
1145
+ if (Array.isArray(result)) return result;
1146
+ return result.results ?? [];
1147
+ }
1148
+ /**
1149
+ * Register a new bank account (CBU) for the seller. Note: MP usually
1150
+ * requires this through the dashboard for compliance — this endpoint may
1151
+ * not work for all sellers.
1152
+ */
1153
+ async registerBankAccount(params) {
1154
+ return this.request("POST", "/users/me/bank_accounts", params);
1155
+ }
1156
+ // ──────────────────────────────────────────────────────────────────────────
1157
+ // v0.7 — Point Devices (physical terminal hardware: Smart, Tap to Pay)
1158
+ //
1159
+ // Distinct from the logical `Pos` entity. PointDevices are the actual
1160
+ // physical terminals you have at brick-and-mortar shops.
1161
+ // ──────────────────────────────────────────────────────────────────────────
1162
+ /**
1163
+ * List the Point devices linked to the seller's MP account. Each device
1164
+ * has an id (the device serial), an operating_mode (PDV vs STANDALONE),
1165
+ * and an optional pos_id (when bound to a logical POS).
1166
+ */
1167
+ async listPointDevices(params = {}) {
1168
+ const query = {};
1169
+ if (params.posId !== void 0) query["pos.id"] = params.posId;
1170
+ if (params.limit !== void 0) query.limit = params.limit;
1171
+ if (params.offset !== void 0) query.offset = params.offset;
1172
+ const result = await this.request("GET", "/point/integration-api/devices", void 0, { query });
1173
+ return {
1174
+ devices: result.devices ?? [],
1175
+ paging: result.paging ?? { total: 0, limit: params.limit ?? 50, offset: params.offset ?? 0 }
1176
+ };
1177
+ }
1178
+ /**
1179
+ * Switch a Point device's operating mode:
1180
+ * - "PDV": device is bound to a logical Pos and only takes payments
1181
+ * triggered through that Pos (typical for cash-register integrations).
1182
+ * - "STANDALONE": device works independently, accepts any payment.
1183
+ */
1184
+ async updatePointDeviceOperatingMode(deviceId, operatingMode) {
1185
+ return this.request(
1186
+ "PATCH",
1187
+ `/point/integration-api/devices/${encodeURIComponent(deviceId)}`,
1188
+ { operating_mode: operatingMode }
1189
+ );
1190
+ }
1191
+ /**
1192
+ * Create a payment intent on a Point device — the device prompts the buyer
1193
+ * to tap/insert/swipe. Returns immediately with intent id; query state via
1194
+ * `getPointPaymentIntent()` or wait for `point_integration_wh` webhook.
1195
+ *
1196
+ * NOTE: amount is in CENTAVOS (Point API differs from Payments API which
1197
+ * uses pesos). 100 = $1 ARS, 1000 = $10, 10000 = $100, etc.
1198
+ */
1199
+ async createPointPaymentIntent(deviceId, params) {
1200
+ const body = {
1201
+ amount: params.amount,
1202
+ ...params.description ? { description: params.description } : {},
1203
+ ...params.externalReference ? { additional_info: { external_reference: params.externalReference } } : {},
1204
+ payment: {
1205
+ installments: params.installments ?? 1,
1206
+ ...params.installmentsCost ? { installments_cost: params.installmentsCost } : {},
1207
+ ...params.printOnTerminal !== void 0 ? { print_on_terminal: params.printOnTerminal } : {},
1208
+ ...params.ticketNumber ? { ticket_number: params.ticketNumber } : {}
1209
+ }
1210
+ };
1211
+ return this.request(
1212
+ "POST",
1213
+ `/point/integration-api/devices/${encodeURIComponent(deviceId)}/payment-intents`,
1214
+ body
1215
+ );
1216
+ }
1217
+ /** Get the current state of a Point payment intent. */
1218
+ async getPointPaymentIntent(intentId) {
1219
+ return this.request(
1220
+ "GET",
1221
+ `/point/integration-api/payment-intents/${encodeURIComponent(intentId)}`
1222
+ );
1223
+ }
1224
+ /**
1225
+ * Cancel an OPEN payment intent before the buyer interacts with the device.
1226
+ * Only works while state is "OPEN" — once the buyer taps, you can't cancel.
1227
+ */
1228
+ async cancelPointPaymentIntent(deviceId, intentId) {
1229
+ await this.request(
1230
+ "DELETE",
1231
+ `/point/integration-api/devices/${encodeURIComponent(deviceId)}/payment-intents/${encodeURIComponent(intentId)}`
1232
+ );
1233
+ return { id: intentId, canceled: true };
1234
+ }
1026
1235
  };
1027
1236
  z.enum(["MLA", "MLB", "MLM", "MCO", "MLC", "MLU"]);
1028
1237
  var CurrencyIdSchema = z.enum(["ARS", "USD", "BRL", "MXN"]);
@@ -1403,6 +1612,63 @@ z.object({
1403
1612
  bank_name: z.string().optional()
1404
1613
  }).passthrough().optional()
1405
1614
  }).passthrough();
1615
+ z.object({
1616
+ id: z.union([z.string(), z.number()]).transform(String),
1617
+ status: z.string().optional(),
1618
+ external_reference: z.string().nullable().optional(),
1619
+ preference_id: z.union([z.string(), z.number()]).optional(),
1620
+ payments: z.array(z.unknown()).optional(),
1621
+ shipments: z.array(z.unknown()).optional(),
1622
+ payer: z.unknown().optional(),
1623
+ collector: z.unknown().optional(),
1624
+ marketplace: z.string().optional(),
1625
+ total_amount: z.number().optional(),
1626
+ paid_amount: z.number().optional(),
1627
+ refunded_amount: z.number().optional(),
1628
+ shipping_cost: z.number().optional(),
1629
+ date_created: z.string().optional(),
1630
+ last_updated: z.string().optional(),
1631
+ site_id: z.string().optional(),
1632
+ order_status: z.string().optional()
1633
+ }).passthrough();
1634
+ z.object({
1635
+ id: z.union([z.string(), z.number()]).transform(String),
1636
+ cbu: z.string().optional(),
1637
+ alias: z.string().nullable().optional(),
1638
+ bank_name: z.string().optional(),
1639
+ account_type: z.string().optional(),
1640
+ status: z.string().optional(),
1641
+ is_default: z.boolean().optional(),
1642
+ date_created: z.string().optional()
1643
+ }).passthrough();
1644
+ z.object({
1645
+ id: z.string(),
1646
+ pos_id: z.union([z.string(), z.number()]).nullable().optional(),
1647
+ store_id: z.union([z.string(), z.number()]).nullable().optional(),
1648
+ external_pos_id: z.string().nullable().optional(),
1649
+ operating_mode: z.union([z.literal("PDV"), z.literal("STANDALONE"), z.string()]).optional()
1650
+ }).passthrough();
1651
+ z.object({
1652
+ id: z.string(),
1653
+ device_id: z.string().optional(),
1654
+ amount: z.number().optional(),
1655
+ state: z.union([
1656
+ z.literal("OPEN"),
1657
+ z.literal("PROCESSING"),
1658
+ z.literal("FINISHED"),
1659
+ z.literal("CANCELED"),
1660
+ z.literal("ERROR"),
1661
+ z.string()
1662
+ ]).optional(),
1663
+ payment: z.object({
1664
+ id: z.union([z.string(), z.number()]).optional(),
1665
+ type: z.string().optional(),
1666
+ installments: z.number().optional(),
1667
+ installments_cost: z.string().optional(),
1668
+ print_on_terminal: z.boolean().optional()
1669
+ }).passthrough().optional(),
1670
+ additional_info: z.unknown().optional()
1671
+ }).passthrough();
1406
1672
 
1407
1673
  // src/oauth.ts
1408
1674
  var DEFAULT_AUTHORIZE_URL = "https://auth.mercadopago.com.ar/authorization";
@@ -1470,6 +1736,243 @@ function isExpiringSoon(expirationMs, skewSeconds = 300) {
1470
1736
  return Date.now() + skewSeconds * 1e3 >= expirationMs;
1471
1737
  }
1472
1738
 
1739
+ // src/helpers.ts
1740
+ function computeMarketplaceFee(amountArs, rule) {
1741
+ if (amountArs <= 0) return 0;
1742
+ const percentPart = (rule.percent ?? 0) > 0 ? amountArs * (rule.percent / 100) : 0;
1743
+ const flatPart = rule.flatArs ?? 0;
1744
+ let fee = percentPart + flatPart;
1745
+ if (rule.minArs !== void 0) fee = Math.max(fee, rule.minArs);
1746
+ if (rule.maxArs !== void 0) fee = Math.min(fee, rule.maxArs);
1747
+ if (fee > amountArs) fee = amountArs;
1748
+ if (rule.round !== false) fee = Math.round(fee);
1749
+ return fee;
1750
+ }
1751
+ var STATUS_DETAIL_MAP = {
1752
+ // Approved
1753
+ accredited: {
1754
+ summary: "Pago aprobado y acreditado.",
1755
+ recommendedAction: "Confirmar al cliente y continuar con el flujo (env\xEDo, factura).",
1756
+ retryable: false
1757
+ },
1758
+ partially_refunded: {
1759
+ summary: "Pago aprobado con reembolso parcial.",
1760
+ recommendedAction: "Mostrar el monto neto y el reembolso. Verificar inventario si corresponde.",
1761
+ retryable: false
1762
+ },
1763
+ // Pending
1764
+ pending_contingency: {
1765
+ summary: "Pago en proceso por contingencia. MP est\xE1 procesando \u2014 puede demorar minutos a horas.",
1766
+ recommendedAction: "No reintentar todav\xEDa. Esperar webhook de actualizaci\xF3n (puede demorar 24h m\xE1x).",
1767
+ retryable: false
1768
+ },
1769
+ pending_review_manual: {
1770
+ summary: "Pago en revisi\xF3n manual por el equipo de seguridad de MP.",
1771
+ recommendedAction: "No reintentar. MP responder\xE1 con webhook en 24-72h. Avisar al cliente sobre la demora.",
1772
+ retryable: false
1773
+ },
1774
+ pending_waiting_payment: {
1775
+ summary: "Esperando que el comprador complete el pago (t\xEDpico de account_money / boleto / Rapipago).",
1776
+ recommendedAction: "Mostrar instrucciones de pago. MP avisar\xE1 por webhook cuando se complete.",
1777
+ retryable: false
1778
+ },
1779
+ pending_waiting_transfer: {
1780
+ summary: "Esperando confirmaci\xF3n de transferencia bancaria.",
1781
+ recommendedAction: "Esperar webhook. Sin acci\xF3n del agente.",
1782
+ retryable: false
1783
+ },
1784
+ pending_challenge: {
1785
+ summary: "El emisor de la tarjeta requiri\xF3 autenticaci\xF3n 3DS. El comprador debe completar el desaf\xEDo.",
1786
+ recommendedAction: "Redirigir al comprador a `payment.three_ds_info.external_resource_url` (us\xE1 analyze_payment_3ds para obtenerlo).",
1787
+ retryable: false
1788
+ },
1789
+ // Rejected — RETRYABLE (user can fix and try again)
1790
+ cc_rejected_bad_filled_card_number: {
1791
+ summary: "El n\xFAmero de tarjeta es incorrecto.",
1792
+ recommendedAction: "Pedir al cliente que verifique el n\xFAmero. Reintentable.",
1793
+ retryable: true
1794
+ },
1795
+ cc_rejected_bad_filled_security_code: {
1796
+ summary: "El CVV es incorrecto.",
1797
+ recommendedAction: "Pedir el CVV nuevamente. Reintentable.",
1798
+ retryable: true
1799
+ },
1800
+ cc_rejected_bad_filled_date: {
1801
+ summary: "La fecha de vencimiento es incorrecta.",
1802
+ recommendedAction: "Pedir al cliente que verifique mes/a\xF1o. Reintentable.",
1803
+ retryable: true
1804
+ },
1805
+ cc_rejected_bad_filled_other: {
1806
+ summary: "Alg\xFAn dato de la tarjeta es incorrecto.",
1807
+ recommendedAction: "Pedir al cliente que revise todos los datos. Reintentable.",
1808
+ retryable: true
1809
+ },
1810
+ cc_rejected_call_for_authorize: {
1811
+ summary: "El emisor requiere que el cliente autorice el pago llamando al banco.",
1812
+ recommendedAction: "Mostrar el tel\xE9fono del banco emisor (us\xE1 list_issuers para obtenerlo). Reintentable despu\xE9s de la llamada.",
1813
+ retryable: true
1814
+ },
1815
+ cc_rejected_card_disabled: {
1816
+ summary: "La tarjeta est\xE1 inhabilitada por el banco emisor.",
1817
+ recommendedAction: "El cliente debe contactar a su banco. Probar con otra tarjeta. Reintentable con otra tarjeta.",
1818
+ retryable: true
1819
+ },
1820
+ cc_rejected_insufficient_amount: {
1821
+ summary: "Saldo insuficiente en la tarjeta.",
1822
+ recommendedAction: "Sugerir tarjeta alternativa o monto menor. Reintentable.",
1823
+ retryable: true
1824
+ },
1825
+ cc_rejected_invalid_installments: {
1826
+ summary: "El emisor no soporta esa cantidad de cuotas para esta tarjeta.",
1827
+ recommendedAction: "Llamar a calculate_installments para ver opciones v\xE1lidas y sugerir otra. Reintentable.",
1828
+ retryable: true
1829
+ },
1830
+ cc_rejected_other_reason: {
1831
+ summary: "Pago rechazado por raz\xF3n no especificada del emisor.",
1832
+ recommendedAction: "Sugerir otra tarjeta o m\xE9todo de pago. Reintentable con otra tarjeta.",
1833
+ retryable: true
1834
+ },
1835
+ // Rejected — NON-RETRYABLE (don't retry the same card)
1836
+ cc_rejected_blacklist: {
1837
+ summary: "Pago rechazado por blacklist de seguridad de MP. NO REINTENTAR con esta tarjeta.",
1838
+ recommendedAction: "Sugerir un m\xE9todo de pago alternativo (account_money, otra tarjeta de otro titular).",
1839
+ retryable: false
1840
+ },
1841
+ cc_rejected_high_risk: {
1842
+ summary: "Rechazo por an\xE1lisis de riesgo de MP. La tarjeta es v\xE1lida pero MP detect\xF3 fraude potencial.",
1843
+ recommendedAction: "Sugerir otro medio de pago o pedirle al cliente que verifique su identidad en MP.",
1844
+ retryable: false
1845
+ },
1846
+ cc_rejected_max_attempts: {
1847
+ summary: "Excedi\xF3 el n\xFAmero m\xE1ximo de intentos con esta tarjeta.",
1848
+ recommendedAction: "Pedir al cliente que use otra tarjeta. NO REINTENTAR la misma.",
1849
+ retryable: false
1850
+ },
1851
+ cc_rejected_duplicated_payment: {
1852
+ summary: "Ya se proces\xF3 un pago id\xE9ntico en los \xFAltimos minutos (deduplicaci\xF3n de MP).",
1853
+ recommendedAction: "Verificar con search_payments si el pago anterior se acredit\xF3. Sin acci\xF3n adicional necesaria.",
1854
+ retryable: false
1855
+ },
1856
+ // Cancelled / refunded / mediation
1857
+ by_collector: {
1858
+ summary: "El vendedor cancel\xF3 el pago.",
1859
+ recommendedAction: "Sin acci\xF3n. Estado final.",
1860
+ retryable: false
1861
+ },
1862
+ by_payer: {
1863
+ summary: "El comprador cancel\xF3 el pago.",
1864
+ recommendedAction: "Sin acci\xF3n. Estado final.",
1865
+ retryable: false
1866
+ },
1867
+ refunded: {
1868
+ summary: "Pago reembolsado al comprador.",
1869
+ recommendedAction: "Estado final. Reflejar el reembolso en tu sistema.",
1870
+ retryable: false
1871
+ },
1872
+ charged_back: {
1873
+ summary: "Contracargo (chargeback) iniciado por el banco emisor.",
1874
+ recommendedAction: "Revisar list_payment_disputes para responder. Surface al equipo de ops.",
1875
+ retryable: false
1876
+ }
1877
+ };
1878
+ function explainPaymentStatus(payment) {
1879
+ const status = payment.status;
1880
+ const statusDetail = payment.status_detail ?? "";
1881
+ const detail = STATUS_DETAIL_MAP[statusDetail];
1882
+ if (detail) {
1883
+ const isFinal = status === "approved" || status === "rejected" || status === "cancelled" || status === "refunded" || status === "charged_back";
1884
+ return {
1885
+ summary: detail.summary,
1886
+ recommendedAction: detail.recommendedAction,
1887
+ final: isFinal,
1888
+ paid: status === "approved",
1889
+ retryable: detail.retryable
1890
+ };
1891
+ }
1892
+ switch (status) {
1893
+ case "approved":
1894
+ return {
1895
+ summary: "Pago aprobado.",
1896
+ recommendedAction: "Continuar con el flujo posterior (env\xEDo, factura, notificaci\xF3n).",
1897
+ final: true,
1898
+ paid: true,
1899
+ retryable: false
1900
+ };
1901
+ case "authorized":
1902
+ return {
1903
+ summary: "Pago autorizado pero no capturado (auth-only).",
1904
+ recommendedAction: "Llamar a capture_payment cuando complet\xE9s el servicio. Vence en 7 d\xEDas si no captur\xE1s.",
1905
+ final: false,
1906
+ paid: false,
1907
+ retryable: false
1908
+ };
1909
+ case "in_process":
1910
+ return {
1911
+ summary: "Pago en proceso.",
1912
+ recommendedAction: "Esperar webhook. Sin acci\xF3n inmediata.",
1913
+ final: false,
1914
+ paid: false,
1915
+ retryable: false
1916
+ };
1917
+ case "in_mediation":
1918
+ return {
1919
+ summary: "Pago en mediaci\xF3n con MP por disputa del comprador.",
1920
+ recommendedAction: "Revisar list_payment_disputes y responder via dashboard.",
1921
+ final: false,
1922
+ paid: false,
1923
+ retryable: false
1924
+ };
1925
+ case "pending":
1926
+ return {
1927
+ summary: "Pago pendiente. El comprador no complet\xF3 el pago todav\xEDa o MP est\xE1 procesando.",
1928
+ recommendedAction: "Esperar webhook (puede demorar minutos a 72h seg\xFAn el m\xE9todo).",
1929
+ final: false,
1930
+ paid: false,
1931
+ retryable: false
1932
+ };
1933
+ case "rejected":
1934
+ return {
1935
+ summary: `Pago rechazado (status_detail: ${statusDetail || "no especificado"}).`,
1936
+ recommendedAction: "Verificar status_detail. Considerar otro m\xE9todo de pago.",
1937
+ final: true,
1938
+ paid: false,
1939
+ retryable: true
1940
+ };
1941
+ case "cancelled":
1942
+ return {
1943
+ summary: "Pago cancelado.",
1944
+ recommendedAction: "Estado final. Sin acci\xF3n.",
1945
+ final: true,
1946
+ paid: false,
1947
+ retryable: false
1948
+ };
1949
+ case "refunded":
1950
+ return {
1951
+ summary: "Pago reembolsado.",
1952
+ recommendedAction: "Estado final. Reflejar el reembolso.",
1953
+ final: true,
1954
+ paid: false,
1955
+ retryable: false
1956
+ };
1957
+ case "charged_back":
1958
+ return {
1959
+ summary: "Pago con contracargo del banco.",
1960
+ recommendedAction: "Surfacear a ops. Revisar disputas.",
1961
+ final: true,
1962
+ paid: false,
1963
+ retryable: false
1964
+ };
1965
+ default:
1966
+ return {
1967
+ summary: `Status no reconocido: '${status}'.`,
1968
+ recommendedAction: "Inspeccionar payment.status + payment.status_detail manualmente.",
1969
+ final: false,
1970
+ paid: false,
1971
+ retryable: false
1972
+ };
1973
+ }
1974
+ }
1975
+
1473
1976
  // src/test-cards.ts
1474
1977
  var TEST_CARDS_AR = {
1475
1978
  VISA_CREDIT: {
@@ -1707,7 +2210,41 @@ var DEFAULT_DESCRIPTIONS = {
1707
2210
  // ── 3DS analyzer (v0.6 — pure) ───────────────────────────────────────────
1708
2211
  analyze_payment_3ds: "Pure local analyzer for a Payment's 3DS (Strong Customer Authentication) state. Pass a payment_id (string) and the tool fetches the Payment then derives { status: 'not_required'|'frictionless'|'challenge_required'|'rejected'|'unknown', mode, challengeUrl, description }. USE THIS after every create_payment for credit cards: when challengeUrl !== null, you MUST redirect the buyer there before the payment can complete. Without 3DS, payments stay in 'pending' indefinitely if the issuer demanded a challenge.",
1709
2212
  // ── Test cards (v0.6 — pure) ─────────────────────────────────────────────
1710
- get_test_cards: "Pure helper that returns the official MP test cards for AR (MLA): VISA/Mastercard/Amex credit + debit, with the 'magic' holder names that route the payment to specific status_detail values (APRO=approved, OTHE=rejected, CONT=pending, FUND=insufficient_amount, etc.). USE WHEN you need to demo a payment flow without a real card, or to script integration tests. Pure data \u2014 no network call."
2213
+ get_test_cards: "Pure helper that returns the official MP test cards for AR (MLA): VISA/Mastercard/Amex credit + debit, with the 'magic' holder names that route the payment to specific status_detail values (APRO=approved, OTHE=rejected, CONT=pending, FUND=insufficient_amount, etc.). USE WHEN you need to demo a payment flow without a real card, or to script integration tests. Pure data \u2014 no network call.",
2214
+ // ── Customer + Card extensions (v0.7) ────────────────────────────────────
2215
+ get_customer: "Get a customer by id. Returns full Customer object: email, first_name, last_name, identification, address, default_card, registered cards. PURE READ. USE WHEN you have the customer_id from a previous create_customer / find_customer_by_email / payment.payer.id and want the full record.",
2216
+ update_customer: "Update a customer's profile (first_name, last_name, phone, identification, address, default_card). MP merges the patch \u2014 fields you don't send remain unchanged. Use to keep customer records in sync (e.g., shipping address changes) or to set a default card for charge_saved_card.",
2217
+ create_customer_card: "Add a saved card to an existing customer using a card_token (one-time token from MP frontend Cardform \u2014 agents should NEVER take raw card data, that's a PCI violation). Returns the saved CustomerCard with id usable in charge_saved_card. Persists across charges (no need to re-tokenize each time).",
2218
+ get_customer_card: "Get details of a single saved card by (customer_id, card_id). Returns last 4 digits, expiration, brand, issuer. PURE READ \u2014 useful before charge_saved_card to confirm the card is still valid.",
2219
+ // ── Subscription / Plan / Refund / Preference extensions (v0.7) ─────────
2220
+ get_subscription_plan: "Fetch a subscription plan by id. Returns plan config: amount, frequency, status, init_point. Use to inspect a plan before subscribing customers, or to display plan details to the user.",
2221
+ update_subscription: "Update a subscription's amount, status, reason, external_reference, OR card_token_id (to switch payment method when the buyer's card is expired/declined). For card swap: pass card_token_id from a fresh tokenization. CONSTRAINTS: status changes only support 'paused' | 'cancelled' (use authorize via init_point flow to re-activate).",
2222
+ search_subscriptions: "Search subscriptions across the seller's account. Filter by status (pending/authorized/paused/cancelled), payer_email, external_reference, or preapproval_plan_id (to find all subscribers of a plan). Paginated. USE WHEN you need to enumerate active subscribers, audit cancellations, or find a subscription by external reference.",
2223
+ get_refund: "Fetch a single refund by (payment_id, refund_id). Returns the Refund object with amount, status, date_created. PURE READ \u2014 useful to verify a refund processed or to reconcile partial-refund history.",
2224
+ update_payment_preference: "Update a Checkout Pro preference (notification_url, back_urls, items, payer info, payment_methods exclusion list). Only works on preferences NOT yet paid. Common use: regenerate the link with a new notification_url after deployment, or change items if the buyer requested adjustments before paying.",
2225
+ // ── Merchant Orders (v0.7) ────────────────────────────────────────────────
2226
+ get_merchant_order: "Get a merchant_order with all its associated payments + shipments. MerchantOrder is the parent entity for Payments associated with a single Preference \u2014 one Order can have multiple partial Payments (retries, installments). USE THIS in webhooks with topic='merchant_order' to get the aggregate paid_amount, refunded_amount, and shipping status in one call.",
2227
+ search_merchant_orders: "Search merchant_orders by preference_id, external_reference, or status. Paginated. Returns up to 50 per page. USE WHEN you have a preference_id and want all its derived merchant_orders, or when reconciling 'which payments belong to which preference'.",
2228
+ update_merchant_order: "Update a merchant_order \u2014 typically to add items or shipping info. Most agent flows don't need this; use only when integrating with a custom shipping flow that requires updating the MO mid-lifecycle.",
2229
+ // ── Stores + POS CRUD completion (v0.7) ──────────────────────────────────
2230
+ get_store: "Fetch a single store by (user_id, store_id). Returns store details: name, location, business_hours, external_id. PURE READ.",
2231
+ update_store: "Update a store's properties (name, location, business_hours, external_id). MP merges the patch.",
2232
+ delete_store: "Delete a store. IRREVERSIBLE. Confirm with user before calling. Will fail if the store has associated POSes \u2014 delete those first.",
2233
+ get_pos: "Fetch a POS by id. Returns: name, store_id, category, external_id, qr_template (if configured). PURE READ. Use when you need to find the external_id for create_qr_payment.",
2234
+ update_pos: "Update a POS's properties (name, category, external_id). MP merges the patch.",
2235
+ delete_pos: "Delete a POS. IRREVERSIBLE. Cancels any pending QR orders attached to it. Confirm with user before calling.",
2236
+ // ── Bank Accounts (v0.7) ─────────────────────────────────────────────────
2237
+ list_bank_accounts: "List the bank accounts (CBUs) the seller has registered with MP for receiving payouts. Returns an array \u2014 the one with `is_default: true` is where settlements (release_money) go. USE BEFORE list_settlements when the user asks 'a qu\xE9 cuenta me deposita MP'.",
2238
+ register_bank_account: "Register a new bank account (CBU) for the seller. NOTE: MP usually requires this through the dashboard for compliance \u2014 this endpoint may not work for all accounts. If it fails with 403, redirect the user to https://www.mercadopago.com.ar/banking/dashboard.",
2239
+ // ── Point Devices físicos (v0.7) ─────────────────────────────────────────
2240
+ list_point_devices: "List the physical Point devices (Smart, Tap to Pay, etc.) linked to the seller's MP account. Distinct from logical POS \u2014 these are actual terminals at brick-and-mortar shops. Returns each device's id (serial), operating_mode (PDV vs STANDALONE), and pos_id (when bound to a logical POS). Filter by pos_id to find devices for a specific cash register.",
2241
+ update_point_device_mode: "Switch a Point device's operating_mode between 'PDV' (bound to a logical POS, takes payments triggered through that POS) and 'STANDALONE' (works independently, accepts any payment). PDV is for cash-register integrations; STANDALONE is for free-form retail. Affects how payments hit the device.",
2242
+ create_point_payment_intent: "Create a payment intent on a physical Point device \u2014 the device prompts the buyer to tap/insert/swipe their card. Returns immediately with intent_id; query state via get_point_payment_intent or wait for point_integration_wh webhook. **AMOUNT IS IN CENTAVOS**, NOT pesos (Point API differs from Payments API): 100 = $1, 1000 = $10, 10000 = $100.",
2243
+ get_point_payment_intent: "Get the current state of a Point payment intent (OPEN, PROCESSING, FINISHED, CANCELED, ERROR). USE in polling loops if you can't wait for the webhook. When state=FINISHED, the intent.payment.id is the resulting Payment id usable with get_payment.",
2244
+ cancel_point_payment_intent: "Cancel an OPEN point payment intent before the buyer interacts with the device. ONLY WORKS while state='OPEN' \u2014 once the buyer taps, you can't cancel; refund_payment after the fact instead.",
2245
+ // ── Pure helpers (v0.7) ──────────────────────────────────────────────────
2246
+ compute_marketplace_fee: "PURE HELPER (no network) \u2014 given a transaction amount + fee rule (% or flat ARS, with optional min/max floors), returns the exact `marketplace_fee` value in ARS to pass to create_order or create_payment_preference. USE WHEN your platform takes a commission and you need to compute the exact fee per transaction. Examples: { percent: 5, minArs: 50, maxArs: 5000 } for percentage with floor + cap; { flatArs: 200, percent: 2 } for fixed + percentage.",
2247
+ explain_payment_status: "PURE HELPER (no network) \u2014 given a Payment object (from get_payment / create_payment / handle_webhook), returns { summary, recommendedAction, final, paid, retryable } in Spanish. Translates MP's cryptic status_detail codes to plain Spanish + actionable guidance ('reintentar con otra tarjeta' vs 'esperar webhook' vs 'estado final'). USE THIS instead of having to memorize 30+ status_detail codes \u2014 surface summary + recommendedAction directly to the user."
1711
2248
  };
1712
2249
  function mercadoPagoTools(client, options) {
1713
2250
  const desc = (name) => options.descriptions?.[name] ?? DEFAULT_DESCRIPTIONS[name];
@@ -3101,6 +3638,396 @@ function mercadoPagoTools(client, options) {
3101
3638
  usage: "Pass holderName='APRO' for an approved payment, 'OTHE' for rejected, 'CONT' for pending, 'FUND' for insufficient amount, 'CALL' for call-for-authorize. Use a NEW payer email per call (append a timestamp) to avoid MP idempotency-on-email deduping."
3102
3639
  };
3103
3640
  }
3641
+ }),
3642
+ // ─────────────────────────────────────────────────────────────────────────
3643
+ // v0.7 — Customer + Card extensions
3644
+ // ─────────────────────────────────────────────────────────────────────────
3645
+ get_customer: tool({
3646
+ description: desc("get_customer"),
3647
+ inputSchema: z.object({ customer_id: z.string() }),
3648
+ execute: async ({ customer_id }) => {
3649
+ return client.getCustomer(customer_id);
3650
+ }
3651
+ }),
3652
+ update_customer: tool({
3653
+ description: desc("update_customer"),
3654
+ inputSchema: z.object({
3655
+ customer_id: z.string(),
3656
+ first_name: z.string().optional(),
3657
+ last_name: z.string().optional(),
3658
+ phone: z.object({ area_code: z.string().optional(), number: z.string().optional() }).optional(),
3659
+ identification: z.object({ type: z.string(), number: z.string() }).optional(),
3660
+ address: z.object({
3661
+ street_name: z.string().optional(),
3662
+ street_number: z.number().optional(),
3663
+ zip_code: z.string().optional()
3664
+ }).optional(),
3665
+ description: z.string().optional(),
3666
+ default_card: z.string().optional()
3667
+ }),
3668
+ execute: async ({ customer_id, ...patch }) => {
3669
+ const cleaned = {};
3670
+ for (const [k, v] of Object.entries(patch)) {
3671
+ if (v !== void 0) cleaned[k] = v;
3672
+ }
3673
+ return client.updateCustomer(customer_id, cleaned);
3674
+ }
3675
+ }),
3676
+ create_customer_card: tool({
3677
+ description: desc("create_customer_card"),
3678
+ inputSchema: z.object({
3679
+ customer_id: z.string(),
3680
+ card_token: z.string().describe("Card token from MP frontend Cardform OR create_card_token.")
3681
+ }),
3682
+ execute: async ({ customer_id, card_token }) => {
3683
+ return client.createCustomerCard(customer_id, card_token);
3684
+ }
3685
+ }),
3686
+ get_customer_card: tool({
3687
+ description: desc("get_customer_card"),
3688
+ inputSchema: z.object({
3689
+ customer_id: z.string(),
3690
+ card_id: z.string()
3691
+ }),
3692
+ execute: async ({ customer_id, card_id }) => {
3693
+ return client.getCustomerCard(customer_id, card_id);
3694
+ }
3695
+ }),
3696
+ // ─────────────────────────────────────────────────────────────────────────
3697
+ // v0.7 — Subscription / Plan / Refund / Preference extensions
3698
+ // ─────────────────────────────────────────────────────────────────────────
3699
+ get_subscription_plan: tool({
3700
+ description: desc("get_subscription_plan"),
3701
+ inputSchema: z.object({ plan_id: z.string() }),
3702
+ execute: async ({ plan_id }) => {
3703
+ return client.getSubscriptionPlan(plan_id);
3704
+ }
3705
+ }),
3706
+ update_subscription: tool({
3707
+ description: desc("update_subscription"),
3708
+ inputSchema: z.object({
3709
+ subscription_id: z.string(),
3710
+ transaction_amount: z.number().positive().optional(),
3711
+ card_token_id: z.string().optional(),
3712
+ status: z.enum(["authorized", "paused", "cancelled"]).optional(),
3713
+ reason: z.string().optional(),
3714
+ external_reference: z.string().optional()
3715
+ }),
3716
+ execute: async ({ subscription_id, ...patch }) => {
3717
+ const cleaned = {};
3718
+ for (const [k, v] of Object.entries(patch)) {
3719
+ if (v !== void 0) cleaned[k] = v;
3720
+ }
3721
+ return client.updatePreapproval(subscription_id, cleaned);
3722
+ }
3723
+ }),
3724
+ search_subscriptions: tool({
3725
+ description: desc("search_subscriptions"),
3726
+ inputSchema: z.object({
3727
+ status: z.string().optional(),
3728
+ payer_email: z.string().email().optional(),
3729
+ external_reference: z.string().optional(),
3730
+ plan_id: z.string().optional(),
3731
+ limit: z.number().int().min(1).max(100).optional(),
3732
+ offset: z.number().int().min(0).optional()
3733
+ }),
3734
+ execute: async ({ status, payer_email, external_reference, plan_id, limit, offset }) => {
3735
+ const params = {};
3736
+ if (status !== void 0) params.status = status;
3737
+ if (payer_email !== void 0) params.payerEmail = payer_email;
3738
+ if (external_reference !== void 0) params.externalReference = external_reference;
3739
+ if (plan_id !== void 0) params.preapproval_plan_id = plan_id;
3740
+ if (limit !== void 0) params.limit = limit;
3741
+ if (offset !== void 0) params.offset = offset;
3742
+ return client.searchPreapprovals(params);
3743
+ }
3744
+ }),
3745
+ get_refund: tool({
3746
+ description: desc("get_refund"),
3747
+ inputSchema: z.object({
3748
+ payment_id: z.string(),
3749
+ refund_id: z.string()
3750
+ }),
3751
+ execute: async ({ payment_id, refund_id }) => {
3752
+ return client.getRefund(payment_id, refund_id);
3753
+ }
3754
+ }),
3755
+ update_payment_preference: tool({
3756
+ description: desc("update_payment_preference"),
3757
+ inputSchema: z.object({
3758
+ preference_id: z.string(),
3759
+ notification_url: z.string().url().optional(),
3760
+ external_reference: z.string().optional(),
3761
+ statement_descriptor: z.string().optional()
3762
+ }),
3763
+ execute: async ({ preference_id, ...patch }) => {
3764
+ const cleaned = {};
3765
+ for (const [k, v] of Object.entries(patch)) {
3766
+ if (v !== void 0) cleaned[k] = v;
3767
+ }
3768
+ return client.updatePreference(preference_id, cleaned);
3769
+ }
3770
+ }),
3771
+ // ─────────────────────────────────────────────────────────────────────────
3772
+ // v0.7 — Merchant Orders
3773
+ // ─────────────────────────────────────────────────────────────────────────
3774
+ get_merchant_order: tool({
3775
+ description: desc("get_merchant_order"),
3776
+ inputSchema: z.object({ merchant_order_id: z.string() }),
3777
+ execute: async ({ merchant_order_id }) => {
3778
+ return client.getMerchantOrder(merchant_order_id);
3779
+ }
3780
+ }),
3781
+ search_merchant_orders: tool({
3782
+ description: desc("search_merchant_orders"),
3783
+ inputSchema: z.object({
3784
+ preference_id: z.string().optional(),
3785
+ external_reference: z.string().optional(),
3786
+ status: z.string().optional(),
3787
+ limit: z.number().int().min(1).max(100).optional(),
3788
+ offset: z.number().int().min(0).optional()
3789
+ }),
3790
+ execute: async ({ preference_id, external_reference, status, limit, offset }) => {
3791
+ const params = {};
3792
+ if (preference_id !== void 0) params.preferenceId = preference_id;
3793
+ if (external_reference !== void 0) params.externalReference = external_reference;
3794
+ if (status !== void 0) params.status = status;
3795
+ if (limit !== void 0) params.limit = limit;
3796
+ if (offset !== void 0) params.offset = offset;
3797
+ return client.searchMerchantOrders(params);
3798
+ }
3799
+ }),
3800
+ update_merchant_order: tool({
3801
+ description: desc("update_merchant_order"),
3802
+ inputSchema: z.object({
3803
+ merchant_order_id: z.string(),
3804
+ patch: z.record(z.string(), z.unknown())
3805
+ }),
3806
+ execute: async ({ merchant_order_id, patch }) => {
3807
+ return client.updateMerchantOrder(merchant_order_id, patch);
3808
+ }
3809
+ }),
3810
+ // ─────────────────────────────────────────────────────────────────────────
3811
+ // v0.7 — Stores + POS CRUD completion
3812
+ // ─────────────────────────────────────────────────────────────────────────
3813
+ get_store: tool({
3814
+ description: desc("get_store"),
3815
+ inputSchema: z.object({
3816
+ user_id: z.string(),
3817
+ store_id: z.string()
3818
+ }),
3819
+ execute: async ({ user_id, store_id }) => {
3820
+ return client.getStore(user_id, store_id);
3821
+ }
3822
+ }),
3823
+ update_store: tool({
3824
+ description: desc("update_store"),
3825
+ inputSchema: z.object({
3826
+ user_id: z.string(),
3827
+ store_id: z.string(),
3828
+ name: z.string().optional(),
3829
+ external_id: z.string().optional()
3830
+ }),
3831
+ execute: async ({ user_id, store_id, ...patch }) => {
3832
+ const cleaned = {};
3833
+ for (const [k, v] of Object.entries(patch)) {
3834
+ if (v !== void 0) cleaned[k] = v;
3835
+ }
3836
+ return client.updateStore(user_id, store_id, cleaned);
3837
+ }
3838
+ }),
3839
+ delete_store: tool({
3840
+ description: desc("delete_store"),
3841
+ inputSchema: z.object({
3842
+ user_id: z.string(),
3843
+ store_id: z.string()
3844
+ }),
3845
+ execute: async ({ user_id, store_id }) => {
3846
+ await client.deleteStore(user_id, store_id);
3847
+ return { user_id, store_id, deleted: true };
3848
+ }
3849
+ }),
3850
+ get_pos: tool({
3851
+ description: desc("get_pos"),
3852
+ inputSchema: z.object({ pos_id: z.string() }),
3853
+ execute: async ({ pos_id }) => {
3854
+ return client.getPos(pos_id);
3855
+ }
3856
+ }),
3857
+ update_pos: tool({
3858
+ description: desc("update_pos"),
3859
+ inputSchema: z.object({
3860
+ pos_id: z.string(),
3861
+ name: z.string().optional(),
3862
+ external_id: z.string().optional(),
3863
+ category: z.number().optional()
3864
+ }),
3865
+ execute: async ({ pos_id, ...patch }) => {
3866
+ const cleaned = {};
3867
+ for (const [k, v] of Object.entries(patch)) {
3868
+ if (v !== void 0) cleaned[k] = v;
3869
+ }
3870
+ return client.updatePos(pos_id, cleaned);
3871
+ }
3872
+ }),
3873
+ delete_pos: tool({
3874
+ description: desc("delete_pos"),
3875
+ inputSchema: z.object({ pos_id: z.string() }),
3876
+ execute: async ({ pos_id }) => {
3877
+ await client.deletePos(pos_id);
3878
+ return { pos_id, deleted: true };
3879
+ }
3880
+ }),
3881
+ // ─────────────────────────────────────────────────────────────────────────
3882
+ // v0.7 — Bank Accounts
3883
+ // ─────────────────────────────────────────────────────────────────────────
3884
+ list_bank_accounts: tool({
3885
+ description: desc("list_bank_accounts"),
3886
+ inputSchema: z.object({}),
3887
+ execute: async () => {
3888
+ const accounts = await client.listBankAccounts();
3889
+ return { accounts };
3890
+ }
3891
+ }),
3892
+ register_bank_account: tool({
3893
+ description: desc("register_bank_account"),
3894
+ inputSchema: z.object({
3895
+ cbu: z.string().regex(/^\d{22}$/),
3896
+ alias: z.string().optional()
3897
+ }),
3898
+ execute: async (input) => {
3899
+ const params = {
3900
+ cbu: input.cbu
3901
+ };
3902
+ if (input.alias !== void 0) params.alias = input.alias;
3903
+ return client.registerBankAccount(params);
3904
+ }
3905
+ }),
3906
+ // ─────────────────────────────────────────────────────────────────────────
3907
+ // v0.7 — Point Devices físicos
3908
+ // ─────────────────────────────────────────────────────────────────────────
3909
+ list_point_devices: tool({
3910
+ description: desc("list_point_devices"),
3911
+ inputSchema: z.object({
3912
+ pos_id: z.union([z.string(), z.number()]).optional(),
3913
+ limit: z.number().int().min(1).max(100).optional(),
3914
+ offset: z.number().int().min(0).optional()
3915
+ }),
3916
+ execute: async ({ pos_id, limit, offset }) => {
3917
+ const params = {};
3918
+ if (pos_id !== void 0) params.posId = pos_id;
3919
+ if (limit !== void 0) params.limit = limit;
3920
+ if (offset !== void 0) params.offset = offset;
3921
+ return client.listPointDevices(params);
3922
+ }
3923
+ }),
3924
+ update_point_device_mode: tool({
3925
+ description: desc("update_point_device_mode"),
3926
+ inputSchema: z.object({
3927
+ device_id: z.string(),
3928
+ operating_mode: z.enum(["PDV", "STANDALONE"])
3929
+ }),
3930
+ execute: async ({ device_id, operating_mode }) => {
3931
+ return client.updatePointDeviceOperatingMode(device_id, operating_mode);
3932
+ }
3933
+ }),
3934
+ create_point_payment_intent: tool({
3935
+ description: desc("create_point_payment_intent"),
3936
+ inputSchema: z.object({
3937
+ device_id: z.string(),
3938
+ amount_centavos: z.number().int().positive().describe("Amount in CENTAVOS (NOT pesos). 100 = $1, 1000 = $10, 10000 = $100."),
3939
+ description: z.string().optional(),
3940
+ external_reference: z.string().optional(),
3941
+ installments: z.number().int().min(1).max(24).optional(),
3942
+ installments_cost: z.enum(["seller", "buyer"]).optional(),
3943
+ print_on_terminal: z.boolean().optional(),
3944
+ ticket_number: z.string().optional()
3945
+ }),
3946
+ execute: async (input) => {
3947
+ const params = {
3948
+ amount: input.amount_centavos
3949
+ };
3950
+ if (input.description !== void 0) params.description = input.description;
3951
+ if (input.external_reference !== void 0) params.externalReference = input.external_reference;
3952
+ if (input.installments !== void 0) params.installments = input.installments;
3953
+ if (input.installments_cost !== void 0) params.installmentsCost = input.installments_cost;
3954
+ if (input.print_on_terminal !== void 0) params.printOnTerminal = input.print_on_terminal;
3955
+ if (input.ticket_number !== void 0) params.ticketNumber = input.ticket_number;
3956
+ return client.createPointPaymentIntent(input.device_id, params);
3957
+ }
3958
+ }),
3959
+ get_point_payment_intent: tool({
3960
+ description: desc("get_point_payment_intent"),
3961
+ inputSchema: z.object({ intent_id: z.string() }),
3962
+ execute: async ({ intent_id }) => {
3963
+ return client.getPointPaymentIntent(intent_id);
3964
+ }
3965
+ }),
3966
+ cancel_point_payment_intent: tool({
3967
+ description: desc("cancel_point_payment_intent"),
3968
+ inputSchema: z.object({
3969
+ device_id: z.string(),
3970
+ intent_id: z.string()
3971
+ }),
3972
+ execute: async ({ device_id, intent_id }) => {
3973
+ return client.cancelPointPaymentIntent(device_id, intent_id);
3974
+ }
3975
+ }),
3976
+ // ─────────────────────────────────────────────────────────────────────────
3977
+ // v0.7 — Pure helpers
3978
+ // ─────────────────────────────────────────────────────────────────────────
3979
+ compute_marketplace_fee: tool({
3980
+ description: desc("compute_marketplace_fee"),
3981
+ inputSchema: z.object({
3982
+ amount_ars: z.number().positive(),
3983
+ flat_ars: z.number().nonnegative().optional(),
3984
+ percent: z.number().min(0).max(100).optional(),
3985
+ min_ars: z.number().nonnegative().optional(),
3986
+ max_ars: z.number().nonnegative().optional(),
3987
+ round: z.boolean().optional()
3988
+ }),
3989
+ execute: async (input) => {
3990
+ const rule = {};
3991
+ if (input.flat_ars !== void 0) rule.flatArs = input.flat_ars;
3992
+ if (input.percent !== void 0) rule.percent = input.percent;
3993
+ if (input.min_ars !== void 0) rule.minArs = input.min_ars;
3994
+ if (input.max_ars !== void 0) rule.maxArs = input.max_ars;
3995
+ if (input.round !== void 0) rule.round = input.round;
3996
+ const fee = computeMarketplaceFee(input.amount_ars, rule);
3997
+ return {
3998
+ amount_ars: input.amount_ars,
3999
+ marketplace_fee: fee,
4000
+ seller_receives: input.amount_ars - fee,
4001
+ rule_applied: rule
4002
+ };
4003
+ }
4004
+ }),
4005
+ explain_payment_status: tool({
4006
+ description: desc("explain_payment_status"),
4007
+ inputSchema: z.object({
4008
+ payment_id: z.string().optional().describe("If provided, fetches the Payment first."),
4009
+ payment: z.record(z.string(), z.unknown()).optional().describe("Alternatively, pass a Payment object directly (saves a network round-trip).")
4010
+ }),
4011
+ execute: async ({ payment_id, payment }) => {
4012
+ let p;
4013
+ if (payment) {
4014
+ p = payment;
4015
+ } else if (payment_id) {
4016
+ p = await client.getPayment(payment_id);
4017
+ } else {
4018
+ return {
4019
+ ok: false,
4020
+ error: "Pass either payment_id or payment."
4021
+ };
4022
+ }
4023
+ const explanation = explainPaymentStatus(p);
4024
+ return {
4025
+ ok: true,
4026
+ payment_status: p.status,
4027
+ payment_status_detail: p.status_detail ?? null,
4028
+ ...explanation
4029
+ };
4030
+ }
3104
4031
  })
3105
4032
  };
3106
4033
  }
@@ -3124,6 +4051,6 @@ var InMemoryStateAdapter = class {
3124
4051
  }
3125
4052
  };
3126
4053
 
3127
- export { InMemoryStateAdapter, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, TEST_CARDS_AR, TEST_PAYERS_AR, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, exchangeCodeForToken, expirationTimeMs, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
4054
+ export { InMemoryStateAdapter, MercadoPagoAccountTypeMismatchError, MercadoPagoAuthError, MercadoPagoAuthorizeForbiddenError, MercadoPagoBackUrlInvalidError, MercadoPagoClient, MercadoPagoError, MercadoPagoOverloadedError, MercadoPagoPaymentRejectedError, MercadoPagoRateLimitError, MercadoPagoSelfPaymentError, MercadoPagoTimeoutError, TEST_CARDS_AR, TEST_PAYERS_AR, analyze3DS, buildAuthorizeUrl, buildTestCardScenario, classifyError, computeMarketplaceFee, exchangeCodeForToken, expirationTimeMs, explainPaymentStatus, isExpiringSoon, mercadoPagoTools, parseWebhookEvent, refreshAccessToken, verifyWebhookSignature };
3128
4055
  //# sourceMappingURL=index.js.map
3129
4056
  //# sourceMappingURL=index.js.map