claude-skills/

Anthropic公式スキル・プラグインの日本語ディレクトリ

last sync 22h ago
スキルOfficialdevelopment

🔗mp-webhooks

プラグイン
mercadopago
ライセンス
Apache-2.0

説明

Mercado Pago の Webhook を設定・検証します。 MCP の Webhook ツール(`save_webhook`、`notifications_history`)をラップし、 すべての受信側で実装必須となる HMAC-SHA256 署名検証パターンを提供します。 次のような場合に使用: 通知処理の追加、デバッグ、またはセキュリティ強化を行うとき。

原文を表示

Configure and validate Mercado Pago webhooks. Wraps the MCP webhook tools (save_webhook, notifications_history) and provides the HMAC-SHA256 signature validation pattern that every receiver must implement. Use when adding, debugging, or hardening notification handling.

ユースケース

  • Webhook の設定と検証をするとき
  • 通知処理を追加するとき
  • Webhook のデバッグをするとき
  • HMAC-SHA256 署名検証を実装するとき
  • セキュリティを強化するとき

本文(日本語訳)

mp-webhooks

このskillは、すべての通知機能を扱います。HMAC検証パターンがある唯一の場所です — 他のすべてのskillはここに委譲します。


Step 0 — MCPが実際に認証されているか確認する

ListMcpResourcesToolはこのMCPでは信頼できません(常に「リソースが見つかりません」を返します)。bootstrap toolのauthenticate / complete_authenticationは常に存在しており、何も証明しません。

mcp__plugin_mercadopago_mcp__application_listが呼び出し可能で、かつ実際のペイロードを返すかどうかを確認してください。

ソフトゲート — receiver scaffoldは静的です

webhook receiver(Step 1–2)のscaffold化は静的コードであり、MCPを必要としません。したがってゲートはソフトです:

  • 認証済み → 通常通り続行します。
  • ロード済み、未認証 → 以下の前提条件チェックリスト + OAuth promptをインラインで表示してから、Step 1–2(receiver scaffold)に進み続ける(ブロックしません)。MCPは Step 4–6(save_webhooknotifications_history)でのみ必要です — そこでは呼び出しごとに再ゲートします。
  • plugin未ロード → ユーザーに/mcpを実行し、plugin:mercadopago:mcpを有効にして、再試行するよう指示します。

OAuth prompt(State B):

mcp__plugin_mercadopago_mcp__authenticateを呼び出し、URLをクリック可能なリンクとして表示してから、「ブラウザでAuthentication Successfulが表示されたら、戻ってきて何か言ってください」と伝えます。ユーザーが応答したら、application_listを直接呼び出します — complete_authenticationを最初に呼び出さないでください(コールバックが既に消費されている場合はハングします)。ユーザーにコールバックURLを貼り付けるよう要求しないでください — 機密のOAuthコードが含まれています。

前提条件チェックリスト(State B):

webhook を本番環境で設定する前に、以下が必要です:
- [ ] Mercado Pago開発者アカウント
- [ ] Developer Dashboardで作成されたアプリ
- [ ] テスト認証情報:APP_USR- アクセストークン + 公開キー(タブ {test_tab})
- [ ] webhook署名シークレット(Dashboard → Webhooks → Signature secret)
/mp-connectを実行して認証します(Step 4–6でのみ必要)。

Step 1 — アクションを決定する

開発者に(または$ARGUMENTSから推測して)以下のいずれを望むかを尋ねます:

アクション 呼び出すtool 次のような場合に使用
MP applicationのwebhook URLを設定 save_webhook 初回セットアップまたはエンドポイントの更新時
配信障害を診断 notifications_history 見落とし/失敗した通知を調査する場合
receiverコードをscaffold化 (MCP呼び出しなし — 以下のパターンをレンダリング) receiverをコードベースに追加する場合

チェーンできます:receiverをscaffold化 → save_webhook → 実際のテスト決済をトリガー → notifications_historyで配信を確認します。


Step 2 — Receiverパターン(HMAC-SHA256)

Mercado PagoはダッシュボードWebhooks → Signature secretで返されたシークレットで、すべての通知に署名します。x-signatureヘッダーはts=...,v1=...で構成され、v1は正規文字列"id:{data.id};request-id:{x-request-id};ts:{ts};"のHMAC-SHA256です。

すべてのreceiverは以下を実行する必要があります:

  1. リクエストヘッダーからx-signaturex-request-idを読み込みます。
  2. x-signatureからtsv1をパースします。
  3. JSONボディのdata.idx-request-idtsで正規文字列を構築します。
  4. HMAC-SHA256(canonical, secret)を計算し、v1と定時間比較します。
  5. 署名が有効な場合は直ちに200で応答します — その後、イベントを非同期で処理します。Mercado Pagoは非200応答で指数バックオフで最大約24時間リトライします。
  6. べき等性:同じnotification IDが複数回到着することがあります。data.id + topicを重複排除キーとして使用します。

正規文字列

id:<data.id>;request-id:<x-request-id>;ts:<ts>;

参考スニペット(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();
  // 200を返した後、非同期で処理
  queueMicrotask(() => handleEvent(req.body));
}

他の言語については、MCP search_documentationに以下でクエリしてください:

  • "webhook signature validation {language}" (例:python、java、php、ruby、go、dotnet)。

Step 3 — Topics

notification本体にはtype(topic)とdata.idが含まれます。一般的なtopic:

