「2つの lookup_key ごとに checkout.session.completed を1発ずつ、計2回トリガーしたい」。ローカルには .dev.vars も sk_test_ もなく、stripe CLI を素直に叩ける状態ではない。手元は Claude Code on the web のセッション1つだけ。Stripe MCP でどこまで行けるか試した記録です。
結論を先に書くと、Stripe MCP の stripe api write 経由で Checkout Session を直接作成し、Claude Code on the web にプリインストールされている Chromium を Playwright から呼んで test カード 4242... で完了させる、という形に着地しました。webhook イベントは2発とも発火しました。
やりたかったこと
テスト対象のハンドラ(recordCheckoutSession)が、本物の Checkout Session に対して listLineItems を呼び、price.lookup_key で種別を判定する作りになっています。つまり「その price/lookup_key を含む実際の Checkout Session が完了している」状態を作らないと、ハンドラの分岐をテストできません。
対象の lookup_key は2つでした。
ticket_normal(本編のみ)ticket_with_afterparty(懇親会込み)
この2つの lookup_key ごとに、それぞれ Checkout Session を1回完了させて、checkout.session.completed webhook を Stripe 側で発火させる。これをやらせたい。
最初に Claude Code に投げたプロンプトはこれです。

前提: Stripe MCP がつながっている
Stripe MCP は Claude のコネクタ画面からつなぎます。読み取り専用ツール8個と書き込み系ツールに分かれていて、書き込み系を有効にしておかないと今回の用途では話が始まりません。

Claude Code on the web から Stripe MCP が見えている状態で、まず search stripe resources で対象の price を引きにいきました。

クエリは prices:lookup_key:"ticket_normal" OR lookup_key:"ticket_with_afterparty"。ヒットした2件はどちらも recurring(subscription モード用)の price でした。unit_amount はそれぞれ 0 jpy と 2000 jpy。ここまでは MCP の読み取り系だけで終わります。
最初にぶつかった壁: 「webhook を直接発火させるツール」が無い
Claude Code が price を確認した直後に、こういう見立てを返してきました。

要点はこの2つです。
- Stripe MCP には
stripe trigger相当の「webhook イベントを直接発火させるツール」が無い - Stripe API にも「Checkout Session を API で完了させる」エンドポイントは存在しない(完了はホスト型決済ページ経由のみ)
つまり、ハンドラに正しい形の checkout.session.completed を届けたければ、本物の Checkout Session を本物の決済ページで完了させるしか道がない。Claude Code on the web 側からはホスト型決済ページの「完了」をどう起こすかが論点になります。
Claude Code が提示した3つの選択肢
このタイミングで Claude Code 側から、完了方法を3つに整理して聞いてきました。

- URL作成→自分で完了 (推奨): MCP で各 price の Checkout URL を2本作成。自分がブラウザで開いてテストカード
4242...で完了させる - Stripe CLI で trigger: Stripe CLI を入れて、対象 price を参照するカスタム fixture を書いて
stripe trigger checkout.session.completedを2回実行 - ヘッドレスブラウザで自動完了: Playwright でホスト型決済ページをテストカードで自動操作して完了
1番が推奨で、3番は「Stripe 側 UI 変更に弱く不安定」と但し書きが付いていました。「人間が手を動かすのが一番確実」というのは技術的にはその通りだけど、それを Claude Code 越しにわざわざ頼んだ意味が薄くなるので、ハンズオフでいけそうな道を先に潰したい。
Stripe CLI 案がここで落ちる


