Stripe Agent ToolkitでMCPサーバーを収益化するサンプルを試す

Stripe Agent ToolkitでMCPサーバーを収益化するサンプルを試す

Clock Icon2025.05.04

はじめに

Stripe Agent ToolkitをModel Context Protocol(MCP)を経由で呼び出して、MCPサーバーを収益化するデモをStripeの社員の方が紹介していました。

https://x.com/jeff_weinstein/status/1918029261430255626

利用しているSDKはこちらで、MCP呼び出し時に商品の契約状態をチェックして実現しているようです。

https://github.com/stripe/agent-toolkit

先日ClaudeのWeb版からMCPが接続できるようになったので、ビジネス活用シーンが増えると考えており、面白いと感じたので試してみることにしました。
https://dev.classmethod.jp/articles/shuntaka-claude-web-model-context-protocol-mcp/

デモ動画があります。今回はこの中で示されている内容の一部について説明します。

https://www.youtube.com/live/njBGqr-BU54?t=3360s

概要

今回はStripe Agent Toolkitのexampleを使って、Claude(web)からMCP経由でツールがサブスク未契約状態で使えないが、契約後使えるようになるという機能を試します。

https://github.com/stripe/agent-toolkit/tree/main/typescript/examples/cloudflare

試す機能は、単にサブスクリプション契約状態によってツールの実行を制御するというシンプルなものです。

AgentのSDKはexampleをみる限り、ai-sdk cloudflare langchain openai で利用できそうです。今回は cloudflare を利用します。
https://github.com/stripe/agent-toolkit/tree/main/typescript/examples

Cloudflare Workersを利用してMCPサーバーを構築します。リモートMCP実装文脈でCloudflareが使われることが多いと思います。理由は以下があります。

  • MCPの認証、認可仕様cloudflare/workers-oauth-providerというOAuth 2.1 Provider Frameworkを利用することで簡単に構築可能
    • 前項に関連して、認証フローの途中で永続化が必要な箇所があり、Cloudflare Workers KVが隠蔽してくれる
  • MCPで利用されるSSE実装もcloudflare/agentsで簡単に構築が可能
  • WebアプリケーションのサーバーFWであるHonoとの親和性がある

今回のサンプルもcloudflare/workers-oauth-providerを使った認証フローを使っています。

試してみる

ソースコードの準備

git clone https://github.com/stripe/agent-toolkit.git
cd typescript

このディレクトリがpnpmのルートになっているのでモジュールインストールします。

pnpm install

こちらのサンプルに移動します

cd typescript/examples/cloudflare/

StripeのAPIキーの準備

以下のURLからAPIキーを発行します。sk_test_から始まるものを控えます。

https://dashboard.stripe.com/test/apikeys

.envをの設定を行います。

cp .dev.vars.example .dev.vars

控えたAPIキーを設定します。

.dev.vars
STRIPE_SECRET_KEY=sk_test_......

KVの作成とコンフィグ設定

KVを作成します。

$ wrangler kv namespace create "OAUTH_KV"

 ⛅️ wrangler 4.14.1
-------------------

Resource location: remote
🌀 Creating namespace with title "OAUTH_KV"
✨ Success!
Add the following to your configuration file in your kv_namespaces array:
{
  "kv_namespaces": [
    {
      "binding": "OAUTH_KV",
      "id": "c440..." # <- メモ
    }
  ]
}

コンフィグにKV設定をします

