@ar-agents/mercadopago 0.4.0 → 0.6.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
 
@@ -31,6 +31,11 @@ This file is for AI agents using or recommending this package. Humans should sta
31
31
  | **"Qué bancos emiten Visa?"** | `list_issuers(payment_method_id: "visa")` (pass `bin` for accurate match) |
32
32
  | **"Listame los tipos de identificación válidos en AR"** | `list_identification_types` (DNI/CUIT/CUIL/etc) |
33
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`. |
34
39
 
35
40
  ## The two main "take a payment" patterns
36
41
 
@@ -197,10 +202,75 @@ v0.2 ships `parseWebhookEvent()` for the `preapproval` topic (subscription lifec
197
202
  - Take raw card data in the agent runtime (PCI scope violation).
198
203
  - Bypass MP's first-payment-CVV requirement for subscriptions (impossible).
199
204
  - Reactivate a cancelled subscription or payment (MP doesn't allow).
200
- - Implement Marketplace splits (different MP product, different OAuth flow — out of scope until v0.4+).
201
205
  - Pay out the seller (transfers + withdrawals are dashboard-only / closed API).
202
206
  - Make decisions about pricing or installments — caller's responsibility.
203
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
+
204
274
  ## Mercado Pago context (for non-AR agents)
205
275
 
206
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,64 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - MP v0.6: account/balance + settlements + 3DS analyzer + test cards. **+6 tools (56 total)**.
8
+
9
+ **Account / Balance / Settlements (4 tools)**:
10
+
11
+ - `get_account_balance` — current MP wallet `{ available, unavailable, total, currency_id }`. Per-seller in marketplace setups.
12
+ - `list_account_movements({ from?, to?, limit?, offset? })` — wallet movement log (incoming payments, refunds, holdings, transfers).
13
+ - `list_settlements({ from?, to?, status? })` — `release_money` transfers from MP wallet → registered CBU.
14
+ - `get_settlement(id)` — single settlement detail with bank_account info.
15
+
16
+ **3DS analyzer (1 tool + 1 helper)**:
17
+
18
+ - `analyze_payment_3ds(payment_id)` — fetches the Payment, derives `{ status: 'not_required'|'frictionless'|'challenge_required'|'rejected'|'unknown', mode, challengeUrl, description }`. When `challengeUrl !== null`, MUST redirect the buyer to complete authentication.
19
+ - `analyze3DS(payment)` exported as a pure helper for callers who already have a Payment object.
20
+
21
+ **Test cards (1 tool + helpers)**:
22
+
23
+ - `get_test_cards` — returns the official AR (MLA) sandbox cards: VISA/Mastercard/Amex credit + debit. Each has the "magic" holder names that route to specific status_detail (APRO, OTHE, CONT, FUND, CALL, SECU, EXPI, FORM).
24
+ - `TEST_CARDS_AR`, `TEST_PAYERS_AR`, `buildTestCardScenario(card, scenario, amount)` exported for direct use in test files.
25
+
26
+ **132 tests pass** (was 117; +15 v0.6 tests). publint clean. attw 🟢. 24.3 KB brotli'd (within 32 KB budget).
27
+
28
+ ## 0.5.0
29
+
30
+ ### Minor Changes
31
+
32
+ - MP v0.5: production hardening + marketplace flows. **+9 tools (50 total)**.
33
+
34
+ **Webhook handler combo (1 tool)**:
35
+
36
+ - `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.
37
+ - `mercadoPagoTools({ webhookSecret })` to enable.
38
+ - Returns `{ verified, event, resource, resource_error }`. Reject with HTTP 401 when `verified: false`.
39
+
40
+ **OAuth Marketplace flow (3 tools + 5 helper functions)**:
41
+
42
+ - `oauth_authorize_url` — pure function, builds the URL the seller visits to authorize your marketplace app.
43
+ - `oauth_exchange_code` — server-side exchange of the OAuth code for an `OAuthToken` (`access_token` + `refresh_token` + `user_id` + `expires_in`).
44
+ - `oauth_refresh_token` — refresh a per-seller token before it expires (~6h).
45
+ - Helper functions exported: `buildAuthorizeUrl`, `exchangeCodeForToken`, `refreshAccessToken`, `expirationTimeMs`, `isExpiringSoon`.
46
+ - `mercadoPagoTools({ oauth: { clientId, clientSecret } })` to enable.
47
+
48
+ **Order Management API (5 tools)**:
49
+
50
+ - `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.
51
+ - `capture_mode: "manual"` enables the auth-only flow → `capture_order(id, amount?)` later.
52
+
53
+ **Marketplace split payments**:
54
+
55
+ - `marketplace`, `marketplace_fee` (in ARS), `collector_id` (seller MP user_id) supported on BOTH `create_order` AND `create_payment_preference`.
56
+ - Funds route to the seller; `marketplace_fee` is split off to the marketplace's MP account.
57
+
58
+ 117 tests pass. publint clean. attw all green. 21.6 KB brotli'd (within 32 KB budget).
59
+
60
+ The MCP wrapper auto-picks up the new tools — `@ar-agents/mcp` patch bump.
61
+
3
62
  ## 0.4.0
4
63
 
5
64
  ### 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`,