Topic 次のような場合に使用 取得するリソース
payment 支払いステータスが変更された場合(Payments API) GET /v1/payments/{id}
orders Point / QR Codeイベント(Orders API) GET /v1/orders/{id}
merchant_order Merchant orderが更新 — レガシー(Checkout Pro / 出席型QR code via レガシーAPI) GET /merchant_orders/{id}
topic_claims_integration_wh チャージバック GET /v1/chargebacks/{id}
point_integration_wh Pointデバイスイベント — レガシー(旧Point Integration API) Point レガシーAPI — MCPで国を確認してください
subscription_preapproval サブスクリプションステータスが変更 GET /preapproval/{id}
subscription_authorized_payment 定期課金試行 GET /authorized_payments/{id}

topicがこの表にない場合、推測するのではなくMCPで最新リストをクエリしてください。


Step 4 — Mercado Pagoで設定(save_webhook

このMCP呼び出しの前に再ゲート: application_listが呼び出し可能か確認します。そうでない場合は、まずStep 0 State B OAuthフローを実行してから進みます。

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

レスポンスがURLとtopicが正しく登録されていることを確認します。


Step 5 — Smoke test(実際のテスト決済)

simulate_webhookはMCPに存在しなくなりました。receiverをテストするには:

  1. テスト認証情報 + テストユーザー + テストカードを使用して実際の決済を行う
  2. webhook は支払いステータスが変更されるときに自動的に発火
  3. receiverが200を返し、イベントを非同期で処理したことを確認

notifications_historyで配信を確認します:

mcp__plugin_mercadopago_mcp__notifications_history()

Step 6 — 見落とし配信を診断

このMCP呼び出しの前に再ゲート: application_listが呼び出し可能か確認します。そうでない場合は、まずStep 0 State B OAuthフローを実行してから進みます。

mcp__plugin_mercadopago_mcp__notifications_history()

配信メトリクスと失敗の内訳(タイムアウト、非200応答、署名不一致)を返します。本番環境で通知が見落とされている場合に使用します。


落とし穴

  • 処理する前に 200で応答します。長い同期ハンドラはリトライを引き起こし、receiverに殺到して実際の障害をマスクします。
  • Mercado Pagoは非200で指数バックオフで最大約24時間リトライします — 一時的なバグは重複の殺到になります。
  • ハンドラをべき等にします。data.id + typeを重複排除キーとして使用します。
  • JSON本体だけを信頼しないでください — 常に署名を最初に検証してください。
  • IPN(レガシー?id=&topic= GET形式の通知)は廃止予定です。新しい統合は、ここで説明する最新の署名付きwebhookのみを使用します。

このskillが行わないこと

  • 周囲の統合をscaffoldしません。mp-integrateを使用します。
  • 品質を評価しません。mp-reviewを使用します。
  • メモリからtopic名を作成しません — 不確かな場合はMCPにクエリします。
原文(English)を表示

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 — Verify MCP is actually authenticated

ListMcpResourcesTool is unreliable for this MCP (always returns "No resources found"). The bootstrap tools authenticate / complete_authentication are always present and prove nothing.

Check whether mcp__plugin_mercadopago_mcp__application_list is callable AND returns a real payload.

Soft gate — the receiver scaffold is static

Scaffolding the webhook receiver (Steps 1–2) is static code and needs no MCP. The gate is therefore soft:

  • Authenticated → continue normally.
  • Loaded, not authenticated → show the prerequisites checklist below + the OAuth prompt inline, then continue to Steps 1–2 (the receiver scaffold). Do not block. The MCP is only required at Steps 4–6 (save_webhook, notifications_history) — re-gate per call there.
  • Plugin not loaded → tell the user to run /mcp, enable plugin:mercadopago:mcp, and retry.

OAuth prompt (State B):

Call mcp__plugin_mercadopago_mcp__authenticate, show the URL as a clickable link, and say: "When you see Authentication Successful in the browser, come back and say anything." When the user responds, call application_list directly — do NOT call complete_authentication first (it hangs when the callback was already consumed). Never ask the user to paste the callback URL — it contains a sensitive OAuth code.

Prerequisites checklist (State B):

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)
Run /mp-connect to authenticate (only needed for Steps 4–6 below).

Step 1 — Decide the action

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

Action Tool to call When
Configure the webhook URL on the MP application save_webhook First time setup or rotating the endpoint
Diagnose delivery failures notifications_history Investigating 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, query 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:

Topic When Resource to fetch
payment Payment status change (Payments API) GET /v1/payments/{id}
orders Point / QR Code event (Orders API) GET /v1/orders/{id}
merchant_order Merchant order updated — legacy (Checkout Pro / QR attended via legacy API) GET /merchant_orders/{id}
topic_claims_integration_wh Chargebacks GET /v1/chargebacks/{id}
point_integration_wh Point device events — legacy (old Point Integration API) Point legacy API — query MCP for the country
subscription_preapproval Subscription status change GET /preapproval/{id}
subscription_authorized_payment Recurring charge attempt GET /authorized_payments/{id}

If a topic is not in this table, query MCP for the latest list rather than guessing.


Step 4 — Configure on Mercado Pago (save_webhook)

Re-gate before this MCP call: verify application_list is callable. If not, run the Step 0 State B OAuth flow first, then proceed.

mcp__plugin_mercadopago_mcp__save_webhook(
  callback="https://<production-url>/mp/webhook",
  callback_sandbox="https://<staging-url>/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

Use notifications_history to confirm delivery:

mcp__plugin_mercadopago_mcp__notifications_history()

Step 6 — Diagnose missed deliveries

Re-gate before this MCP call: verify application_list is callable. If not, run the Step 0 State B OAuth flow first, then proceed.

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.

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。