2番(Stripe CLI)は .dev.vars も環境変数の sk_test_ も無い状態で、 CLI の stripe trigger は内部で API を叩くので API キー認証が必須、ここで詰みました。シークレットを後乗せして CLI を入れて fixture を書く一連の手数より、ホスト型決済ページを自動で叩く方が手数が少ないので、3番に倒します。
このとき自分の返信が「mcp ならいけるでしょ」だったのですが、Claude Code 側がすかさず「これはブラウザ MCP ではなく、Playwright でホスト型決済ページを test カードで自動操作する形です(利用可能なブラウザ MCP は無いため)」と補足してきました。これは正しい補足で、Claude Code on the web のコネクタにブラウザ系の MCP は今のところ繋がっていません。実体は bash で Playwright を動かす形です。
Stripe MCP で Checkout Session を直接作成する
Stripe MCP の専用ツールには「Checkout Session を作る」名前のツールは公開されていません。代わりに stripe api write という汎用ツールがあって、stripe_api_operation_id に PostCheckoutSessions を指定すると Checkout Session を作れます。Payment Link 経由でも同じ目的は達成できますが、Payment Link は再利用前提のリソースで「使い捨ての webhook テスト用URL」としては少し重いので、Checkout Session 直行のほうがテストデータが汚れにくい。
![Claude が stripe api write の使用許可を求めるダイアログ。stripe_api_operation_id は PostCheckoutSessions、parameters には line_items[0][price] に ticket_normal の price ID、mode に subscription、metadata[test_purpose] に webhook_test_ticket_normal、success_url と cancel_url が指定されている](https://wp-api.wp-kyoto.net/wp-content/uploads/2026/06/244c8f8cf4605f37ecb24e92ea57d5b0-20260606083142.png)
パラメータはこういう形でした。
{
"parameters": {
"cancel_url": "https://example.com/cancel",
"line_items[0][price]": "price_1Tf6wXGn9dCp0nhQGa4EVUQb",
"line_items[0][quantity]": 1,
"metadata[test_purpose]": "webhook_test_ticket_normal",
"mode": "subscription",
"success_url": "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"
},
"stripe_api_operation_id": "PostCheckoutSessions"
}
対象 price が recurring なので mode は subscription。後で発火確認したいので metadata[test_purpose] に識別子を入れています。同じ要領で ticket_with_afterparty の price でもう1本作って、Checkout URL が2本そろいました。
Claude Code on the web で Playwright を動かすときの落とし穴
ここからが今回いちばん「あれっ」となったところです。Claude Code が Playwright で Chromium を入れにいくと、こうなりました。

順にこういう状態でした。
npx playwright install chromium相当がcdn.playwright.devブロックで失敗- apt 経由のインストールも失敗
- snap はそもそも snapd が無いコンテナなので不可
/opt/pw-browsersに Chromium (build 1194) がプリインストールされていたので、そっちを使うルートに切り替え
これは Claude Code on the web の egress プロキシの allowlist の問題で、Playwright のバイナリ配信ホストが許可リストに入っていないために起きます。公式リポジトリの issue #15583 にも同件が「Blocked」ステータスで挙がっていて、現状はインフラ側の allowlist 更新待ちです。Claude.ai の通常チャットでは起きない、Claude Code on the web 固有の制約です。
救いは /opt/pw-browsers に Chromium が同梱されていたこと。Claude Code は自力でこれを見つけてフォールバックしました。同じ環境で Playwright を使いたい人は、npx playwright install を信用せず /opt/pw-browsers 配下を最初に ls したほうが早いと思います。
その後、TLS 傍受プロキシの CA に引っかかって証明書エラーが出たので、Playwright 側で証明書エラーを無視して再実行(--ignore-https-errors 相当)。ホスト型決済ページの DOM 構造を1本目で偵察したところ、フォームは iframe を挟まないネイティブの <input> 群(email / card / expiry / cvc / name / country / ZIP / phone)で構成されていて、Playwright から直接埋められる形でした。まず ¥2000(ticket_with_afterparty)で実行し、続けて ¥0(ticket_normal)で実行。
発火の裏取り: MCP は event 一覧を返さない

決済ページ自体は両方 cs_test_ の完了画面まで到達しました。次にやることは「本当に checkout.session.completed webhook が Stripe 側で発火しているか」の確認で、ここで MCP の制約がもう一段見えました。
- Stripe MCP には Event 一覧の読み取りツールが無い
- Checkout Session の単体読み取りも公開されていない
つまり、ハンドラ側のログを見れば確実だけど、MCP 内に閉じて「発火した」を確定させるには間接ルートが必要になります。今回 Claude Code が取ったのは Subscription 経由の裏取りでした。mode: subscription で Checkout を完了させると、副作用として Subscription が新規生成されます。ここを fetch stripe resources で取りにいって、対象 price (ticket_normal / ticket_with_afterparty)を持つ Subscription が2本できていれば、対応する Checkout Session が完了していたことになります。
2本とも確認できて、決済完了画面のスクショも揃って、checkout.session.completed を2発、Stripe 側で発火させるという当初の目的にたどり着きました。
所感
Stripe MCP は「Stripe API のラッパー集」ではあるけど、テスト時に欲しい配管(trigger や Event 一覧、Checkout Session の単体読み取り)が一部欠けているので、webhook の発火テストを MCP 単体で完結させるのは現状むずかしい、というのが今回の結論です。
ただ Claude Code on the web 側に Playwright と Chromium が同梱されているおかげで、Stripe MCP で Checkout Session を作って Playwright で完了させる、という二段構えで「コンソールを触らずに本物の webhook を発火させる」ところまでは持っていけました。Stripe CLI を後乗せして fixture を書くより、手数も短い。cdn.playwright.dev のブロックは事前情報なしだとそこそこ時間を吸われるので、これから Claude Code on the web で Playwright を回す人は /opt/pw-browsers を先に確認する、というのを覚えて帰っていただけると元が取れます。