mcpField
M
mp-webhooks

mp-webhooks

github.com/mercadopagoDevelopment3262 installsUpdated 5w ago
Repository

About mp-webhooks

mp-webhooks is a developer skill for building and operating Mercado Pago webhook receivers. It centralizes HMAC-SHA256 signature validation guidance and separates offline scaffolding from MCP-backed configuration and diagnosis.

Key features

  1. 01HMAC-SHA256 signature validation
  2. 02Receiver scaffolding guidance
  3. 03Idempotent event handling
  4. 04Webhook registration and rotation
  5. 05Delivery history diagnosis

Use cases

  1. 01Add a signed webhook receiver
  2. 02Configure or rotate a callback URL
  3. 03Investigate missed notifications

MCP support

Uses Mercado Pago MCP tools on demand: `search_documentation` for signature guidance, `save_webhook` for callback registration, and `notifications_history` for delivery diagnosis.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/mercadopago/mercadopago-claude-marketplace --skill mp-webhooks

After installing, type/mp-webhooksin Claude Code to confirm it loaded.

Details

From the project README

mp-webhooks

This skill is for everything notifications. It is the only place where the HMAC validation pattern lives — every other skill defers here.


Step 0 — Connect only for an MCP-backed action

Do not inspect MCP state when this skill starts. Scaffolding and reviewing the receiver pattern are static operations and require no MCP connection.

Connect only immediately before one of these selected operations:

OperationRequired MCP tool
Fetch a language-specific signature examplesearch_documentation
Resolve an unknown or country-specific topicsearch_documentation
Register or rotate the callback URLsave_webhook
Confirm or diagnose webhook deliverynotifications_history

On-demand authentication procedure:

  1. Attempt the intended tool directly if callable. Do not call application_list as a connection probe.
  2. If it is unavailable or returns an authentication error, call mcp__plugin_mercadopago_mcp__authenticate.
  3. Show the clickable OAuth link in the developer's language and instruct them to Cmd+Click (Mac) or Ctrl+Click (Windows/Linux), without copying the URL into an external browser.
  4. When the developer returns, retry the intended tool directly. Never ask them to paste a callback URL.
  5. If MCP tools are not loaded, explain how to enable plugin:mercadopago:mcp. Keep any static scaffold/review work available offline.

Show this prerequisites checklist only when the developer selects an MCP-backed action:

Before configuring webhooks live, you'll need:
- [ ] A Mercado Pago developer account
- [ ] An app created in the Developer Dashboard
- [ ] Test credentials: APP_USR- access token + public key (tab {test_tab})
- [ ] The webhook signature secret (Dashboard → Webhooks → Signature secret)
Connection will be requested immediately before the selected MCP operation.

Step 1 — Decide the action

Ask the developer (or infer from $ARGUMENTS) which of these they want:

ActionTool to callWhen
Configure the webhook URL on the MP applicationsave_webhookFirst time setup or rotating the endpoint
Diagnose delivery failuresnotifications_historyInvestigating missed/failed notifications
Scaffold the receiver code(no MCP call — render the pattern below)Adding the receiver to the codebase

You may chain them: scaffold the receiver → save_webhook → trigger a real test payment → use notifications_history to confirm delivery.


Step 2 — Receiver pattern (HMAC-SHA256)

Mercado Pago signs every notification with the secret returned in the dashboard at Webhooks → Signature secret. The x-signature header is composed of ts=...,v1=... where v1 is the HMAC-SHA256 of the canonical string "id:{data.id};request-id:{x-request-id};ts:{ts};".

Every receiver MUST:

  1. Read x-signature and x-request-id from the request headers.
  2. Parse ts and v1 out of x-signature.
  3. Build the canonical string with data.id (from the JSON body) and x-request-id and ts.
  4. Compute HMAC-SHA256(canonical, secret) and compare in constant time with v1.
  5. Respond 200 immediately if the signature is valid — process the event asynchronously afterwards. Mercado Pago retries on non-200 responses with exponential backoff for up to ~24 hours.
  6. Be idempotent: the same notification id may arrive more than once. Use data.id + topic as the dedup key.
