@ar-agents/mercadopago 0.3.0 → 0.5.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 CHANGED
@@ -1,4 +1,4 @@
1
- # @ar-agents/mercadopago — agent guide (v0.2)
1
+ # @ar-agents/mercadopago — agent guide (v0.5)
2
2
 
3
3
  This file is for AI agents using or recommending this package. Humans should start with [README.md](./README.md). Format follows the [agents.md convention](https://agents.md/).
4
4
 
@@ -22,6 +22,20 @@ This file is for AI agents using or recommending this package. Humans should sta
22
22
  | **"Listame los métodos disponibles"** | `list_payment_methods` |
23
23
  | **"¿Quién soy?" / "¿En qué cuenta estoy?"** | `get_account_info` |
24
24
  | **"Pausá / Reactivá / Cancelá la suscripción"** | `pause_subscription` / `resume_subscription` / `cancel_subscription` |
25
+ | **"Listame los cobros recurrentes del último mes"** | `list_subscription_payments` (authorized_payments under a preapproval) |
26
+ | **"Quiero un plan reutilizable de $X/mes"** | `create_subscription_plan` → after, `subscribe_to_plan(plan_id, customer)` per buyer |
27
+ | **"Mostrame los planes que tengo configurados"** | `list_subscription_plans` |
28
+ | **"Cambiá el precio del Plan Pro a $30k"** | `update_subscription_plan(plan_id, amount: 30000)` (existing subscribers keep old price; only NEW signups pay new) |
29
+ | **"Necesito armar un POS para cobrar con QR en mi local"** | `list_stores` → if empty `create_store` → then `create_pos(store_id)` → then `create_qr_payment(external_pos_id)` |
30
+ | **"Mostrame las disputas que tiene este pago"** | `list_payment_disputes(payment_id)` (read-only; surface `dashboard_url` to user) |
31
+ | **"Qué bancos emiten Visa?"** | `list_issuers(payment_method_id: "visa")` (pass `bin` for accurate match) |
32
+ | **"Listame los tipos de identificación válidos en AR"** | `list_identification_types` (DNI/CUIT/CUIL/etc) |
33
+ | **"Configurame un webhook para recibir notificaciones de pagos"** | `list_webhooks` first, then `create_webhook(url, topic: "payment")` if not present |
34
+ | **"Procesame este webhook que me llegó de MP"** (v0.5) | `handle_webhook` — verifica HMAC + parsea + auto-fetch del recurso en una sola call |
35
+ | **"Vincular cuenta MP de un vendedor a mi marketplace"** (v0.5) | `oauth_authorize_url` → vendedor aprueba → `oauth_exchange_code` → persistir token → `oauth_refresh_token` cuando expira |
36
+ | **"Cobrar a través de un seller third-party con fee de marketplace"** (v0.5) | `create_order` con `marketplace_fee` + `collector_id` (o `create_payment_preference` con los mismos campos) |
37
+ | **"Autorizar ahora, capturar después"** (ride-share, hotel, marketplace) (v0.5) | `create_order` con `capture_mode: "manual"` → cuando completás el servicio, `capture_order(order_id)` |
38
+ | **"Cancelar una orden no capturada"** (v0.5) | `cancel_order` (libera el auth-hold). Si ya capturó, usá `refund_payment`. |
25
39
 
26
40
  ## The two main "take a payment" patterns
27
41
 
@@ -188,10 +202,75 @@ v0.2 ships `parseWebhookEvent()` for the `preapproval` topic (subscription lifec
188
202
  - Take raw card data in the agent runtime (PCI scope violation).
189
203
  - Bypass MP's first-payment-CVV requirement for subscriptions (impossible).
190
204
  - Reactivate a cancelled subscription or payment (MP doesn't allow).
191
- - Implement Marketplace splits (different MP product, different OAuth flow — out of scope until v0.4+).
192
205
  - Pay out the seller (transfers + withdrawals are dashboard-only / closed API).
193
206
  - Make decisions about pricing or installments — caller's responsibility.
194
207
 
208
+ ## v0.5 — Webhook handler combo
209
+
210
+ Webhooks are how MP tells you a payment cleared, a subscription was authorized,
211
+ a QR was scanned. Without HMAC verification, anyone can POST to your webhook
212
+ URL and forge state changes. **Always verify.**
213
+
214
+ The `handle_webhook` tool consolidates the 3-step pattern (verify → parse →
215
+ fetch resource) into ONE call:
216
+
217
+ ```
218
+ result = handle_webhook(raw_body, signature_header, request_id_header, auto_fetch)
219
+ → { verified, event: { topic, dataId, action }, resource, resource_error }
220
+ ```
221
+
222
+ Behavior:
223
+ - `verified: false` + `error` → reject with HTTP 401, do NOT process. Either signature mismatch, missing webhookSecret, or invalid JSON body.
224
+ - `verified: true` + `resource: <Payment|Preapproval>` → safe to act on. The resource is fetched AS the MP user the client is configured for.
225
+ - `auto_fetch: false` → just verify+parse, skip the GET. Use when you only need to enqueue a job for async processing.
226
+
227
+ **Per-seller webhooks (marketplace)**: in a marketplace setup, instantiate
228
+ the `MercadoPagoClient` with the SELLER's access_token before calling
229
+ `handle_webhook` so the auto-fetch resolves correctly. Your routing layer
230
+ needs to look up the seller from the webhook payload's `user_id` and pick
231
+ the right client.
232
+
233
+ ## v0.5 — OAuth Marketplace flow
234
+
235
+ For marketplace platforms (Rappi, MercadoLibre, Tienda Nube, etc.) where
236
+ your app cobra a través de cuentas MP de terceros (sellers in your platform).
237
+
238
+ **3 legs**:
239
+ 1. `oauth_authorize_url` — pure function, no network. Returns a URL; redirect the seller there.
240
+ 2. `oauth_exchange_code` — server-side. Takes the `code` from the OAuth callback, returns `{ user_id, access_token, refresh_token, expires_in }`. **Persist all of it.**
241
+ 3. `oauth_refresh_token` — server-side. Use saved `refresh_token` to get a fresh `access_token` before/at expiration.
242
+
243
+ **Token storage shape** (per seller):
244
+ ```
245
+ {
246
+ user_id: string, // identifies the seller
247
+ access_token: string, // expires in ~6h
248
+ refresh_token: string, // long-lived, ROTATES on refresh
249
+ expires_at: number, // Date.now() + expires_in*1000
250
+ }
251
+ ```
252
+
253
+ **State for every API call**: instantiate `new MercadoPagoClient({ accessToken: token.access_token })` AS THE SELLER. All subsequent payments / subscriptions / refunds happen on that seller's account.
254
+
255
+ **Marketplace fee**: pass `marketplace_fee` (in ARS) + `collector_id: token.user_id` to `create_order` or `create_payment_preference`. Funds route to the seller, fee goes to your marketplace account.
256
+
257
+ ## v0.5 — Order Management vs Preference
258
+
259
+ | When | Use |
260
+ | --------------------------------------- | ------------------------- |
261
+ | Simple hosted pay-link (most common) | `create_payment_preference` |
262
+ | Auth-only flow (capture later) | `create_order` w/ `capture_mode: "manual"` |
263
+ | Multi-payment-per-order | `create_order` |
264
+ | Mix online + in-store with unified status | `create_order` |
265
+ | You need MP's modern Order lifecycle | `create_order` |
266
+
267
+ `create_order` returns an Order with explicit lifecycle:
268
+ - `created` → Order opened, no payment yet
269
+ - `processed` → at least one payment attached
270
+ - `action_required` → manual-capture mode, awaits `capture_order`
271
+ - `canceled` → `cancel_order` was called
272
+ - `refunded` → all payments refunded
273
+
195
274
  ## Mercado Pago context (for non-AR agents)
196
275
 
197
276
  - **Mercado Pago** = dominant Argentine consumer payment platform (also Brazil/Mexico/Chile/Colombia/Uruguay). Owned by Mercado Libre. Like Stripe in scope but with deeper LATAM-specific features (cuotas sin interés, in-store QR, account_money instant transfer).
package/CHANGELOG.md CHANGED
@@ -1,5 +1,110 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - MP v0.5: production hardening + marketplace flows. **+9 tools (50 total)**.
8
+
9
+ **Webhook handler combo (1 tool)**:
10
+
11
+ - `handle_webhook` — verifies HMAC-SHA256 signature, parses the event, and (optionally) auto-fetches the underlying resource (Payment, Subscription) in ONE call. Replaces the manual chain of verify_webhook_signature + parse_webhook_event + get_payment.
12
+ - `mercadoPagoTools({ webhookSecret })` to enable.
13
+ - Returns `{ verified, event, resource, resource_error }`. Reject with HTTP 401 when `verified: false`.
14
+
15
+ **OAuth Marketplace flow (3 tools + 5 helper functions)**:
16
+
17
+ - `oauth_authorize_url` — pure function, builds the URL the seller visits to authorize your marketplace app.
18
+ - `oauth_exchange_code` — server-side exchange of the OAuth code for an `OAuthToken` (`access_token` + `refresh_token` + `user_id` + `expires_in`).
19
+ - `oauth_refresh_token` — refresh a per-seller token before it expires (~6h).
20
+ - Helper functions exported: `buildAuthorizeUrl`, `exchangeCodeForToken`, `refreshAccessToken`, `expirationTimeMs`, `isExpiringSoon`.
21
+ - `mercadoPagoTools({ oauth: { clientId, clientSecret } })` to enable.
22
+
23
+ **Order Management API (5 tools)**:
24
+
25
+ - `create_order`, `get_order`, `update_order`, `capture_order`, `cancel_order` — MP's modern Order API. Distinct from Preference: explicit lifecycle, manual-capture support (auth-only flows for ride-share, hotels, marketplaces), multi-payment-per-order semantics.
26
+ - `capture_mode: "manual"` enables the auth-only flow → `capture_order(id, amount?)` later.
27
+
28
+ **Marketplace split payments**:
29
+
30
+ - `marketplace`, `marketplace_fee` (in ARS), `collector_id` (seller MP user_id) supported on BOTH `create_order` AND `create_payment_preference`.
31
+ - Funds route to the seller; `marketplace_fee` is split off to the marketplace's MP account.
32
+
33
+ 117 tests pass. publint clean. attw all green. 21.6 KB brotli'd (within 32 KB budget).
34
+
35
+ The MCP wrapper auto-picks up the new tools — `@ar-agents/mcp` patch bump.
36
+
37
+ ## 0.4.0
38
+
39
+ ### Minor Changes
40
+
41
+ - v0.4.0 — full toolkit: Subscription Plans + Stores/POS + Disputes + Subscription Payment History + Lookup helpers + Webhooks management
42
+
43
+ **41 tools total** (was 24 in v0.3). Adds 17 new tools covering the rest of the agent-relevant MP API surface.
44
+
45
+ # New: Subscription Plans (5 tools)
46
+
47
+ For SaaS-style billing where you have fixed tiers (Básico/Pro/Enterprise), use plans instead of per-customer preapprovals.
48
+
49
+ - `create_subscription_plan` — define reusable plan (price + frequency + optional free trial)
50
+ - `list_subscription_plans` — list all plans
51
+ - `update_subscription_plan` — change reason / amount / status / back_url (existing subs keep old amount)
52
+ - `subscribe_to_plan` — enroll a customer in a plan; returns init_point URL
53
+ - `list_subscription_payments` — auto-charge attempts (authorized_payments) under a preapproval. Useful for "show me cobros del último mes for this client" or to debug failing recurring charges.
54
+
55
+ # New: Stores + POS management (4 tools)
56
+
57
+ Self-serve setup for in-store QR payments. Eliminates the previous one-time MP dashboard step.
58
+
59
+ - `create_store` — create a store under the seller
60
+ - `list_stores` — list configured stores
61
+ - `create_pos` — create a POS under a store (the `external_id` is what `create_qr_payment` uses)
62
+ - `list_pos` — list POSes (optionally filtered by store_id)
63
+
64
+ # New: Disputes / Chargebacks (2 tools, read-only)
65
+
66
+ - `list_payment_disputes` — list disputes raised against a payment (surfaces `dashboard_url`)
67
+ - `get_dispute` — full dispute details (reason, amount, resolution status)
68
+
69
+ Resolution remains dashboard-only; the lib surfaces the right URL.
70
+
71
+ # New: Lookup helpers (2 tools)
72
+
73
+ - `list_identification_types` — AR returns DNI/CI/LE/LC/Otro/Pasaporte/CUIT/CUIL with min/max length
74
+ - `list_issuers` — banks issuing a card type. Pass `bin` (first 6-8 digits) for precise issuer detection — needed for issuer-specific cuotas promos like Naranja Galicia 6 cuotas sin interés
75
+
76
+ # New: Webhooks management (4 tools)
77
+
78
+ Programmatically configure webhook subscriptions instead of clicking around the MP dashboard.
79
+
80
+ - `list_webhooks` — see what's configured
81
+ - `create_webhook` — subscribe a URL to a topic (`payment`, `subscription_authorized_payment`, `merchant_order`, `point_integration_wh`, etc.)
82
+ - `update_webhook` — change URL or topic
83
+ - `delete_webhook` — unsubscribe
84
+
85
+ # Quality
86
+
87
+ - 81/81 tests pass (was 61 in v0.3) — added 20 tests for v0.4 endpoints
88
+ - 21.72 KB ESM brotli'd (under 32 KB budget)
89
+ - publint + arethetypeswrong all 🟢
90
+ - Type-safe end-to-end; new types: SubscriptionPlan, Store, Pos, Dispute, IdentificationType, Issuer, WebhookConfig, SubscriptionPayment
91
+
92
+ # Cumulative tool inventory (41 total)
93
+
94
+ - Subscriptions: 5 (create, get, cancel, pause, resume)
95
+ - Subscription Plans: 5 (create, list, update, subscribe, list_payments)
96
+ - Payments: 5 (create, get, search, cancel, capture)
97
+ - Refunds: 2 (create, list)
98
+ - Checkout Pro: 2 (create_preference, get_preference)
99
+ - Customers + Cards: 4 (create, find, list_cards, delete_card)
100
+ - Saved-card charging: 1 (charge_saved_card)
101
+ - Methods + Installments: 2 (list_methods, calculate_installments)
102
+ - Account: 1 (get_account_info)
103
+ - QR + POS: 6 (create_qr, cancel_qr, create_store, list_stores, create_pos, list_pos)
104
+ - Disputes: 2 (list, get)
105
+ - Lookup: 2 (identification_types, issuers)
106
+ - Webhooks: 4 (list, create, update, delete)
107
+
3
108
  ## 0.3.0
4
109
 
5
110
  ### Minor Changes
package/README.md CHANGED
@@ -18,7 +18,7 @@ Compatible with any caller that uses `tool()`.
18
18
 
19
19
  | What | Value |
20
20
  | --- | --- |
21
- | Tools shipped | `create_subscription`, `get_subscription_status`, `cancel_subscription`, `pause_subscription`, `resume_subscription` |
21
+ | Tools shipped | **50 tools** Subscriptions, Payments, Refunds, Checkout Pro, Customers, Saved Cards, Cuotas, QR in-store, Subscription Plans, Stores+POS, Disputes, Lookups, Webhooks management, **handle_webhook combo**, **OAuth Marketplace flow**, **Order Management API** |
22
22
  | External dependencies | Mercado Pago access token (TEST or APP_USR), state adapter (Upstash, Redis, Postgres, in-memory, etc.) |
23
23
  | Latency | 200–600ms per MP call; <1ms for state ops |
24
24
  | Cost | $0 — MP API is free; merchant pays per-transaction fees on auto-charges |
@@ -264,15 +264,20 @@ Methods:
264
264
 
265
265
  ### `mercadoPagoTools(client, options)`
266
266
 
267
- Returns a `ToolSet` (the Vercel AI SDK type) with five entries:
268
-
269
- | Tool name | What it does |
270
- | ------------------------- | ----------------------------------------------------------------- |
271
- | `create_subscription` | Create a new subscription, return `init_point_url` for the buyer |
272
- | `get_subscription_status` | Read the latest status from MP, merged with cached webhook info |
273
- | `cancel_subscription` | Cancel the subscription (triggers safety guardrail, see #9) |
274
- | `pause_subscription` | Pause an authorized subscription |
275
- | `resume_subscription` | Resume a paused subscription |
267
+ Returns a `ToolSet` with **50 tools** spanning the full MP API surface an
268
+ agent typically needs. See [AGENTS.md](./AGENTS.md) for the full list with
269
+ selection guidance. Highlights:
270
+
271
+ - **Subscriptions + Plans** (10 tools): create_subscription, create_subscription_plan, subscribe_to_plan, list_subscription_payments, pause/resume/cancel
272
+ - **Payments + Refunds** (7 tools): create_payment, search_payments, capture_payment, refund_payment, list_refunds…
273
+ - **Checkout Pro** (2 tools): create_payment_preference, get_payment_preference
274
+ - **Customers + Saved Cards** (4 tools): create_customer, find_customer_by_email, list_customer_cards, charge_saved_card (CVV-required)
275
+ - **In-store QR + POS** (4 tools): create_qr_payment, cancel_qr_payment, create_store, create_pos
276
+ - **Cuotas + lookups** (3 tools): calculate_installments, list_payment_methods, list_issuers
277
+ - **Disputes + Webhooks management** (6 tools): list_payment_disputes, create_webhook, list_webhooks…
278
+ - **v0.5 — Webhook handler combo** (1 tool): `handle_webhook` — verify HMAC + parse + auto-fetch in ONE call
279
+ - **v0.5 — OAuth Marketplace** (3 tools): `oauth_authorize_url`, `oauth_exchange_code`, `oauth_refresh_token` — wire third-party MP accounts to your platform
280
+ - **v0.5 — Order Management API** (5 tools): `create_order`, `get_order`, `update_order`, `capture_order`, `cancel_order` — modern API with auth-only support and marketplace splits
276
281
 
277
282
  Options:
278
283
 
@@ -281,9 +286,68 @@ mercadoPagoTools(client, {
281
286
  state: SubscriptionStateAdapter; // required
282
287
  backUrl: string; // required, must be HTTPS
283
288
  descriptions?: Partial<Record<ToolName, string>>; // optional override
289
+ webhookSecret?: string; // for handle_webhook (HMAC verify)
290
+ oauth?: { clientId, clientSecret }; // for OAuth marketplace flow
284
291
  });
285
292
  ```
286
293
 
294
+ ### v0.5 — Webhook handler combo
295
+
296
+ ```ts
297
+ // In your /api/mercadopago/webhook handler
298
+ const result = await tools.handle_webhook.execute({
299
+ raw_body: await req.text(),
300
+ signature_header: req.headers.get("x-signature"),
301
+ request_id_header: req.headers.get("x-request-id"),
302
+ auto_fetch: true, // also fetches the Payment / Subscription
303
+ }, ctx);
304
+
305
+ if (!result.verified) return new Response("unauthorized", { status: 401 });
306
+ // Use result.event.topic, result.event.dataId, result.resource (Payment | Preapproval | …)
307
+ ```
308
+
309
+ ### v0.5 — OAuth Marketplace flow (3 legs)
310
+
311
+ ```ts
312
+ // 1. Build authorize URL — redirect the seller here
313
+ const { url } = await tools.oauth_authorize_url.execute({
314
+ redirect_uri: "https://app.test/oauth/callback",
315
+ state: cryptoRandomToken(), // bind to user's session, verify on redirect
316
+ }, ctx);
317
+
318
+ // 2. On redirect, exchange the code (server-side, secret required)
319
+ const { token } = await tools.oauth_exchange_code.execute({
320
+ code: req.query.code,
321
+ redirect_uri: "https://app.test/oauth/callback",
322
+ }, ctx);
323
+ // Persist { token.user_id, token.access_token, token.refresh_token, token.expires_in }
324
+
325
+ // 3. Refresh proactively (or reactively on 401)
326
+ const { token } = await tools.oauth_refresh_token.execute({
327
+ refresh_token: savedRefreshToken,
328
+ }, ctx);
329
+
330
+ // Then operate AS the seller:
331
+ const sellerClient = new MercadoPagoClient({ accessToken: token.access_token });
332
+ ```
333
+
334
+ ### v0.5 — Marketplace split payments
335
+
336
+ For two-sided platforms (Rappi-style) where you collect on a seller's behalf
337
+ and take a fee, pass `marketplace`, `marketplace_fee`, `collector_id` to
338
+ `create_order` (or `create_payment_preference`). Funds route to the seller's
339
+ MP account; `marketplace_fee` (in ARS) goes to your marketplace account.
340
+
341
+ ```ts
342
+ await tools.create_order.execute({
343
+ type: "online",
344
+ total_amount: 10_000,
345
+ marketplace: "MyApp",
346
+ marketplace_fee: 500, // ARS (NOT %)
347
+ collector_id: token.user_id, // seller MP user_id from OAuth
348
+ }, ctx);
349
+ ```
350
+
287
351
  ### Errors
288
352
 
289
353
  All errors extend `MercadoPagoError` which carries `status`, `endpoint`,