wrangler.jsonc
   "kv_namespaces": [
     {
       "binding": "OAUTH_KV",
-      "id": "<ADD YOUR KV NAMESPACEID HERE>",
+      "id": "c440...", // <- 設定
     },
   ],
   "observability": {

ローカルで動作確認

wranglerを使って、cloudflare workerをエミュレートします。ローカルではkvはシミュが使われるみたいです。

$ pnpm dev

> remote-mcp-server@0.0.0 dev /Users/shuntaka/repos/github.com/stripe/agent-toolkit/typescript/examples/cloudflare
> wrangler dev

 ⛅️ wrangler 4.13.2 (update available 4.14.1)
-------------------------------------------------------

Using vars defined in .dev.vars
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Durable Objects:
  - MCP_OBJECT: MyMCP
- KV Namespaces:
  - OAUTH_KV: c440... [simulated locally]
- Vars:
  - STRIPE_SECRET_KEY: "(hidden)"
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:4242
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│  [b] open a browser, [d] open devtools, [l] turn off local mode, [c] clear console, [x] to exit  │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯

modelcontextprotocolのdebugerを使います。

$ npx @modelcontextprotocol/inspector@latest http://localhost:4242/sse
Starting MCP inspector...
⚙️ Proxy server listening on port 6277
🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀

CleanShot 2025-05-04 at 13.29.13@2x

CleanShot 2025-05-04 at 13.30.16@2x

Connectを押下するとMCPサーバーの以下のURLリダイレクトされます。redirect_uriの通り、inspectorにリダイレクトされます。

http://localhost:4242/authorize?
response_type=code&
client_id=Y...&
code_challenge=J...&
code_challenge_method=S256&
redirect_uri=http%3A%2F%2F127.0.0.1%3A6274%2Foauth%2Fcallback

CleanShot 2025-05-04 at 13.30.28@2x

emailを設定し、Approveを押下します。

CleanShot 2025-05-04 at 13.31.07@2x

Connectedになっていることが確認できました。
CleanShot 2025-05-04 at 13.35.38@2x

List Toolsを押下します。各種ツールを試すことができます。
CleanShot 2025-05-04 at 13.36.55@2x

これらの操作した際のログを置いておきます。気になる方は参考にしてください。

操作中のwranglerのログ
$ pnpm dev

> remote-mcp-server@0.0.0 dev /Users/shuntaka/repos/github.com/stripe/agent-toolkit/typescript/examples/cloudflare
> wrangler dev

 ⛅️ wrangler 4.13.2 (update available 4.14.1)
-------------------------------------------------------

Using vars defined in .dev.vars
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Durable Objects:
  - MCP_OBJECT: MyMCP
- KV Namespaces:
  - OAUTH_KV: c44... [simulated locally]
- Vars:
  - STRIPE_SECRET_KEY: "(hidden)"
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:4242
✘ [ERROR] OAuth error response: 401 invalid_token - Missing or invalid access token

[wrangler:inf] GET /sse 401 Unauthorized (9ms)
[wrangler:inf] OPTIONS /.well-known/oauth-authorization-server 204 No Content (1ms)
[wrangler:inf] GET /.well-known/oauth-authorization-server 200 OK (2ms)
[wrangler:inf] OPTIONS /register 204 No Content (1ms)
[wrangler:inf] POST /register 201 Created (6ms)
[wrangler:inf] GET /authorize 200 OK (6ms)
[wrangler:inf] GET /favicon.ico 404 Not Found (5ms)
[wrangler:inf] POST /approve 200 OK (19ms)
[wrangler:inf] GET /.well-known/oauth-authorization-server 200 OK (3ms)
[wrangler:inf] POST /token 200 OK (12ms)
[wrangler:inf] GET /sse 200 OK (11ms)
Connection kvYFe7VeZ02X0sDeiw_hE connected to _a:173291278cd81e815260ed1fb8068c4c58ee04a2c9ba529010f7d6992f425b4d
[wrangler:inf] POST /sse/message 202 Accepted (3ms)
[wrangler:inf] POST /sse/message 202 Accepted (4ms)
[wrangler:inf] POST /sse/message 202 Accepted (20ms)
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│  [b] open a browser, [d] open devtools, [l] turn off local mode, [c] clear console, [x] to exit  │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
操作中のinspectorのログ
$ npx @modelcontextprotocol/inspector@latest http://localhost:4242/sse
Starting MCP inspector...
⚙️ Proxy server listening on port 6277
🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀
New SSE connection. NOTE: The sse transport is deprecated and has been replaced by streamable-http
Query parameters: [Object: null prototype] {
  url: 'http://localhost:4242/sse',
  transportType: 'sse'
}
SSE transport: url=http://localhost:4242/sse, headers=Accept
Received 401 Unauthorized from MCP server: SSE error: Non-200 status code (401)
New SSE connection. NOTE: The sse transport is deprecated and has been replaced by streamable-http
Query parameters: [Object: null prototype] {
  url: 'http://localhost:4242/sse',
  transportType: 'sse'
}
SSE transport: url=http://localhost:4242/sse, headers=Accept,authorization
Connected to SSE transport
Connected MCP client to backing server transport
Created web app transport
Set up MCP proxy
Received message for sessionId 08eb9f13-4cb0-466c-9f9d-ba14a98f8d72
Received message for sessionId 08eb9f13-4cb0-466c-9f9d-ba14a98f8d72
Received message for sessionId 08eb9f13-4cb0-466c-9f9d-ba14a98f8d72

デプロイする

❯ wrangler deploy

Cloudflare collects anonymous telemetry about your usage of Wrangler. Learn more at https://github.com/cloudflare/workers-sdk/tree/main/packages/wrangler/telemetry.md

 ⛅️ wrangler 4.14.1
-------------------

Total Upload: 1053.77 KiB / gzip: 186.85 KiB
Worker Startup Time: 36 ms
Your Worker has access to the following bindings:
- Durable Objects:
  - MCP_OBJECT: MyMCP
- KV Namespaces:
  - OAUTH_KV: c44...
Uploaded my-mcp-server (2.55 sec)
Deployed my-mcp-server triggers (0.81 sec)
  https://my-mcp-server.shuntaka9576.workers.dev
Current Version ID: 81e5db47-d615-4e0d-9237-1403cb51bb81
npx wrangler secret put STRIPE_SECRET_KEY

https://my-mcp-server.shuntaka9576.workers.devが作成されました。

リモートサーバーの動作確認

Workers AI LLM Playgroundで試します。

Enter MCP server URLにhttps://my-mcp-server.shuntaka9576.workers.dev/sseを入れ、Connectを押下します。
CleanShot 2025-05-04 at 13.45.23@2x

以下の画面画面が出てきます
CleanShot 2025-05-04 at 13.49.07@2x

ちなみにApproveしていない状態でKVには1レコード挿入されています。これはOAuth 2.0の動的クライアント登録プロセスの過程で作成されたものです。
CleanShot 2025-05-04 at 13.47.56@2x

メールアドレスを変えて、Approveします。
CleanShot 2025-05-04 at 13.50.30@2x

ApproveされるとKV側には3つのレコードが作成されています。
CleanShot 2025-05-04 at 13.58.09@2x

StatusがConnectedになったので接続できたことが確認できます。
CleanShot 2025-05-04 at 15.20.46@2x

ツールを動かしてみます。24+32は? big_addを使って24+32は?の2つを試します。後者は失敗しました。これはまだStripeのpriceIdがソースコードでハードコードされたもののためです。この後の手順で差し替えます。
CleanShot 2025-05-04 at 13.55.46@2x

Cloude(Web)でMCP連携を試す

こちらから、Add moreを押下します
https://claude.ai/settings/profile#integrations-section

Integrations設定をし、Addを押下します。
CleanShot 2025-05-04 at 14.02.06@2x

Connectを押下します。
CleanShot 2025-05-04 at 14.02.58@2x

以下のURLにリダイレクトします。ローカルでやった際と同じです。Approveを押下するとhttps://claude.ai/api/mcp/auth_callbackにリダイレクトされます。

https://my-mcp-server.shuntaka9576.workers.dev/authorize?
response_type=code&
client_id=t...
redirect_uri=https://claude.ai/api/mcp/auth_callback&
scope=claudeai&
code_challenge=1...
code_challenge_method=S256&
state=H...

CleanShot 2025-05-04 at 14.03.39@2x

設定が完了しました。
CleanShot 2025-05-04 at 14.05.36@2x

3つツールが登録されていることも確認できます。
CleanShot 2025-05-04 at 14.06.18@2x

ハードコードされているpriceIDは使えないため、Stripeでテスト用のサブスクを作成します。サンドボックスなので実際にお金は発生しません。

https://dashboard.stripe.com/test/products

プロダクトを作成します。サブスクリプションで月50JPYにします。
CleanShot 2025-05-04 at 14.41.25@2x

priceIDを控えます。
CleanShot 2025-05-04 at 14.42.02@2x

この部分をコピーしたpriceIDに変更します。
https://github.com/stripe/agent-toolkit/blob/03f95ccb98f896f6004df21cdb26ae20da1da189/typescript/examples/cloudflare/src/index.ts#L46

wrangler deploy

未契約の場合

サブスク未契約状態で問い合わせをすると失敗することが確認できます。
CleanShot 2025-05-04 at 14.45.41@2x

ちなみにClaudeのチャットUIで折りたたまれているレスポンスにstripeのサブスク購入リンクがあります。
CleanShot 2025-05-04 at 14.46.48@2x

URLを聞くと教えてくれます。
CleanShot 2025-05-04 at 14.48.26@2x

URLに行くと、Stripeの購入画面に遷移します。テストカードで契約します。
CleanShot 2025-05-04 at 14.49.49@2x

契約済みの場合

契約すると、ここで記載したURLにリダイレクトされます。契約ありがとうございます!的な画面とか詳しい説明リンク、元のアプリの遷移など用意するのが良いと思います。
https://github.com/stripe/agent-toolkit/blob/03f95ccb98f896f6004df21cdb26ae20da1da189/typescript/examples/cloudflare/src/index.ts#L47
CleanShot 2025-05-04 at 14.51.33@2x

契約後問い合わせるとツールが利用できます。
CleanShot 2025-05-04 at 14.53.05@2x

ソース解説

MCPのツール実装です。OAuthProviderに設定するためにクラスでラップしています。
https://github.com/stripe/agent-toolkit/blob/03f95ccb98f896f6004df21cdb26ae20da1da189/typescript/examples/cloudflare/src/index.ts#L19-L72

先ほどのツールをworkers-oauth-providerに設定し、sseの認可処理の実装が可能です。apiHandlerdefaultHandlerですが、型が合わないことが自分もあったのですが、ゴリ押してますね。一つの例として参考になりました。
https://github.com/stripe/agent-toolkit/blob/03f95ccb98f896f6004df21cdb26ae20da1da189/typescript/examples/cloudflare/src/index.ts#L75-L84

さいごに

やってみるとStripeの既存のAPIをMCPでラップした形なのが分かります。SDKなので記述が少なくて済むのは便利ですね。ChatGPTのEC機能がついたりと、大規模言語モデルを介した商品購入の取り組みが始まっています。AI起点で検索を始めることが多くなっていくので相性が良さそうだと思います。他にも面白そうなデモがあったので、試そうと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.