Canonical string
id:<data.id>;request-id:<x-request-id>;ts:<ts>;
Reference snippet (Node.js, Express)
import crypto from "node:crypto";

const SECRET = process.env.MP_WEBHOOK_SECRET;

export function mpWebhook(req, res) {
  const signature = req.header("x-signature") ?? "";
  const requestId = req.header("x-request-id") ?? "";
  const parts = Object.fromEntries(
    signature.split(",").map((p) => p.split("=").map((s) => s.trim()))
  );
  const ts = parts.ts;
  const v1 = parts.v1;
  const dataId = req.body?.data?.id;
  if (!ts || !v1 || !dataId || !requestId) return res.status(400).end();

  const canonical = `id:${dataId};request-id:${requestId};ts:${ts};`;
  const expected = crypto.createHmac("sha256", SECRET).update(canonical).digest("hex");

  const ok = expected.length === v1.length &&
             crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
  if (!ok) return res.status(401).end();

  res.status(200).end();
  // process asynchronously after responding 200
  queueMicrotask(() => handleEvent(req.body));
}

For other languages, apply Step 0 immediately before querying MCP search_documentation with:

  • "webhook signature validation {language}" (e.g., python, java, php, ruby, go, dotnet).

Step 3 — Topics

The notification body contains type (the topic) and data.id. Common topics:

TopicWhenResource to fetch
paymentPayment status change (Payments API)GET /v1/payments/{id}
ordersPoint / QR Code event (Orders API)GET /v1/orders/{id}
merchant_orderMerchant order updated — legacy (Checkout Pro / QR attended via legacy API)GET /merchant_orders/{id}
topic_claims_integration_whChargebacksGET /v1/chargebacks/{id}
point_integration_whPoint device events — legacy (old Point Integration API)Point legacy API — query MCP for the country
subscription_preapprovalSubscription status changeGET /preapproval/{id}
subscription_authorized_paymentRecurring charge attemptGET /authorized_payments/{id}

If a topic is not in this table, apply Step 0 immediately before querying MCP for the latest list rather than guessing.


Step 4 — Configure on Mercado Pago (save_webhook)

Connect on demand: apply Step 0 immediately before save_webhook. Do not call application_list first.

mcp__plugin_mercadopago_mcp__save_webhook(
  callback="https://<production-url>/mp/webhook",
  callback_url="https://<your-domain>/mp/webhook",
  topics=["payment", "merchant_order", ...]
)

Confirm the response shows the URL and topics correctly registered.


Step 5 — Smoke test (real test payment)

simulate_webhook no longer exists in the MCP. To test your receiver:

  1. Make a real payment using test credentials + test user + test card
  2. The webhook fires automatically when the payment status changes
  3. Verify your receiver returned 200 and processed the event idempotently

Apply Step 0 immediately before using notifications_history to confirm delivery:

mcp__plugin_mercadopago_mcp__notifications_history()

Step 6 — Diagnose missed deliveries

Connect on demand: apply Step 0 immediately before notifications_history. Do not call application_list first.

mcp__plugin_mercadopago_mcp__notifications_history()

Returns delivery metrics and a breakdown of failures (timeouts, non-200 responses, signature mismatches). Use this when notifications are missing in production.


Gotchas

  • Respond 200 before processing. A long synchronous handler causes retries that flood the receiver and can mask the real failure.
  • Mercado Pago retries on non-200 with exponential backoff up to ~24h — a transient bug becomes a flood of duplicates.
  • Make handlers idempotent. Use data.id + type as the dedup key.
  • Never trust the JSON body alone — always validate the signature first.
  • IPN (the legacy ?id=&topic= GET-style notification) is deprecated. New integrations use only the modern signed webhook described here.

What this skill does NOT do

  • It does not scaffold the surrounding integration. Use mp-integrate.
  • It does not evaluate quality. Use mp-review.
  • It does not invent topic names from memory — query MCP if unsure.

Comments

Markdown supported