This is page 1 of 7. Use http://codebase.md/stripe/agent-toolkit?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .github
│ ├── ISSUE_TEMPLATE
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ └── workflows
│ ├── main.yml
│ ├── npm_release_shared.yml
│ ├── pypi_release.yml
│ └── sync-skills.yml
├── .gitignore
├── .vscode
│ ├── extensions.json
│ ├── launch.json
│ └── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── gemini-extension.json
├── LICENSE
├── llm
│ ├── ai-sdk
│ │ ├── jest.config.ts
│ │ ├── LICENSE
│ │ ├── meter
│ │ │ ├── examples
│ │ │ │ ├── .env.example
│ │ │ │ ├── .gitignore
│ │ │ │ ├── anthropic.ts
│ │ │ │ ├── google.ts
│ │ │ │ ├── openai.ts
│ │ │ │ ├── README.md
│ │ │ │ └── tsconfig.json
│ │ │ ├── index.ts
│ │ │ ├── meter-event-logging.ts
│ │ │ ├── meter-event-types.ts
│ │ │ ├── README.md
│ │ │ ├── tests
│ │ │ │ ├── ai-sdk-billing-wrapper-anthropic.test.ts
│ │ │ │ ├── ai-sdk-billing-wrapper-general.test.ts
│ │ │ │ ├── ai-sdk-billing-wrapper-google.test.ts
│ │ │ │ ├── ai-sdk-billing-wrapper-openai.test.ts
│ │ │ │ ├── ai-sdk-billing-wrapper-other-providers.test.ts
│ │ │ │ ├── meter-event-logging.test.ts
│ │ │ │ └── model-name-normalization.test.ts
│ │ │ ├── tsconfig.json
│ │ │ ├── types.ts
│ │ │ ├── utils.ts
│ │ │ └── wrapperV2.ts
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── provider
│ │ │ ├── examples
│ │ │ │ ├── .env.example
│ │ │ │ ├── .gitignore
│ │ │ │ ├── anthropic.ts
│ │ │ │ ├── google.ts
│ │ │ │ ├── openai.ts
│ │ │ │ ├── README.md
│ │ │ │ └── tsconfig.json
│ │ │ ├── index.ts
│ │ │ ├── README.md
│ │ │ ├── stripe-language-model.ts
│ │ │ ├── stripe-provider.ts
│ │ │ ├── tests
│ │ │ │ ├── stripe-language-model.test.ts
│ │ │ │ ├── stripe-provider.test.ts
│ │ │ │ └── utils.test.ts
│ │ │ ├── tsconfig.build.json
│ │ │ ├── tsconfig.json
│ │ │ ├── types.ts
│ │ │ └── utils.ts
│ │ ├── README.md
│ │ ├── tsconfig.json
│ │ └── tsup.config.ts
│ ├── README.md
│ └── token-meter
│ ├── examples
│ │ ├── anthropic.ts
│ │ ├── gemini.ts
│ │ └── openai.ts
│ ├── index.ts
│ ├── jest.config.ts
│ ├── LICENSE
│ ├── meter-event-logging.ts
│ ├── meter-event-types.ts
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── README.md
│ ├── tests
│ │ ├── meter-event-logging.test.ts
│ │ ├── model-name-normalization.test.ts
│ │ ├── token-meter-anthropic.test.ts
│ │ ├── token-meter-gemini.test.ts
│ │ ├── token-meter-general.test.ts
│ │ ├── token-meter-openai.test.ts
│ │ └── type-detection.test.ts
│ ├── token-meter.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ ├── types.ts
│ └── utils
│ └── type-detection.ts
├── README.md
├── SECURITY.md
├── skills
│ ├── get-started-kiro.md
│ ├── README.md
│ ├── stripe-best-practices.md
│ └── sync.js
└── tools
├── modelcontextprotocol
│ ├── .dxtignore
│ ├── .gitignore
│ ├── .node-version
│ ├── .prettierrc
│ ├── build-dxt.js
│ ├── Dockerfile
│ ├── eslint.config.mjs
│ ├── jest.config.ts
│ ├── LICENSE
│ ├── manifest.json
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── README.md
│ ├── server.json
│ ├── src
│ │ ├── index.ts
│ │ └── test
│ │ └── index.test.ts
│ ├── stripe_icon.png
│ └── tsconfig.json
├── python
│ ├── .editorconfig
│ ├── .flake8
│ ├── examples
│ │ ├── crewai
│ │ │ ├── .env.template
│ │ │ ├── main.py
│ │ │ └── README.md
│ │ ├── langchain
│ │ │ ├── __init__.py
│ │ │ ├── .env.template
│ │ │ ├── main.py
│ │ │ └── README.md
│ │ ├── openai
│ │ │ ├── .env.template
│ │ │ ├── customer_support
│ │ │ │ ├── .env.template
│ │ │ │ ├── emailer.py
│ │ │ │ ├── env.py
│ │ │ │ ├── main.py
│ │ │ │ ├── pyproject.toml
│ │ │ │ ├── README.md
│ │ │ │ ├── repl.py
│ │ │ │ └── support_agent.py
│ │ │ ├── file_search
│ │ │ │ ├── main.py
│ │ │ │ └── README.md
│ │ │ └── web_search
│ │ │ ├── .env.template
│ │ │ ├── main.py
│ │ │ └── README.md
│ │ └── strands
│ │ └── main.py
│ ├── Makefile
│ ├── pyproject.toml
│ ├── README.md
│ ├── requirements.txt
│ ├── stripe_agent_toolkit
│ │ ├── __init__.py
│ │ ├── api.py
│ │ ├── configuration.py
│ │ ├── crewai
│ │ │ ├── tool.py
│ │ │ └── toolkit.py
│ │ ├── functions.py
│ │ ├── langchain
│ │ │ ├── tool.py
│ │ │ └── toolkit.py
│ │ ├── openai
│ │ │ ├── hooks.py
│ │ │ ├── tool.py
│ │ │ └── toolkit.py
│ │ ├── prompts.py
│ │ ├── schema.py
│ │ ├── strands
│ │ │ ├── __init__.py
│ │ │ ├── hooks.py
│ │ │ ├── tool.py
│ │ │ └── toolkit.py
│ │ └── tools.py
│ └── tests
│ ├── __init__.py
│ ├── test_configuration.py
│ └── test_functions.py
├── README.md
└── typescript
├── .gitignore
├── .prettierrc
├── eslint.config.mjs
├── examples
│ ├── ai-sdk
│ │ ├── .env.template
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── README.md
│ │ └── tsconfig.json
│ ├── cloudflare
│ │ ├── .dev.vars.example
│ │ ├── .gitignore
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── app.ts
│ │ │ ├── imageGenerator.ts
│ │ │ ├── index.ts
│ │ │ ├── oauth.ts
│ │ │ └── utils.ts
│ │ ├── tsconfig.json
│ │ ├── worker-configuration.d.ts
│ │ └── wrangler.jsonc
│ ├── langchain
│ │ ├── .env.template
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── README.md
│ │ └── tsconfig.json
│ └── openai
│ ├── .env.template
│ ├── index.ts
│ ├── package.json
│ ├── README.md
│ └── tsconfig.json
├── jest.config.ts
├── LICENSE
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── README.md
├── src
│ ├── ai-sdk
│ │ ├── index.ts
│ │ ├── tool.ts
│ │ └── toolkit.ts
│ ├── cloudflare
│ │ ├── index.ts
│ │ └── README.md
│ ├── langchain
│ │ ├── index.ts
│ │ ├── tool.ts
│ │ └── toolkit.ts
│ ├── modelcontextprotocol
│ │ ├── index.ts
│ │ ├── README.md
│ │ ├── register-paid-tool.ts
│ │ └── toolkit.ts
│ ├── openai
│ │ ├── index.ts
│ │ └── toolkit.ts
│ ├── shared
│ │ ├── api.ts
│ │ ├── balance
│ │ │ └── retrieveBalance.ts
│ │ ├── configuration.ts
│ │ ├── coupons
│ │ │ ├── createCoupon.ts
│ │ │ └── listCoupons.ts
│ │ ├── customers
│ │ │ ├── createCustomer.ts
│ │ │ └── listCustomers.ts
│ │ ├── disputes
│ │ │ ├── listDisputes.ts
│ │ │ └── updateDispute.ts
│ │ ├── documentation
│ │ │ └── searchDocumentation.ts
│ │ ├── invoiceItems
│ │ │ └── createInvoiceItem.ts
│ │ ├── invoices
│ │ │ ├── createInvoice.ts
│ │ │ ├── finalizeInvoice.ts
│ │ │ └── listInvoices.ts
│ │ ├── paymentIntents
│ │ │ └── listPaymentIntents.ts
│ │ ├── paymentLinks
│ │ │ └── createPaymentLink.ts
│ │ ├── prices
│ │ │ ├── createPrice.ts
│ │ │ └── listPrices.ts
│ │ ├── products
│ │ │ ├── createProduct.ts
│ │ │ └── listProducts.ts
│ │ ├── refunds
│ │ │ └── createRefund.ts
│ │ ├── subscriptions
│ │ │ ├── cancelSubscription.ts
│ │ │ ├── listSubscriptions.ts
│ │ │ └── updateSubscription.ts
│ │ └── tools.ts
│ └── test
│ ├── modelcontextprotocol
│ │ └── register-paid-tool.test.ts
│ └── shared
│ ├── balance
│ │ ├── functions.test.ts
│ │ └── parameters.test.ts
│ ├── configuration.test.ts
│ ├── customers
│ │ ├── functions.test.ts
│ │ └── parameters.test.ts
│ ├── disputes
│ │ └── functions.test.ts
│ ├── documentation
│ │ ├── functions.test.ts
│ │ └── parameters.test.ts
│ ├── invoiceItems
│ │ ├── functions.test.ts
│ │ ├── parameters.test.ts
│ │ └── prompts.test.ts
│ ├── invoices
│ │ ├── functions.test.ts
│ │ ├── parameters.test.ts
│ │ └── prompts.test.ts
│ ├── paymentIntents
│ │ ├── functions.test.ts
│ │ ├── parameters.test.ts
│ │ └── prompts.test.ts
│ ├── paymentLinks
│ │ ├── functions.test.ts
│ │ ├── parameters.test.ts
│ │ └── prompts.test.ts
│ ├── prices
│ │ ├── functions.test.ts
│ │ └── parameters.test.ts
│ ├── products
│ │ ├── functions.test.ts
│ │ └── parameters.test.ts
│ ├── refunds
│ │ ├── functions.test.ts
│ │ └── parameters.test.ts
│ └── subscriptions
│ ├── functions.test.ts
│ ├── parameters.test.ts
│ └── prompts.test.ts
├── tsconfig.json
└── tsup.config.ts
```
# Files
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/.node-version:
--------------------------------------------------------------------------------
```
1 | 22.14.0
2 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/.gitignore:
--------------------------------------------------------------------------------
```
1 | dist/
2 | node_modules/
3 | *.dxt
4 | dxt-dist/
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/.env.template:
--------------------------------------------------------------------------------
```
1 | OPENAI_API_KEY=""
2 | STRIPE_SECRET_KEY=""
```
--------------------------------------------------------------------------------
/tools/typescript/examples/openai/.env.template:
--------------------------------------------------------------------------------
```
1 | OPENAI_API_KEY=""
2 | STRIPE_SECRET_KEY=""
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/.gitignore:
--------------------------------------------------------------------------------
```
1 | # wrangler project
2 | .dev.vars
3 | .wrangler/
4 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/langchain/.env.template:
--------------------------------------------------------------------------------
```
1 | LANGSMITH_API_KEY=""
2 | STRIPE_SECRET_KEY=""
3 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/.dxtignore:
--------------------------------------------------------------------------------
```
1 | node_modules/
2 | node_modules/**/*.*
3 | tsconfig.json
4 | Dockerfile
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/web_search/.env.template:
--------------------------------------------------------------------------------
```
1 | OPENAI_API_KEY=""
2 | STRIPE_SECRET_KEY=""
3 | STRIPE_CUSTOMER_ID=""
4 | STRIPE_METER=""
5 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/.prettierrc:
--------------------------------------------------------------------------------
```
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "es5",
4 | "bracketSpacing": false
5 | }
6 |
```
--------------------------------------------------------------------------------
/tools/typescript/.prettierrc:
--------------------------------------------------------------------------------
```
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "es5",
4 | "bracketSpacing": false
5 | }
6 |
```
--------------------------------------------------------------------------------
/tools/python/examples/crewai/.env.template:
--------------------------------------------------------------------------------
```
1 | STRIPE_SECRET_KEY=""
2 | OPENAI_API_BASE=""
3 | OPENAI_MODEL_NAME="gpt-4o"
4 | OPENAI_API_KEY=""
5 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/ai-sdk/.env.template:
--------------------------------------------------------------------------------
```
1 | STRIPE_SECRET_KEY=""
2 | STRIPE_CUSTOMER_ID=""
3 | STRIPE_METER_INPUT=""
4 | STRIPE_METER_OUTPUT=""
5 |
```
--------------------------------------------------------------------------------
/tools/python/examples/langchain/.env.template:
--------------------------------------------------------------------------------
```
1 | LANGSMITH_API_KEY=""
2 | STRIPE_SECRET_KEY=""
3 | OPENAI_API_BASE=""
4 | OPENAI_MODEL_NAME="gpt-4o"
5 | OPENAI_API_KEY=""
6 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/examples/.env.example:
--------------------------------------------------------------------------------
```
1 | STRIPE_API_KEY=sk_test_...
2 | STRIPE_CUSTOMER_ID=cus_...
3 | OPENAI_API_KEY=...
4 | ANTHROPIC_API_KEY=...
5 | GOOGLE_GENERATIVE_AI_API_KEY=...
6 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/examples/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Environment variables
2 | .env
3 | .env.local
4 | .env.*.local
5 |
6 | # Allow .env.example
7 | !.env.example
8 |
9 | # Node modules (if any get installed here)
10 | node_modules/
11 |
12 | # Build outputs
13 | dist/
14 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/examples/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Environment variables
2 | .env
3 | .env.local
4 | .env.*.local
5 |
6 | # Allow .env.example
7 | !.env.example
8 |
9 | # Node modules (if any get installed here)
10 | node_modules/
11 |
12 | # Build outputs
13 | dist/
14 |
15 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/.dev.vars.example:
--------------------------------------------------------------------------------
```
1 | STRIPE_SECRET_KEY=sk_test_......
2 | STRIPE_PRICE_ID_ONE_TIME_PAYMENT=price_1RJJwjR1b4cWtS0UCIDTSU3V
3 | STRIPE_PRICE_ID_SUBSCRIPTION=price_1RJJwjR1bGyW9S0UCIDTSU3V
4 | STRIPE_PRICE_ID_USAGE_BASED_SUBSCRIPTION=price_1RJdGWR1bGyW9S0UucbYBFBZ
```
--------------------------------------------------------------------------------
/tools/python/.editorconfig:
--------------------------------------------------------------------------------
```
1 | ; https://editorconfig.org/
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = space
7 | indent_size = 4
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 | end_of_line = lf
11 | charset = utf-8
12 |
13 | [*.{cfg,ini,json,toml,yml}]
14 | indent_size = 2
15 |
16 | [Makefile]
17 | indent_style = tab
18 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/examples/.env.example:
--------------------------------------------------------------------------------
```
1 | # Stripe API Configuration
2 | # Copy this file to .env and fill in your actual values
3 |
4 | # Your Stripe API key (test or live)
5 | # Get it from: https://dashboard.stripe.com/apikeys
6 | STRIPE_API_KEY=sk_test_...
7 |
8 | # Your Stripe Customer ID
9 | # Format: cus_xxxxx
10 | STRIPE_CUSTOMER_ID=cus_...
11 |
12 | # Provider-specific API keys
13 | # (Only required for the provider you want to test)
14 |
15 | # OpenAI API key
16 | OPENAI_API_KEY=sk-...
17 |
18 | # Anthropic API key
19 | ANTHROPIC_API_KEY=sk-ant-...
20 |
21 | # Google Generative AI API key
22 | GOOGLE_GENERATIVE_AI_API_KEY=...
23 |
24 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/customer_support/.env.template:
--------------------------------------------------------------------------------
```
1 | OPENAI_API_KEY=your_openai_api_key
2 | STRIPE_SECRET_KEY=your_stripe_secret_key
3 |
4 | # Your email address and app password
5 | # https://support.google.com/accounts/answer/185833?hl=en
6 | [email protected]
7 | EMAIL_PASSWORD=your_app_specific_password
8 | # Only respond to emails send to this address (defaults to $EMAIL_ADDRESS)
9 | SUPPORT_ADDRESS="[email protected]"
10 |
11 | # If your connecting to gmail, you don't need to customize these
12 | IMAP_SERVER=imap.gmail.com
13 | IMAP_PORT=993
14 | SMTP_SERVER=smtp.gmail.com
15 | SMTP_PORT=587
16 |
```
--------------------------------------------------------------------------------
/tools/python/.flake8:
--------------------------------------------------------------------------------
```
1 | [flake8]
2 | # E501 is the "Line too long" error. We disable it because we use Black for
3 | # code formatting. Black makes a best effort to keep lines under the max
4 | # length, but can go over in some cases.
5 | # W503 goes against PEP8 rules. It's disabled by default, but must be disabled
6 | # explicitly when using `ignore`.
7 | # E704 is disabled in the default configuration, but by specifying `ignore`, we wipe that out.
8 | # ruff formatting creates code that violates it, so we have to disable it manually
9 | ignore = E501, W503, E704
10 | per-file-ignores =
11 | # setup.py is required for tooling
12 | setup.py: IMP102
13 |
```
--------------------------------------------------------------------------------
/tools/typescript/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 | junk/
45 |
46 | # Snowpack dependency directory (https://snowpack.dev/)
47 | web_modules/
48 |
49 | # TypeScript cache
50 | *.tsbuildinfo
51 |
52 | # Optional npm cache directory
53 | .npm
54 |
55 | # Optional eslint cache
56 | .eslintcache
57 |
58 | # Optional stylelint cache
59 | .stylelintcache
60 |
61 | # Microbundle cache
62 | .rpt2_cache/
63 | .rts2_cache_cjs/
64 | .rts2_cache_es/
65 | .rts2_cache_umd/
66 |
67 | # Optional REPL history
68 | .node_repl_history
69 |
70 | # Output of 'npm pack'
71 | *.tgz
72 |
73 | # Yarn Integrity file
74 | .yarn-integrity
75 |
76 | # dotenv environment variable files
77 | .env
78 | .env.development.local
79 | .env.test.local
80 | .env.production.local
81 | .env.local
82 |
83 | # parcel-bundler cache (https://parceljs.org/)
84 | .cache
85 | .parcel-cache
86 |
87 | # Next.js build output
88 | .next
89 | out
90 |
91 | # Nuxt.js build / generate output
92 | .nuxt
93 | dist
94 |
95 | # Gatsby files
96 | .cache/
97 | # Comment in the public line in if your project uses Gatsby and not Next.js
98 | # https://nextjs.org/blog/next-9-1#public-directory-support
99 | # public
100 |
101 | # vuepress build output
102 | .vuepress/dist
103 |
104 | # vuepress v2.x temp and cache directory
105 | .temp
106 | .cache
107 |
108 | # Docusaurus cache and generated files
109 | .docusaurus
110 |
111 | # Serverless directories
112 | .serverless/
113 |
114 | # FuseBox cache
115 | .fusebox/
116 |
117 | # DynamoDB Local files
118 | .dynamodb/
119 |
120 | # TernJS port file
121 | .tern-port
122 |
123 | # Stores VSCode versions used for testing VSCode extensions
124 | .vscode-test
125 |
126 | # yarn v2
127 | .yarn/cache
128 | .yarn/unplugged
129 | .yarn/build-state.yml
130 | .yarn/install-state.gz
131 | .pnp.*
132 |
133 | .turbo
134 |
135 |
136 | /cloudflare/
137 | /openai/
138 | /ai-sdk/
139 | /langchain/
140 | /modelcontextprotocol/
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Node modules
10 | node_modules/
11 | junk/
12 |
13 | # Distribution / packaging
14 | .Python
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | wheels/
27 | share/python-wheels/
28 | *.egg-info/
29 | .installed.cfg
30 | *.egg
31 | MANIFEST
32 |
33 | # PyInstaller
34 | # Usually these files are written by a python script from a template
35 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
36 | *.manifest
37 | *.spec
38 |
39 | # Installer logs
40 | pip-log.txt
41 | pip-delete-this-directory.txt
42 |
43 | # Unit test / coverage reports
44 | htmlcov/
45 | .tox/
46 | .nox/
47 | .coverage
48 | .coverage.*
49 | .cache
50 | nosetests.xml
51 | coverage.xml
52 | *.cover
53 | *.py,cover
54 | .hypothesis/
55 | .pytest_cache/
56 | cover/
57 |
58 | # Translations
59 | *.mo
60 | *.pot
61 |
62 | # Django stuff:
63 | *.log
64 | local_settings.py
65 | db.sqlite3
66 | db.sqlite3-journal
67 |
68 | # Flask stuff:
69 | instance/
70 | .webassets-cache
71 |
72 | # Scrapy stuff:
73 | .scrapy
74 |
75 | # Sphinx documentation
76 | docs/_build/
77 |
78 | # PyBuilder
79 | .pybuilder/
80 | target/
81 |
82 | # Jupyter Notebook
83 | .ipynb_checkpoints
84 |
85 | # IPython
86 | profile_default/
87 | ipython_config.py
88 |
89 | # pyenv
90 | # For a library or package, you might want to ignore these files since the code is
91 | # intended to run in multiple environments; otherwise, check them in:
92 | # .python-version
93 |
94 | # pipenv
95 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
96 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
97 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
98 | # install all needed dependencies.
99 | #Pipfile.lock
100 |
101 | # poetry
102 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
103 | # This is especially recommended for binary packages to ensure reproducibility, and is more
104 | # commonly ignored for libraries.
105 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
106 | #poetry.lock
107 |
108 | # pdm
109 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
110 | #pdm.lock
111 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
112 | # in version control.
113 | # https://pdm.fming.dev/#use-with-ide
114 | .pdm.toml
115 |
116 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
117 | __pypackages__/
118 |
119 | # Celery stuff
120 | celerybeat-schedule
121 | celerybeat.pid
122 |
123 | # SageMath parsed files
124 | *.sage.py
125 |
126 | # Environments
127 | .env
128 | .venv
129 | env/
130 | venv/
131 | ENV/
132 | env.bak/
133 | venv.bak/
134 |
135 | # Spyder project settings
136 | .spyderproject
137 | .spyproject
138 |
139 | # Rope project settings
140 | .ropeproject
141 |
142 | # mkdocs documentation
143 | /site
144 |
145 | # mypy
146 | .mypy_cache/
147 | .dmypy.json
148 | dmypy.json
149 |
150 | # Pyre type checker
151 | .pyre/
152 |
153 | # pytype static type analyzer
154 | .pytype/
155 |
156 | # Cython debug symbols
157 | cython_debug/
158 |
159 | # PyCharm
160 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
161 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162 | # and can be added to the global gitignore or merged into this file. For a more nuclear
163 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164 | #.idea/
165 |
```
--------------------------------------------------------------------------------
/tools/python/examples/crewai/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # CrewAI Example
2 |
3 | ## Setup
4 |
5 | Copy the `.env.template` and populate with your values.
6 |
7 | ```
8 | cp .env.template .env
9 | ```
10 |
11 | ## Usage
12 |
13 | ```
14 | python main.py
15 | ```
16 |
```
--------------------------------------------------------------------------------
/tools/python/examples/langchain/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # LangChain Example
2 |
3 | ## Setup
4 |
5 | Copy the `.env.template` and populate with your values.
6 |
7 | ```
8 | cp .env.template .env
9 | ```
10 |
11 | ## Usage
12 |
13 | ```
14 | python main.py
15 | ```
16 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/ai-sdk/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # AI SDK Example
2 |
3 | ## Setup
4 |
5 | Copy the `.env.template` and populate with your values.
6 |
7 | ```
8 | cp .env.template .env
9 | ```
10 |
11 | ## Usage
12 |
13 | ```
14 | npx ts-node index.ts --env
15 | ```
16 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/openai/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # OpenAI Example
2 |
3 | ## Setup
4 |
5 | Copy the `.env.template` and populate with your values.
6 |
7 | ```
8 | cp .env.template .env
9 | ```
10 |
11 | ## Usage
12 |
13 | ```
14 | npx ts-node index.ts --env
15 | ```
16 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/langchain/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # LangChain Example
2 |
3 | ## Setup
4 |
5 | Copy the `.env.template` and populate with your values.
6 |
7 | ```
8 | cp .env.template .env
9 | ```
10 |
11 | ## Usage
12 |
13 | ```
14 | npx ts-node index.ts --env
15 | ```
16 |
```
--------------------------------------------------------------------------------
/skills/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Skills
2 |
3 | Agents need instructions to follow. The better the instructions, the more likely the agent will be able to do something useful for/with their user.
4 |
5 | Stripe has:
6 |
7 | - LLM readable Docs (append .md to the end of any Docs)
8 | - `search_stripe_documentation` tool built into our MCP server
9 | - MCP Prompts
10 |
11 | This folder is a folder of "prompts" synced with prompts on mcp.stripe.com. The syncing is done through a GitHub action.
12 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/file_search/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Web Search Example
2 |
3 | This example shows how to use the Stripe Agent Toolkit with OpenAI to create an agent that can search the web and charge for outcomes.
4 |
5 | ## Setup
6 |
7 | 1. Create a OpenAI Vector Store following the [OpenAI documentation](https://platform.openai.com/docs/api-reference/vector-stores-files) and add the files you want to search.
8 |
9 | 2. Copy `.env.template` to `.env` populate with the relevant values.
10 |
11 | ```bash
12 | OPENAI_API_KEY=your_openai_api_key
13 | OPENAI_VECTOR_STORE_ID=your_openai_vector_store_id
14 | STRIPE_SECRET_KEY=your_stripe_secret_key
15 | ```
16 |
17 | ## Usage
18 |
19 | ```bash
20 | python main.py
21 | ```
22 |
23 | You can see the invoices created in the Stripe Dashboard.
24 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/web_search/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Web Search Example
2 |
3 | This example shows how to use the Stripe Agent Toolkit with OpenAI to create an agent that can search the web and charge for outcomes.
4 |
5 | ## Setup
6 |
7 | 1. Create a Stripe Billing Meter and Stripe Customer following the [Stripe documentation](https://docs.stripe.com/billing/subscriptions/usage-based/implementation-guide).
8 |
9 | 2. Copy `.env.template` to `.env` populate with the relevant values.
10 |
11 | ```bash
12 | OPENAI_API_KEY=your_openai_api_key
13 | STRIPE_SECRET_KEY=your_stripe_secret_key
14 | STRIPE_CUSTOMER_ID=your_stripe_customer_id
15 | STRIPE_METER=your_stripe_meter
16 | ```
17 |
18 | ## Usage
19 |
20 | ```bash
21 | python main.py
22 | ```
23 |
24 | You can see the usage in the Stripe Dashboard.
25 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/modelcontextprotocol/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # MCP Payments
2 |
3 | A simple MCP server helper to require payment to use tools, whether subscription or usage-based.
4 |
5 | This implementation works on Vercel with a standard MCP server.
6 |
7 | ## Usage Instructions for `registerPaidTool`
8 |
9 | 1. Import the `registerPaidTool` function from this package.
10 | 2. Call `registerPaidTool` with your MCP server, tool name, description, params schema, callback, and payment options.
11 | 3. Example usage:
12 |
13 | ```ts
14 | import {registerPaidTool} from './register-paid-tool';
15 | import {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js';
16 |
17 | const server = new McpServer({
18 | name: 'mcp-typescript server',
19 | version: '0.1.0',
20 | });
21 |
22 | registerPaidTool(
23 | server,
24 | 'add_numbers',
25 | {
26 | a: z.number(),
27 | b: z.number(),
28 | },
29 | ({a, b}) => {
30 | return {
31 | content: [{type: 'text', text: `Result: ${a + b}`}],
32 | };
33 | },
34 | {
35 | priceId: '{{PRICE_ID}}',
36 | successUrl: '{{CALLBACK_URL}}',
37 | email: '{{EMAIL}}',
38 | paymentReason:
39 | 'You must pay a subscription to add two big numbers together.',
40 | stripeSecretKey: '{{SECRET_KEY}}',
41 | }
42 | );
43 | ```
44 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # PaidMcpAgent
2 |
3 | An example of how to monetize an MCP server with Stripe.
4 |
5 | ## Setup
6 |
7 | 1. Copy `.dev.vars.example` to `.dev.vars` and add your Stripe API key.
8 | 2. Configure the required Stripe environment variables:
9 | - `STRIPE_SECRET_KEY`: Your Stripe secret key
10 | - `STRIPE_ONETIME_SUBSCRIPTION_PRICE_ID`: Price ID for one-time payment
11 | - `STRIPE_PRICE_ID_USAGE_BASED_SUBSCRIPTION`: Price ID for usage-based subscription
12 | - `STRIPE_METER_EVENT_NAME`: Event name for usage metering
13 | 3. This demo uses an example fake OAuth implementation for the MCP server. We recommend following the [authorization](https://developers.cloudflare.com/agents/model-context-protocol/authorization/) Cloudflare docs.
14 |
15 | ## Development
16 |
17 | ```
18 | pnpm i
19 | pnpm dev
20 | ```
21 |
22 | ## Testing
23 |
24 | Open up the inspector and connect to your MCP server.
25 |
26 | ```
27 | npx @modelcontextprotocol/inspector@latest http://localhost:4242/sse
28 | ```
29 |
30 | ### Deploy
31 |
32 | ```
33 | npx wrangler secret put STRIPE_SECRET_KEY
34 | npx wrangler secret put STRIPE_PRICE_ID_ONE_TIME_PAYMENT
35 | npx wrangler secret put STRIPE_ONETIME_SUBSCRIPTION_PRICE_ID
36 | npx wrangler secret put STRIPE_PRICE_ID_USAGE_BASED_SUBSCRIPTION
37 | ```
38 |
39 | ### Feedback
40 |
41 | Please leave feedback throught the GitHub issues and discussions on how you
42 | would use the `PaidMcpAgent`!
43 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/customer_support/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Email Support Agent
2 |
3 | Sample app to help you automate your email support. Powered by OpenAI's Agent SDK and [Stripe Agent Toolkit](https://github.com/stripe/ai).
4 |
5 | Customize this agent to fit your own needs by cloning and modifying [support_agent.py](./support_agent.py).
6 |
7 | ## Features
8 |
9 | The support agent currently can:
10 |
11 | - Answer FAQ questions
12 | - Update billing information through Customer Portal
13 | - Send any missing invoices
14 |
15 | We also support a REPL to help you test your agent without sending a gazillion emails.
16 |
17 | ## How it Works
18 |
19 | The support agent will:
20 |
21 | - Connects to your email using an IMAP client
22 | - Checks for unread emails every 30 seconds
23 | - Generates and sends a reply
24 | - Marks the emails as read
25 |
26 | If it doesn't know how to answer the question, it will not respond and ignore the email.
27 |
28 | ## Setup
29 |
30 | 1. Install uv (if not already installed):
31 |
32 | ```bash
33 | curl -LsSf https://astral.sh/uv/install.sh | sh
34 | ```
35 |
36 | 2. Clone this repository
37 | 3. Create and activate a virtual environment:
38 |
39 | ```bash
40 | uv venv
41 | source .venv/bin/activate # On Unix/macOS
42 | # or
43 | .venv\Scripts\activate # On Windows
44 | ```
45 |
46 | 4. Install dependencies:
47 |
48 | ```bash
49 | uv sync
50 | ```
51 |
52 | 5. Copy `.env.example` to `.env`:
53 |
54 | ```bash
55 | cp .env.example .env
56 | ```
57 |
58 | 6. Configure your `.env` file with:
59 | - Email credentials (create an [app-specific password](https://support.google.com/accounts/answer/185833) for Gmail)
60 | - IMAP/SMTP server details (defaults for Gmail provided in .env.example)
61 | - OpenAI API key
62 | - Stripe Secret Key
63 |
64 | ## Usage
65 |
66 | Run the agent:
67 |
68 | ```bash
69 | python main.py
70 | ```
71 |
72 | Run the REPL with:
73 |
74 | ```bash
75 | python repl.py
76 | ```
77 |
78 | ## Customize for your App
79 |
80 | This repository is just a sample app tailored to our [example website](http://standupjack.com).
81 |
82 | We recommend cloning this repository and customizing the system prompt and tools in [support_agent.py](./support_agent.py). It's very easy to add new capabilities.
83 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/cloudflare/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # MCP Payments
2 |
3 | `PaidMcpAgent` extends [Cloudflare's `McpAgent`](https://github.com/cloudflare/agents) to make it simple to require payment to use tools, whether subscription or usage-based. For a full end-to-end example, see [/examples/cloudflare](../../examples/cloudflare/).
4 |
5 | ## Usage
6 |
7 | ### Setup
8 |
9 | ```
10 | npm install @stripe/agent-toolkit
11 | ```
12 |
13 | Modify your existing MCP server by extending with `PaidMcpAgent` instead of `McpAgent`.
14 |
15 | ```ts
16 | import {
17 | PaymentState,
18 | experimental_PaidMcpAgent as PaidMcpAgent,
19 | } from '@stripe/agent-toolkit/cloudflare';
20 |
21 | type Props = {
22 | userEmail: string;
23 | };
24 |
25 | type State = PaymentState & {};
26 |
27 | export class MyMCP extends PaidMcpAgent<Bindings, State, Props> {}
28 | ```
29 |
30 | Lastly, set your `STRIPE_SECRET_KEY` in `.dev.vars` to test, and then `npx wrangler secret put STRIPE_SECRET_KEY` when ready for production.
31 |
32 | ### Monetizing a tool
33 |
34 | Consider a basic tool that can add two numbers together:
35 |
36 | ```ts
37 | this.server.tool('add', {a: z.number(), b: z.number()}, ({a, b}) => {
38 | return {
39 | content: [{type: 'text', text: `Result: ${a + b}`}],
40 | };
41 | });
42 | ```
43 |
44 | To make this paid using a subscription, first create a product and price in the Stripe Dashboard.
45 |
46 | Then, replace `this.server.tool` with `this.paidTool` and add your payment config: `priceId`, `paymentReason`, and `successUrl`.
47 |
48 | ```ts
49 | this.paidTool(
50 | 'add_numbers',
51 | {
52 | a: z.number(),
53 | b: z.number(),
54 | },
55 | ({a, b}) => {
56 | return {
57 | content: [{type: 'text', text: `Result: ${a + b}`}],
58 | };
59 | },
60 | {
61 | priceId: '{{PRICE_ID}}',
62 | successUrl: 'https://mcp.mysite.com/success',
63 | paymentReason:
64 | 'You must pay a subscription to add two big numbers together.',
65 | }
66 | );
67 | ```
68 |
69 | ## Authentication
70 |
71 | `PaidMcp` relies on `props.userEmail` to identify (or create) a Stripe customer. You can prepopulate this directly, or integrate with `OAuthProvider` from `@cloudflare/workers-oauth-provider` to set the prop on succesful authentication.
72 |
```
--------------------------------------------------------------------------------
/tools/python/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe Agent Toolkit - Python
2 |
3 | The Stripe Agent Toolkit library enables popular agent frameworks including OpenAI's Agent SDK, LangChain, and CrewAI to integrate with Stripe APIs through function calling. The
4 | library is not exhaustive of the entire Stripe API. It is built directly on top
5 | of the [Stripe Python SDK][python-sdk].
6 |
7 | ## Installation
8 |
9 | You don't need this source code unless you want to modify the package. If you just
10 | want to use the package, just run:
11 |
12 | ```sh
13 | uv pip install stripe-agent-toolkit
14 | ```
15 |
16 | ### Requirements
17 |
18 | - Python 3.11+
19 |
20 | ## Usage
21 |
22 | The library needs to be configured with your account's secret key which is
23 | available in your [Stripe Dashboard][api-keys].
24 |
25 | ```python
26 | from stripe_agent_toolkit.openai.toolkit import StripeAgentToolkit
27 |
28 | stripe_agent_toolkit = StripeAgentToolkit(
29 | secret_key="sk_test_...",
30 | configuration={
31 | "actions": {
32 | "payment_links": {
33 | "create": True,
34 | },
35 | }
36 | },
37 | )
38 | ```
39 |
40 | The toolkit works with OpenAI's Agent SDK, LangChain, and CrewAI and can be passed as a list of tools. For example:
41 |
42 | ```python
43 | from agents import Agent
44 |
45 | stripe_agent = Agent(
46 | name="Stripe Agent",
47 | instructions="You are an expert at integrating with Stripe",
48 | tools=stripe_agent_toolkit.get_tools()
49 | )
50 | ```
51 |
52 | Examples for OpenAI's Agent SDK,LangChain, and CrewAI are included in [/examples](/examples).
53 |
54 | [python-sdk]: https://github.com/stripe/stripe-python
55 | [api-keys]: https://dashboard.stripe.com/account/apikeys
56 |
57 | #### Context
58 |
59 | In some cases you will want to provide values that serve as defaults when making requests. Currently, the `account` context value enables you to make API calls for your [connected accounts](https://docs.stripe.com/connect/authentication).
60 |
61 | ```python
62 | stripe_agent_toolkit = StripeAgentToolkit(
63 | secret_key="sk_test_...",
64 | configuration={
65 | "context": {
66 | "account": "acct_123"
67 | }
68 | }
69 | )
70 | ```
71 |
72 | ## Development
73 |
74 | ```
75 | uv venv --python 3.11
76 | source .venv/bin/activate
77 | uv pip install -r requirements.txt
78 | ```
79 |
```
--------------------------------------------------------------------------------
/llm/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # LLM metering packages
2 |
3 | This directory contains two packages for tracking and billing LLM token usage with Stripe.
4 |
5 | ## Private preview access required
6 |
7 | Stripe Billing for LLM Tokens is currently only available to organizations participating in the Billing for LLM Tokens Private Preview. If you don't have access and would like to request it, please visit:
8 |
9 | **[Request Access to Billing for LLM Tokens Private Preview](https://docs.stripe.com/billing/token-billing)**
10 |
11 | ## Packages
12 |
13 | ### `@stripe/ai-sdk`
14 |
15 | The Stripe AI SDK provides tools for integrating AI models with Stripe's billing infrastructure when using the Vercel AI SDK. It includes two components:
16 |
17 |
18 |
19 | - **Provider** (`@stripe/ai-sdk/provider`): A custom Vercel AI SDK provider that routes requests through Stripe's LLM proxy at `llm.stripe.com`. It provides a unified interface to access OpenAI, Google Gemini, and Anthropic Claude models with automatic usage tracking and billing integration.
20 |
21 | - **Meter** (`@stripe/ai-sdk/meter`): A wrapper utility that adds billing tracking to any Vercel AI SDK v2 language model. This allows you to use your preferred provider while still tracking usage in Stripe without changing your existing provider setup.
22 |
23 | ### Use ai-sdk when
24 |
25 | - You're using or want to use Vercel AI SDK
26 | - You want a unified interface across multiple AI providers
27 | - You want AI SDK-specific features like tool calling abstractions
28 | - You prefer the AI SDK's streaming abstractions
29 |
30 |
31 | [View ai-sdk documentation](./ai-sdk/README.md)
32 |
33 | ### `@stripe/token-meter`
34 |
35 | @stripe/token-meter provides generic token metering for native AI SDKs with automatic Stripe billing integration. Unlike the ai-sdk package, this works directly with native SDKs from OpenAI, Anthropic, and Google Gemini without requiring the Vercel AI SDK or any other framework.
36 |
37 | It automatically detects provider and response types, supports both streaming and non-streaming responses, and sends billing events asynchronously to Stripe without blocking your application.
38 |
39 | ### Use token-meter when
40 |
41 | - You're using native SDKs (OpenAI, Anthropic, Google) directly
42 | - You don't want framework dependencies
43 | - You need maximum control over API parameters
44 | - You're working with embeddings or specialized APIs
45 |
46 | [View token-meter documentation](./token-meter/README.md)
47 |
48 |
49 | ## Installation
50 |
51 | For Vercel AI SDK integration:
52 | ```bash
53 | npm install @stripe/ai-sdk
54 | ```
55 |
56 | For native SDK integration:
57 | ```bash
58 | npm install @stripe/token-meter
59 | ```
60 |
61 | ## Additional resources
62 |
63 | - [Stripe Meter Events Documentation](https://docs.stripe.com/api/billing/meter-event)
64 | - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing)
65 | - [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
66 |
67 | ## License
68 |
69 | MIT
70 |
71 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe Model Context Protocol
2 |
3 | The Stripe [Model Context Protocol](https://modelcontextprotocol.com/) server allows you to integrate with Stripe APIs through function calling. This protocol supports various tools to interact with different Stripe services.
4 |
5 | ## Setup
6 |
7 | Stripe hosts a remote MCP server at https://mcp.stripe.com. View the docs [here](https://docs.stripe.com/mcp).
8 |
9 | ## Local
10 |
11 | To run the Stripe MCP server locally using npx, use the following command:
12 |
13 | ```bash
14 | # To set up all available tools
15 | npx -y @stripe/mcp --tools=all --api-key=YOUR_STRIPE_SECRET_KEY
16 |
17 | # To set up specific tools
18 | npx -y @stripe/mcp --tools=customers.create,customers.read,products.create --api-key=YOUR_STRIPE_SECRET_KEY
19 |
20 | # To configure a Stripe connected account
21 | npx -y @stripe/mcp --tools=all --api-key=YOUR_STRIPE_SECRET_KEY --stripe-account=CONNECTED_ACCOUNT_ID
22 | ```
23 |
24 | Make sure to replace `YOUR_STRIPE_SECRET_KEY` with your actual Stripe secret key. Alternatively, you could set the STRIPE_SECRET_KEY in your environment variables.
25 |
26 | ### Usage with Claude Desktop
27 |
28 | Add the following to your `claude_desktop_config.json`. See [here](https://modelcontextprotocol.io/quickstart/user) for more details.
29 |
30 | ```
31 | {
32 | "mcpServers": {
33 | "stripe": {
34 | "command": "npx",
35 | "args": [
36 | "-y",
37 | "@stripe/mcp",
38 | "--tools=all",
39 | "--api-key=STRIPE_SECRET_KEY"
40 | ]
41 | }
42 | }
43 | }
44 | ```
45 |
46 | of if you're using Docker
47 |
48 | ```
49 | {
50 | “mcpServers”: {
51 | “stripe”: {
52 | “command”: “docker",
53 | “args”: [
54 | “run”,
55 | "--rm",
56 | "-i",
57 | “mcp/stripe”,
58 | “--tools=all”,
59 | “--api-key=STRIPE_SECRET_KEY”
60 | ]
61 | }
62 | }
63 | }
64 |
65 | ```
66 |
67 | ### Usage with Gemini CLI
68 |
69 | 1. Install [Gemini CLI](https://google-gemini.github.io/gemini-cli/#-installation) through your preferred method.
70 | 2. Install the Stripe MCP extension: `gemini extensions install https://github.com/stripe/ai`.
71 | 3. Start Gemini CLI: `gemini`.
72 | 4. Go through the OAUTH flow: `/mcp auth stripe`.
73 |
74 | ## Available tools
75 |
76 | See the [Stripe MCP documentation](https://docs.stripe.com/mcp#tools) for a list of tools.
77 |
78 | ## Debugging the Server
79 |
80 | To debug your server, you can use the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector).
81 |
82 | First build the server
83 |
84 | ```
85 | npm run build
86 | ```
87 |
88 | Run the following command in your terminal:
89 |
90 | ```bash
91 | # Start MCP Inspector and server with all tools
92 | npx @modelcontextprotocol/inspector node dist/index.js --tools=all --api-key=YOUR_STRIPE_SECRET_KEY
93 | ```
94 |
95 | ### Build using Docker
96 |
97 | First build the server
98 |
99 | ```
100 | docker build -t mcp/stripe .
101 | ```
102 |
103 | Run the following command in your terminal:
104 |
105 | ```bash
106 | docker run -p 3000:3000 -p 5173:5173 -v /var/run/docker.sock:/var/run/docker.sock mcp/inspector docker run --rm -i mcp/stripe --tools=all --api-key=YOUR_STRIPE_SECRET_KEY
107 |
108 | ```
109 |
110 | ### Instructions
111 |
112 | 1. Replace `YOUR_STRIPE_SECRET_KEY` with your actual Stripe API secret key.
113 | 2. Run the command to start the MCP Inspector.
114 | 3. Open the MCP Inspector UI in your browser and click Connect to start the MCP server.
115 | 4. You can see the list of tools you selected and test each tool individually.
116 |
```
--------------------------------------------------------------------------------
/tools/typescript/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe Agent Toolkit - TypeScript
2 |
3 | The Stripe Agent Toolkit enables popular agent frameworks including LangChain and Vercel's AI SDK to integrate with Stripe APIs through function calling. It also provides tooling to quickly integrate metered billing for prompt and completion token usage.
4 |
5 | ## Installation
6 |
7 | You don't need this source code unless you want to modify the package. If you just
8 | want to use the package run:
9 |
10 | ```
11 | npm install @stripe/agent-toolkit
12 | ```
13 |
14 | ### Requirements
15 |
16 | - Node 18+
17 |
18 | ## Usage
19 |
20 | The library needs to be configured with your account's secret key which is available in your [Stripe Dashboard][api-keys]. Additionally, `configuration` enables you to specify the types of actions that can be taken using the toolkit.
21 |
22 | ```typescript
23 | import {StripeAgentToolkit} from '@stripe/agent-toolkit/langchain';
24 |
25 | const stripeAgentToolkit = new StripeAgentToolkit({
26 | secretKey: process.env.STRIPE_SECRET_KEY!,
27 | configuration: {
28 | actions: {
29 | paymentLinks: {
30 | create: true,
31 | },
32 | },
33 | },
34 | });
35 | ```
36 |
37 | ### Tools
38 |
39 | The toolkit works with LangChain and Vercel's AI SDK and can be passed as a list of tools. For example:
40 |
41 | ```typescript
42 | import {AgentExecutor, createStructuredChatAgent} from 'langchain/agents';
43 |
44 | const tools = stripeAgentToolkit.getTools();
45 |
46 | const agent = await createStructuredChatAgent({
47 | llm,
48 | tools,
49 | prompt,
50 | });
51 |
52 | const agentExecutor = new AgentExecutor({
53 | agent,
54 | tools,
55 | });
56 | ```
57 |
58 | #### Context
59 |
60 | In some cases you will want to provide values that serve as defaults when making requests. Currently, the `account` context value enables you to make API calls for your [connected accounts](https://docs.stripe.com/connect/authentication).
61 |
62 | ```typescript
63 | const stripeAgentToolkit = new StripeAgentToolkit({
64 | secretKey: process.env.STRIPE_SECRET_KEY!,
65 | configuration: {
66 | context: {
67 | account: 'acct_123',
68 | },
69 | },
70 | });
71 | ```
72 |
73 | ### Metered billing
74 |
75 | For Vercel's AI SDK, you can use middleware to submit billing events for usage. All that is required is the customer ID and the input/output meters to bill.
76 |
77 | ```typescript
78 | import {StripeAgentToolkit} from '@stripe/agent-toolkit/ai-sdk';
79 | import {openai} from '@ai-sdk/openai';
80 | import {
81 | generateText,
82 | experimental_wrapLanguageModel as wrapLanguageModel,
83 | } from 'ai';
84 |
85 | const stripeAgentToolkit = new StripeAgentToolkit({
86 | secretKey: process.env.STRIPE_SECRET_KEY!,
87 | configuration: {
88 | actions: {
89 | paymentLinks: {
90 | create: true,
91 | },
92 | },
93 | },
94 | });
95 |
96 | const model = wrapLanguageModel({
97 | model: openai('gpt-4o'),
98 | middleware: stripeAgentToolkit.middleware({
99 | billing: {
100 | customer: 'cus_123',
101 | meters: {
102 | input: 'input_tokens',
103 | output: 'output_tokens',
104 | },
105 | },
106 | }),
107 | });
108 | ```
109 |
110 | This works with both `generateText` and `generateStream` from the Vercel AI SDK.
111 |
112 | ## Model Context Protocol
113 |
114 | The Stripe Agent Toolkit also supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.com/). See `/examples/modelcontextprotocol` for an example. The same configuration options are available, and the server can be run with all supported transports.
115 |
116 | ```typescript
117 | import {StripeAgentToolkit} from '@stripe/agent-toolkit/modelcontextprotocol';
118 | import {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
119 |
120 | const server = new StripeAgentToolkit({
121 | secretKey: process.env.STRIPE_SECRET_KEY!,
122 | configuration: {
123 | actions: {
124 | paymentLinks: {
125 | create: true,
126 | },
127 | products: {
128 | create: true,
129 | },
130 | prices: {
131 | create: true,
132 | },
133 | },
134 | },
135 | });
136 |
137 | async function main() {
138 | const transport = new StdioServerTransport();
139 | await server.connect(transport);
140 | console.error('Stripe MCP Server running on stdio');
141 | }
142 |
143 | main().catch((error) => {
144 | console.error('Fatal error in main():', error);
145 | process.exit(1);
146 | });
147 | ```
148 |
149 | [node-sdk]: https://github.com/stripe/stripe-node
150 | [api-keys]: https://dashboard.stripe.com/account/apikeys
151 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/examples/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # AI SDK Billing Wrapper Examples
2 |
3 | This directory contains examples demonstrating how to use the AI SDK Billing Wrapper to automatically track and report token usage to Stripe for billing purposes when using the Vercel AI SDK.
4 |
5 | ## Overview
6 |
7 | The AI SDK Billing Wrapper intercepts calls to language models and automatically sends usage data to Stripe's meter events API, enabling you to bill customers based on their AI token consumption without manually tracking usage.
8 |
9 | ## Setup
10 |
11 | 1. Install dependencies from the ai-sdk-billing-wrapper directory:
12 |
13 | ```bash
14 | cd llm/ai-sdk-billing-wrapper
15 | npm install
16 | ```
17 |
18 | 2. Set up environment variables in the examples directory:
19 |
20 | ```bash
21 | cd examples
22 | cp .env.example .env
23 | ```
24 |
25 | Then edit `.env` and add your credentials:
26 |
27 | ```bash
28 | # Required for all examples
29 | STRIPE_API_KEY=sk_test_...
30 | STRIPE_CUSTOMER_ID=cus_...
31 |
32 | # Provider-specific (only required for the provider you want to test)
33 | OPENAI_API_KEY=sk-...
34 | ANTHROPIC_API_KEY=sk-ant-...
35 | GOOGLE_GENERATIVE_AI_API_KEY=...
36 | ```
37 |
38 | ## Running examples
39 |
40 | Run examples from the examples directory using ts-node:
41 |
42 | ### OpenAI examples
43 |
44 | ```bash
45 | npx ts-node openai.ts
46 | ```
47 |
48 | Demonstrates:
49 | - Basic text generation
50 | - Streaming responses
51 | - System messages
52 | - Multi-turn conversations
53 | - Different GPT models (GPT-4o-mini, GPT-4)
54 | - Max tokens configuration
55 |
56 | ### Anthropic Claude examples
57 |
58 | ```bash
59 | npx ts-node anthropic.ts
60 | ```
61 |
62 | Demonstrates:
63 | - Basic text generation with Claude Sonnet
64 | - Streaming responses
65 | - System messages
66 | - Multi-turn conversations
67 | - Claude Haiku for faster responses
68 | - Max tokens configuration
69 |
70 | ### Google Gemini examples
71 |
72 | ```bash
73 | npx ts-node google.ts
74 | ```
75 |
76 | Demonstrates:
77 | - Basic text generation with Gemini
78 | - Streaming with Gemini Flash
79 | - System messages
80 | - Multi-turn conversations
81 | - Temperature control
82 |
83 | ## How it works
84 |
85 | The `meteredModel` wrapper automatically:
86 |
87 | 1. **Intercepts API Calls**: Wraps any AI SDK v2 language model
88 | 2. **Tracks Token Usage**: Captures input tokens, output tokens, and model information
89 | 3. **Reports to Stripe**: Sends meter events to Stripe after each generation
90 | 4. **Handles Streaming**: Works with both streaming and non-streaming responses
91 |
92 | ## Basic usage pattern
93 |
94 | ```typescript
95 | import { meteredModel } from '@stripe/ai-sdk-billing-wrapper';
96 | import { openai } from '@ai-sdk/openai';
97 | import { generateText } from 'ai';
98 |
99 | const model = meteredModel(
100 | openai('gpt-4o-mini'),
101 | process.env.STRIPE_API_KEY,
102 | 'cus_xxxxx'
103 | );
104 |
105 | const { text } = await generateText({
106 | model,
107 | prompt: 'Hello!',
108 | });
109 | ```
110 |
111 | ## Supported providers
112 |
113 | The wrapper works with any AI SDK provider that implements the v2 specification (`LanguageModelV2`):
114 |
115 | **Supported:**
116 | - OpenAI (`@ai-sdk/openai`)
117 | - Anthropic Claude (`@ai-sdk/anthropic`)
118 | - Google Gemini (`@ai-sdk/google`)
119 | - Azure OpenAI (via `@ai-sdk/openai`)
120 | - Amazon Bedrock (`@ai-sdk/amazon-bedrock`)
121 | - Together AI (via `createOpenAI`)
122 | - Any custom provider implementing `LanguageModelV2`
123 |
124 | **Not supported:**
125 | - Groq (`@ai-sdk/groq`) - uses v1 specification
126 | - Any provider using `LanguageModelV1`
127 |
128 | The wrapper enforces v2-only models at TypeScript compile time.
129 |
130 | ## Stripe meter events
131 |
132 | Each API call generates meter events sent to Stripe:
133 |
134 | ```javascript
135 | {
136 | event_name: 'token-billing-tokens',
137 | payload: {
138 | stripe_customer_id: 'cus_xxxxx',
139 | value: '100',
140 | model: 'openai/gpt-4o-mini',
141 | token_type: 'input'
142 | }
143 | }
144 | ```
145 |
146 | Metadata included:
147 | - Provider (e.g., "openai", "anthropic", "google")
148 | - Model ID (e.g., "gpt-4o-mini", "claude-sonnet-4")
149 | - Input tokens
150 | - Output tokens
151 |
152 | ## Error handling
153 |
154 | The wrapper handles errors gracefully:
155 |
156 | - **Invalid Customer ID**: Throws an error before making the API call
157 | - **Unsupported Models**: TypeScript prevents usage at compile time
158 | - **Stripe API Errors**: Logged but don't interrupt the AI generation
159 | - **Missing Tokens**: Handles responses without usage information
160 |
161 | ## Additional resources
162 |
163 | - [Stripe Meter Events Documentation](https://docs.stripe.com/api/billing/meter-event)
164 | - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing)
165 | - [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
166 | - [AI SDK Providers](https://sdk.vercel.ai/docs/providers)
167 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/examples/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe AI SDK Provider Examples
2 |
3 | This directory contains examples demonstrating how to use the Stripe AI SDK Provider to interact with various LLM models through Stripe's `llm.stripe.com` proxy.
4 |
5 | ## Overview
6 |
7 | The Stripe AI SDK Provider is a custom provider for the Vercel AI SDK that routes all requests through Stripe's LLM proxy, automatically tracking token usage for billing purposes.
8 |
9 | ## Setup
10 |
11 | 1. Install dependencies (from the ai-sdk-provider directory):
12 | ```bash
13 | cd llm/ai-sdk-provider
14 | npm install
15 | ```
16 |
17 | 2. **Set up environment variables** in the examples directory:
18 | ```bash
19 | cd examples
20 | cp .env.example .env
21 | ```
22 |
23 | Then edit `.env` and add your credentials:
24 | ```bash
25 | # Required: Your Stripe API key
26 | STRIPE_API_KEY=sk_test_...
27 |
28 | # Required: Your Stripe Customer ID
29 | STRIPE_CUSTOMER_ID=cus_...
30 | ```
31 |
32 | ## Running examples
33 |
34 | Each example file demonstrates different use cases. Run them from the examples directory:
35 |
36 | ### OpenAI models
37 | ```bash
38 | cd examples
39 | npx ts-node openai.ts
40 | ```
41 |
42 | Examples include:
43 | - Simple text generation
44 | - Streaming responses
45 | - Multi-turn conversations
46 | - Reasoning models (o3)
47 | - Tool calling
48 |
49 | ### Google Gemini models
50 | ```bash
51 | npx ts-node google.ts
52 | ```
53 |
54 | Examples include:
55 | - Text generation with Gemini 2.5 Pro
56 | - Streaming with Gemini Flash
57 | - Using Gemini Lite models
58 | - Custom headers
59 |
60 | ### Anthropic Claude models
61 | ```bash
62 | npx ts-node anthropic.ts
63 | ```
64 |
65 | Examples include:
66 | - Simple text generation
67 | - Streaming with Claude Opus
68 | - Claude Sonnet and Haiku models
69 | - Tool calling
70 | - Per-call customer ID override
71 |
72 | ## Supported models
73 |
74 | ### OpenAI
75 | - `openai/gpt-5`
76 | - `openai/gpt-5-mini`
77 | - `openai/gpt-5-nano`
78 | - `openai/gpt-4.1`
79 | - `openai/gpt-4.1-mini`
80 | - `openai/gpt-4.1-nano`
81 | - `openai/gpt-4o`
82 | - `openai/gpt-4o-mini`
83 | - `openai/o3`, `openai/o3-mini`, `openai/o3-pro`
84 | - `openai/o1`, `openai/o1-mini`, `openai/o1-pro`
85 |
86 | ### Google Gemini
87 | - `google/gemini-2.5-pro`
88 | - `google/gemini-2.5-flash`
89 | - `google/gemini-2.5-flash-lite`
90 | - `google/gemini-2.0-flash`
91 | - `google/gemini-2.0-flash-lite`
92 |
93 | ### Anthropic Claude
94 | - `anthropic/claude-opus-4-1`
95 | - `anthropic/claude-opus-4`
96 | - `anthropic/claude-sonnet-4`
97 | - `anthropic/claude-3-7-sonnet`
98 | - `anthropic/claude-3-5-haiku`
99 | - `anthropic/claude-3-haiku`
100 |
101 | ## Usage patterns
102 |
103 | ### Basic setup
104 |
105 | ```typescript
106 | import { createStripe } from '@stripe/ai-sdk/provider';
107 | import { generateText } from 'ai';
108 |
109 | const stripeLLM = createStripe({
110 | apiKey: process.env.STRIPE_API_KEY!,
111 | customerId: process.env.STRIPE_CUSTOMER_ID, // Optional default
112 | });
113 |
114 | const model = stripe('openai/gpt-5');
115 | ```
116 |
117 | ### Customer ID options
118 |
119 | You can specify the customer ID in three ways (in order of priority):
120 |
121 | 1. **Per-call override** (highest priority):
122 | ```typescript
123 | await generateText({
124 | model: stripe('openai/gpt-5'),
125 | prompt: 'Hello!',
126 | providerOptions: {
127 | stripe: {
128 | customerId: 'cus_override'
129 | }
130 | }
131 | });
132 | ```
133 |
134 | 2. **Model-level setting**:
135 | ```typescript
136 | const model = stripe('openai/gpt-5', {
137 | customerId: 'cus_model_level'
138 | });
139 | ```
140 |
141 | 3. **Provider-level default**:
142 | ```typescript
143 | const stripeLLM = createStripe({
144 | apiKey: '...',
145 | customerId: 'cus_default'
146 | });
147 | ```
148 |
149 | ### Streaming
150 |
151 | ```typescript
152 | import { streamText } from 'ai';
153 |
154 | const result = await streamText({
155 | model: stripe('google/gemini-2.5-flash'),
156 | prompt: 'Tell me a story',
157 | });
158 |
159 | for await (const chunk of result.textStream) {
160 | process.stdout.write(chunk);
161 | }
162 | ```
163 |
164 | ### Tool calling
165 |
166 | ```typescript
167 | const result = await generateText({
168 | model: stripe('anthropic/claude-sonnet-4'),
169 | prompt: 'What is the weather?',
170 | tools: {
171 | getWeather: {
172 | description: 'Get weather for a location',
173 | parameters: {
174 | type: 'object',
175 | properties: {
176 | location: { type: 'string' }
177 | },
178 | required: ['location']
179 | },
180 | execute: async ({ location }) => {
181 | return { temperature: 72, condition: 'Sunny' };
182 | }
183 | }
184 | }
185 | });
186 | ```
187 |
188 | ## How it works
189 |
190 | 1. All requests are routed to `https://llm.stripe.com/chat/completions`
191 | 2. Your Stripe API key is included as the `Authorization` header
192 | 3. The customer ID is included as the `X-Stripe-Customer-ID` header
193 | 4. Stripe automatically tracks token usage and bills the customer according to your Token Billing configuration
194 |
195 | ## Learn more
196 |
197 | - [Stripe Token Billing Documentation](https://stripe.com/docs)
198 | - [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
199 | - [AI SDK Provider Specification](https://github.com/vercel/ai/tree/main/packages/provider)
200 |
201 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe AI SDK - Provider and metering utilities for Vercel AI SDK
2 |
3 | The Stripe AI SDK provides comprehensive tools for integrating AI models with Stripe's billing infrastructure. This unified package includes both a custom Vercel AI SDK provider and metering utilities for tracking token usage across any AI SDK provider.
4 |
5 | ## Private preview access required
6 |
7 | The Stripe AI SDK is currently only available to organizations participating in the Billing for LLM Tokens Private Preview. If you do not have access and would like to request it, please visit:
8 |
9 | **[Request Access to Billing for LLM Tokens Private Preview](https://docs.stripe.com/billing/token-billing)**
10 |
11 | ## Overview
12 |
13 | This package contains two main components:
14 |
15 | ### **Provider** (`@stripe/ai-sdk/provider`)
16 |
17 | A custom Vercel AI SDK provider that routes requests through Stripe's LLM proxy at `llm.stripe.com`, enabling automatic usage tracking and billing integration.
18 |
19 | **Key Features:**
20 | - **Unified API**: Access OpenAI, Google Gemini, and Anthropic Claude through a single interface
21 | - **Automatic tracking**: Token usage is automatically reported to Stripe
22 | - **Built-in billing**: Seamlessly integrate AI costs into your Stripe billing workflow
23 | - **Customer attribution**: Automatically attribute usage to specific customers
24 |
25 | **Quick Start:**
26 | ```typescript
27 | import { createStripe } from '@stripe/ai-sdk/provider';
28 | import { generateText } from 'ai';
29 |
30 | const stripeLLM = createStripe({
31 | apiKey: process.env.STRIPE_API_KEY,
32 | customerId: 'cus_xxxxx',
33 | });
34 |
35 | const { text } = await generateText({
36 | model: stripe('openai/gpt-5'),
37 | prompt: 'What are the three primary colors?',
38 | });
39 | ```
40 |
41 | [→ Full Provider Documentation](./provider/README.md)
42 |
43 | ### **Meter** (`@stripe/ai-sdk/meter`)
44 |
45 | A wrapper utility that adds billing tracking to any Vercel AI SDK language model, allowing you to use your preferred provider while still tracking usage in Stripe.
46 |
47 | **Key Features:**
48 | - **Universal Compatibility**: Works with any AI SDK v2 provider
49 | - **Non-Intrusive**: Preserves all original model functionality
50 | - **Fire-and-Forget**: Billing events are sent asynchronously
51 | - **Automatic Metering**: Token consumption is automatically tracked
52 | - **Customer Attribution**: Attribute usage to specific customers
53 |
54 | **Quick Start:**
55 | ```typescript
56 | import { meteredModel } from '@stripe/ai-sdk/meter';
57 | import { openai } from '@ai-sdk/openai';
58 | import { generateText } from 'ai';
59 |
60 | const model = meteredModel(
61 | openai('gpt-4o-mini'),
62 | process.env.STRIPE_API_KEY,
63 | 'cus_xxxxx'
64 | );
65 |
66 | const { text } = await generateText({
67 | model,
68 | prompt: 'What are the three primary colors?',
69 | });
70 | ```
71 |
72 | [→ Full Meter Documentation](./meter/README.md)
73 |
74 | ## Installation
75 |
76 | ```bash
77 | npm install @stripe/ai-sdk
78 | ```
79 |
80 | ## Which should I use?
81 |
82 | ### Use the **Provider** when:
83 | - You want a unified interface to multiple AI providers
84 | - You prefer routing through Stripe's LLM proxy
85 | - You want automatic usage tracking without any wrapper code
86 | - You're building a new application
87 |
88 | ### Use the **Meter** when:
89 | - You need to use specific provider features or configurations
90 | - You want to keep your existing provider setup
91 | - You need direct access to the native provider APIs
92 | - You're integrating into an existing codebase
93 |
94 | ## Usage examples
95 |
96 | ### Provider example
97 |
98 | ```typescript
99 | import { createStripe } from '@stripe/ai-sdk/provider';
100 | import { streamText } from 'ai';
101 |
102 | const stripeLLM = createStripe({
103 | apiKey: process.env.STRIPE_API_KEY,
104 | customerId: 'cus_xxxxx',
105 | });
106 |
107 | // Works with any supported model
108 | const result = await streamText({
109 | model: stripeLLM('anthropic/claude-sonnet-4'),
110 | prompt: 'Write a short story about AI.',
111 | });
112 |
113 | for await (const chunk of result.textStream) {
114 | process.stdout.write(chunk);
115 | }
116 | ```
117 |
118 | ### Meter example
119 |
120 | ```typescript
121 | import { meteredModel } from '@stripe/ai-sdk/meter';
122 | import { anthropic } from '@ai-sdk/anthropic';
123 | import { streamText } from 'ai';
124 |
125 | const model = meteredModel(
126 | anthropic('claude-3-5-sonnet-20241022'),
127 | process.env.STRIPE_API_KEY,
128 | 'cus_xxxxx'
129 | );
130 |
131 | const result = await streamText({
132 | model,
133 | prompt: 'Write a short story about AI.',
134 | });
135 |
136 | for await (const chunk of result.textStream) {
137 | process.stdout.write(chunk);
138 | }
139 | ```
140 |
141 | ## Supported models
142 |
143 | ### Provider models
144 | The provider supports models from:
145 | - **OpenAI**: GPT-5, GPT-4.1, o3, o1, and more
146 | - **Google**: Gemini 2.5 Pro, Gemini 2.5 Flash, and more
147 | - **Anthropic**: Claude Opus 4, Claude Sonnet 4, Claude Haiku, and more
148 |
149 | ### Meter compatibility
150 | The meter works with any AI SDK v2 provider, including:
151 | - OpenAI (`@ai-sdk/openai`)
152 | - Anthropic (`@ai-sdk/anthropic`)
153 | - Google Gemini (`@ai-sdk/google`)
154 | - Azure OpenAI
155 | - Amazon Bedrock
156 | - And any custom v2 provider
157 |
158 | ## Token usage tracking
159 |
160 | Both components automatically report token usage to Stripe meter events:
161 |
162 | ```javascript
163 | {
164 | event_name: 'token-billing-tokens',
165 | payload: {
166 | stripe_customer_id: 'cus_xxxxx',
167 | value: '100',
168 | model: 'openai/gpt-4o-mini',
169 | token_type: 'input'
170 | }
171 | }
172 | ```
173 |
174 | ## Documentation
175 |
176 | - [Provider Documentation](./provider/README.md)
177 | - [Meter Documentation](./meter/README.md)
178 | - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing)
179 | - [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
180 |
181 | ## Examples
182 |
183 | - [Provider Examples](./provider/examples/)
184 | - [Meter Examples](./meter/examples/)
185 |
186 | ## License
187 |
188 | MIT
189 |
190 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | 
2 |
3 | # Stripe AI
4 |
5 | This repo is the one-stop shop for building AI-powered products and businesses on top of Stripe.
6 |
7 | It contains a collection of SDKs to help you integrate Stripe with LLMs and agent frameworks, including:
8 |
9 | * [`@stripe/agent-toolkit`](/tools/typescript) - for integrating Stripe APIs with popular agent frameworks through function calling—available in [Python](/tools/python) and [TypeScript](/tools/typescript).
10 | * [`@stripe/ai-sdk`](/llm/ai-sdk) - for integrating Stripe's billing infrastructure with Vercel's [`ai`](https://npm.im/ai) and [`@ai-sdk`](https://ai-sdk.dev/) libraries.
11 | * [`@stripe/token-meter`](/llm/token-meter) - for integrating Stripe's billing infrastructure with native SDKs from OpenAI, Anthropic, and Google Gemini, without any framework dependencies.
12 |
13 | ## Model Context Protocol (MCP)
14 |
15 | Stripe hosts a remote MCP server at `https://mcp.stripe.com`. This allows secure MCP client access via OAuth. View the docs [here](https://docs.stripe.com/mcp#remote).
16 |
17 | The Stripe Agent Toolkit also exposes tools in the [Model Context Protocol (MCP)](https://modelcontextprotocol.com/) format. Or, to run a local Stripe MCP server using npx, use the following command:
18 |
19 | ```sh
20 | npx -y @stripe/mcp --tools=all --api-key=YOUR_STRIPE_SECRET_KEY
21 | ```
22 |
23 | See [MCP](/tools/modelcontextprotocol) for more details.
24 |
25 | ## Agent toolkit
26 |
27 | Stripe's Agent Toolkit enables popular agent frameworks including OpenAI's Agent SDK, LangChain, CrewAI, and Vercel's AI SDK to integrate with Stripe APIs through function calling. The library is not exhaustive of the entire Stripe API. It includes support for Python and TypeScript, and is built directly on top of the Stripe [Python][python-sdk] and [Node][node-sdk] SDKs.
28 |
29 | Included below are basic instructions, but refer to [Python](/tools/python) and [TypeScript](/tools/typescript) packages for more information.
30 |
31 | ### Python
32 |
33 | #### Installation
34 |
35 | You don't need this source code unless you want to modify the package. If you just
36 | want to use the package run:
37 |
38 | ```sh
39 | pip install stripe-agent-toolkit
40 | ```
41 |
42 | ##### Requirements
43 |
44 | - Python 3.11+
45 |
46 | #### Usage
47 |
48 | The library needs to be configured with your account's secret key which is
49 | available in your [Stripe Dashboard][api-keys].
50 |
51 | ```python
52 | from stripe_agent_toolkit.openai.toolkit import StripeAgentToolkit
53 |
54 | stripe_agent_toolkit = StripeAgentToolkit(
55 | secret_key="sk_test_...",
56 | configuration={
57 | "actions": {
58 | "payment_links": {
59 | "create": True,
60 | },
61 | }
62 | },
63 | )
64 | ```
65 |
66 | The toolkit works with OpenAI's Agent SDK, LangChain, and CrewAI and can be passed as a list of tools. For example:
67 |
68 | ```python
69 | from agents import Agent
70 |
71 | stripe_agent = Agent(
72 | name="Stripe Agent",
73 | instructions="You are an expert at integrating with Stripe",
74 | tools=stripe_agent_toolkit.get_tools()
75 | )
76 | ```
77 |
78 | Examples for OpenAI's Agent SDK,LangChain, and CrewAI are included in [/examples](/tools/python/examples).
79 |
80 | ##### Context
81 |
82 | In some cases you will want to provide values that serve as defaults when making requests. Currently, the `account` context value enables you to make API calls for your [connected accounts](https://docs.stripe.com/connect/authentication).
83 |
84 | ```python
85 | stripe_agent_toolkit = StripeAgentToolkit(
86 | secret_key="sk_test_...",
87 | configuration={
88 | "context": {
89 | "account": "acct_123"
90 | }
91 | }
92 | )
93 | ```
94 |
95 | ### TypeScript
96 |
97 | #### Installation
98 |
99 | You don't need this source code unless you want to modify the package. If you just
100 | want to use the package run:
101 |
102 | ```sh
103 | npm install @stripe/agent-toolkit
104 | ```
105 |
106 | ##### Requirements
107 |
108 | - Node 18+
109 |
110 | #### Usage
111 |
112 | The library needs to be configured with your account's secret key which is available in your [Stripe Dashboard][api-keys]. Additionally, `configuration` enables you to specify the types of actions that can be taken using the toolkit.
113 |
114 | ```typescript
115 | import { StripeAgentToolkit } from "@stripe/agent-toolkit/langchain";
116 |
117 | const stripeAgentToolkit = new StripeAgentToolkit({
118 | secretKey: process.env.STRIPE_SECRET_KEY!,
119 | configuration: {
120 | actions: {
121 | paymentLinks: {
122 | create: true,
123 | },
124 | },
125 | },
126 | });
127 | ```
128 |
129 | ##### Tools
130 |
131 | The toolkit works with LangChain and Vercel's AI SDK and can be passed as a list of tools. For example:
132 |
133 | ```typescript
134 | import { AgentExecutor, createStructuredChatAgent } from "langchain/agents";
135 |
136 | const tools = stripeAgentToolkit.getTools();
137 |
138 | const agent = await createStructuredChatAgent({
139 | llm,
140 | tools,
141 | prompt,
142 | });
143 |
144 | const agentExecutor = new AgentExecutor({
145 | agent,
146 | tools,
147 | });
148 | ```
149 |
150 | ##### Context
151 |
152 | In some cases you will want to provide values that serve as defaults when making requests. Currently, the `account` context value enables you to make API calls for your [connected accounts](https://docs.stripe.com/connect/authentication).
153 |
154 | ```typescript
155 | const stripeAgentToolkit = new StripeAgentToolkit({
156 | secretKey: process.env.STRIPE_SECRET_KEY!,
157 | configuration: {
158 | context: {
159 | account: "acct_123",
160 | },
161 | },
162 | });
163 | ```
164 |
165 | ## Supported API methods
166 |
167 | See the [Stripe MCP](https://docs.stripe.com/mcp) docs for a list of supported methods.
168 |
169 | [python-sdk]: https://github.com/stripe/stripe-python
170 | [node-sdk]: https://github.com/stripe/stripe-node
171 | [api-keys]: https://dashboard.stripe.com/account/apikeys
172 |
173 | ## License
174 |
175 | [MIT](LICENSE)
```
--------------------------------------------------------------------------------
/tools/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Tools
2 |
3 | ## Model Context Protocol
4 |
5 | Stripe hosts a remote MCP server at `https://mcp.stripe.com`. This allows secure MCP client access via OAuth. View the docs [here](https://docs.stripe.com/mcp#remote).
6 |
7 | It can also be used to create autonomous agents.
8 |
9 | For a local MCP, see the [MCP](/modelcontextprotocol) package.
10 |
11 | ## Agent Toolkit
12 |
13 | The Stripe Agent Toolkit enables popular agent frameworks including Model Context Protocol (MCP), OpenAI's Agent SDK, LangChain, CrewAI, and Vercel's AI SDK to integrate with Stripe APIs through function calling. The
14 | library is not exhaustive of the entire Stripe API. It includes support for MCP, Python, and TypeScript and is built directly on top of the Stripe [Python][python-sdk] and [Node][node-sdk] SDKs.
15 |
16 | Included below are basic instructions, but refer to [Python](/tools/python), [TypeScript](/tools/typescript) packages for more information.
17 |
18 | ## Model Context Protocol
19 |
20 | The Stripe Agent Toolkit also exposes tools in the [Model Context Protocol (MCP)](https://modelcontextprotocol.com/) format. Or, to run a local Stripe MCP server using npx, use the following command:
21 |
22 | ```bash
23 | npx -y @stripe/mcp --tools=all --api-key=YOUR_STRIPE_SECRET_KEY
24 | ```
25 |
26 | ## Python
27 |
28 | ### Installation
29 |
30 | You don't need this source code unless you want to modify the package. If you just
31 | want to use the package run:
32 |
33 | ```sh
34 | pip install stripe-agent-toolkit
35 | ```
36 |
37 | #### Requirements
38 |
39 | - Python 3.11+
40 |
41 | ### Usage
42 |
43 | The library needs to be configured with your account's secret key which is
44 | available in your [Stripe Dashboard][api-keys].
45 |
46 | ```python
47 | from stripe_agent_toolkit.openai.toolkit import StripeAgentToolkit
48 |
49 | stripe_agent_toolkit = StripeAgentToolkit(
50 | secret_key="sk_test_...",
51 | configuration={
52 | "actions": {
53 | "payment_links": {
54 | "create": True,
55 | },
56 | }
57 | },
58 | )
59 | ```
60 |
61 | The toolkit works with OpenAI's Agent SDK, LangChain, and CrewAI and can be passed as a list of tools. For example:
62 |
63 | ```python
64 | from agents import Agent
65 |
66 | stripe_agent = Agent(
67 | name="Stripe Agent",
68 | instructions="You are an expert at integrating with Stripe",
69 | tools=stripe_agent_toolkit.get_tools()
70 | )
71 | ```
72 |
73 | Examples for OpenAI's Agent SDK,LangChain, and CrewAI are included in [/examples](/tools/python/examples).
74 |
75 | #### Context
76 |
77 | In some cases you will want to provide values that serve as defaults when making requests. Currently, the `account` context value enables you to make API calls for your [connected accounts](https://docs.stripe.com/connect/authentication).
78 |
79 | ```python
80 | stripe_agent_toolkit = StripeAgentToolkit(
81 | secret_key="sk_test_...",
82 | configuration={
83 | "context": {
84 | "account": "acct_123"
85 | }
86 | }
87 | )
88 | ```
89 |
90 | ## TypeScript
91 |
92 | ### Installation
93 |
94 | You don't need this source code unless you want to modify the package. If you just
95 | want to use the package run:
96 |
97 | ```
98 | npm install @stripe/agent-toolkit
99 | ```
100 |
101 | #### Requirements
102 |
103 | - Node 18+
104 |
105 | ### Usage
106 |
107 | The library needs to be configured with your account's secret key which is available in your [Stripe Dashboard][api-keys]. Additionally, `configuration` enables you to specify the types of actions that can be taken using the toolkit.
108 |
109 | ```typescript
110 | import { StripeAgentToolkit } from "@stripe/agent-toolkit/langchain";
111 |
112 | const stripeAgentToolkit = new StripeAgentToolkit({
113 | secretKey: process.env.STRIPE_SECRET_KEY!,
114 | configuration: {
115 | actions: {
116 | paymentLinks: {
117 | create: true,
118 | },
119 | },
120 | },
121 | });
122 | ```
123 |
124 | #### Tools
125 |
126 | The toolkit works with LangChain and Vercel's AI SDK and can be passed as a list of tools. For example:
127 |
128 | ```typescript
129 | import { AgentExecutor, createStructuredChatAgent } from "langchain/agents";
130 |
131 | const tools = stripeAgentToolkit.getTools();
132 |
133 | const agent = await createStructuredChatAgent({
134 | llm,
135 | tools,
136 | prompt,
137 | });
138 |
139 | const agentExecutor = new AgentExecutor({
140 | agent,
141 | tools,
142 | });
143 | ```
144 |
145 | #### Context
146 |
147 | In some cases you will want to provide values that serve as defaults when making requests. Currently, the `account` context value enables you to make API calls for your [connected accounts](https://docs.stripe.com/connect/authentication).
148 |
149 | ```typescript
150 | const stripeAgentToolkit = new StripeAgentToolkit({
151 | secretKey: process.env.STRIPE_SECRET_KEY!,
152 | configuration: {
153 | context: {
154 | account: "acct_123",
155 | },
156 | },
157 | });
158 | ```
159 |
160 | #### Metered billing
161 |
162 | For Vercel's AI SDK, you can use middleware to submit billing events for usage. All that is required is the customer ID and the input/output meters to bill.
163 |
164 | ```typescript
165 | import { StripeAgentToolkit } from "@stripe/agent-toolkit/ai-sdk";
166 | import { openai } from "@ai-sdk/openai";
167 | import {
168 | generateText,
169 | experimental_wrapLanguageModel as wrapLanguageModel,
170 | } from "ai";
171 |
172 | const stripeAgentToolkit = new StripeAgentToolkit({
173 | secretKey: process.env.STRIPE_SECRET_KEY!,
174 | configuration: {
175 | actions: {
176 | paymentLinks: {
177 | create: true,
178 | },
179 | },
180 | },
181 | });
182 |
183 | const model = wrapLanguageModel({
184 | model: openai("gpt-4o"),
185 | middleware: stripeAgentToolkit.middleware({
186 | billing: {
187 | customer: "cus_123",
188 | meters: {
189 | input: "input_tokens",
190 | output: "output_tokens",
191 | },
192 | },
193 | }),
194 | });
195 | ```
196 |
197 | ## Supported API methods
198 |
199 | See the [Stripe MCP](https://docs.stripe.com/mcp) docs for a list of supported methods.
200 |
201 | [python-sdk]: https://github.com/stripe/stripe-python
202 | [node-sdk]: https://github.com/stripe/stripe-node
203 | [api-keys]: https://dashboard.stripe.com/account/apikeys
204 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Metering utilities for Vercel AI SDK
2 |
3 | The Stripe AI SDK Meter enables automatic token usage tracking and billing for any Vercel AI SDK language model. This wrapper intercepts AI SDK calls and automatically reports usage to Stripe meter events, making it easy to bill customers for their AI consumption.
4 |
5 | > This is part of the [`@stripe/ai-sdk`](../README.md) package. See the main README for an overview of all available tools.
6 |
7 | ## Private preview access required
8 |
9 | The Stripe AI SDK is currently only available to organizations participating in the Billing for LLM Tokens Private Preview. If you don't have access and would like to request it, please visit:
10 |
11 | **[Request Access to Billing for LLM Tokens Private Preview](https://docs.stripe.com/billing/token-billing)**
12 |
13 | ## Why use the AI SDK Meter?
14 |
15 | - **Universal Compatibility**: Works with any AI SDK v2 provider (OpenAI, Anthropic, Google, and more)
16 | - **Automatic Usage Tracking**: Token consumption is automatically tracked and reported to Stripe
17 | - **Seamless Integration**: Simple wrapper function requires minimal code changes
18 | - **Customer Attribution**: Automatically attribute usage to specific customers for accurate billing
19 | - **Non-Intrusive**: Preserves all original model functionality while adding billing capabilities
20 | - **Fire-and-Forget**: Billing events are sent asynchronously without blocking API responses
21 |
22 | Learn more about Stripe's Token Billing and request access to the latest features from the [Stripe Documentation](https://docs.stripe.com/billing/token-billing).
23 |
24 | ## Installation
25 |
26 | ```bash
27 | npm install @stripe/ai-sdk
28 | ```
29 |
30 | ## Basic usage
31 |
32 | Wrap any AI SDK v2 language model with `meteredModel` to enable automatic usage tracking:
33 |
34 | ```typescript
35 | import { meteredModel } from '@stripe/ai-sdk/meter';
36 | import { openai } from '@ai-sdk/openai';
37 | import { generateText } from 'ai';
38 |
39 | const model = meteredModel(
40 | openai('gpt-4o-mini'),
41 | process.env.STRIPE_API_KEY,
42 | 'cus_xxxxx'
43 | );
44 |
45 | const { text } = await generateText({
46 | model,
47 | prompt: 'What are the three primary colors?',
48 | });
49 | ```
50 |
51 | ## API reference
52 |
53 | ### `meteredModel(model, stripeApiKey, stripeCustomerId)`
54 |
55 | Wraps a Vercel AI SDK language model to automatically report usage to Stripe meter events.
56 |
57 | **Parameters:**
58 | - `model` (LanguageModelV2): The AI SDK language model instance to wrap
59 | - `stripeApiKey` (string): Your Stripe API key
60 | - `stripeCustomerId` (string): The Stripe customer ID to attribute usage to
61 |
62 | **Returns:**
63 | The wrapped model with identical functionality plus automatic usage tracking.
64 |
65 | ## Supported providers
66 |
67 | The wrapper works with any AI SDK provider that implements the v2 specification (`LanguageModelV2`):
68 |
69 | **Example supported providers:**
70 | - OpenAI (`@ai-sdk/openai`)
71 | - Anthropic (`@ai-sdk/anthropic`)
72 | - Google Gemini (`@ai-sdk/google`)
73 | - Azure OpenAI (via `@ai-sdk/openai`)
74 | - Amazon Bedrock (`@ai-sdk/amazon-bedrock`)
75 | - Any custom provider implementing `LanguageModelV2`
76 |
77 | ## Examples
78 |
79 | ### Streaming responses
80 |
81 | ```typescript
82 | import { meteredModel } from '@stripe/ai-sdk/meter';
83 | import { anthropic } from '@ai-sdk/anthropic';
84 | import { streamText } from 'ai';
85 |
86 | const model = meteredModel(
87 | anthropic('claude-3-5-sonnet-20241022'),
88 | process.env.STRIPE_API_KEY,
89 | 'cus_xxxxx'
90 | );
91 |
92 | const result = streamText({
93 | model,
94 | prompt: 'Write a short story about AI.',
95 | });
96 |
97 | for await (const chunk of result.textStream) {
98 | process.stdout.write(chunk);
99 | }
100 | ```
101 |
102 | ### Multi-turn conversations
103 |
104 | ```typescript
105 | import { meteredModel } from '@stripe/ai-sdk/meter';
106 | import { google } from '@ai-sdk/google';
107 | import { generateText } from 'ai';
108 |
109 | const model = meteredModel(
110 | google('gemini-2.5-flash'),
111 | process.env.STRIPE_API_KEY,
112 | 'cus_xxxxx'
113 | );
114 |
115 | const result = await generateText({
116 | model,
117 | messages: [
118 | { role: 'user', content: 'What is the capital of France?' },
119 | { role: 'assistant', content: 'The capital of France is Paris.' },
120 | { role: 'user', content: 'What is its population?' },
121 | ],
122 | });
123 | ```
124 |
125 | ### Using different providers
126 |
127 | ```typescript
128 | import { meteredModel } from '@stripe/ai-sdk/meter';
129 | import { openai } from '@ai-sdk/openai';
130 | import { anthropic } from '@ai-sdk/anthropic';
131 | import { google } from '@ai-sdk/google';
132 |
133 | const STRIPE_API_KEY = process.env.STRIPE_API_KEY;
134 | const CUSTOMER_ID = 'cus_xxxxx';
135 |
136 | // OpenAI
137 | const gptModel = meteredModel(
138 | openai('gpt-4o-mini'),
139 | STRIPE_API_KEY,
140 | CUSTOMER_ID
141 | );
142 |
143 | // Anthropic
144 | const claudeModel = meteredModel(
145 | anthropic('claude-3-5-haiku-20241022'),
146 | STRIPE_API_KEY,
147 | CUSTOMER_ID
148 | );
149 |
150 | // Google
151 | const geminiModel = meteredModel(
152 | google('gemini-2.5-flash'),
153 | STRIPE_API_KEY,
154 | CUSTOMER_ID
155 | );
156 | ```
157 |
158 | ## How it works
159 |
160 | The wrapper intercepts calls to the underlying language model and:
161 |
162 | 1. **Forwards the Request**: Passes all parameters to the original model unchanged
163 | 2. **Captures Usage**: Extracts token usage information from the response
164 | 3. **Reports to Stripe**: Sends meter events to Stripe asynchronously
165 | 4. **Returns Response**: Returns the original response without modification
166 |
167 | For streaming responses, the wrapper collects usage information from the final stream chunk and reports it after the stream completes.
168 |
169 | ## Stripe meter events
170 |
171 | Each API call generates meter events sent to Stripe:
172 |
173 | **Input tokens event:**
174 | ```javascript
175 | {
176 | event_name: 'token-billing-tokens',
177 | payload: {
178 | stripe_customer_id: 'cus_xxxxx',
179 | value: '100',
180 | model: 'openai/gpt-4o-mini',
181 | token_type: 'input'
182 | }
183 | }
184 | ```
185 |
186 | **Output tokens event:**
187 | ```javascript
188 | {
189 | event_name: 'token-billing-tokens',
190 | payload: {
191 | stripe_customer_id: 'cus_xxxxx',
192 | value: '50',
193 | model: 'openai/gpt-4o-mini',
194 | token_type: 'output'
195 | }
196 | }
197 | ```
198 |
199 | ## Error handling
200 |
201 | The wrapper handles errors gracefully:
202 |
203 | - **Invalid Models**: TypeScript prevents usage of v1 models at compile time
204 | - **Missing Customer ID**: Throws an error immediately
205 | - **Stripe API Errors**: Logged to console but don't interrupt AI generation
206 | - **Missing Usage Data**: Handles responses without usage information
207 |
208 | ## Additional resources
209 |
210 | - [Stripe Meter Events Documentation](https://docs.stripe.com/api/billing/meter-event)
211 | - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing)
212 | - [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
213 | - [AI SDK Providers](https://sdk.vercel.ai/docs/providers)
214 | - [Example Applications](./examples/)
215 |
216 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe AI SDK Provider
2 |
3 | The Stripe AI SDK Provider enables seamless integration with leading AI models through Stripe's unified LLM proxy at `llm.stripe.com`. This custom provider for the Vercel AI SDK automatically tracks token usage and integrates with Stripe's billing system, making it easy to monetize AI features in your applications.
4 |
5 | > **Note:** This is part of the [`@stripe/ai-sdk`](../README.md) package. See the main README for an overview of all available tools.
6 |
7 | ## Private preview access required
8 |
9 | The Stripe AI SDK Provider is currently only available to organizations participating in the Billing for LLM Tokens Private Preview. If you do not have access and would like to request it, please visit:
10 |
11 | **[Request Access to Billing for LLM Tokens Private Preview](https://docs.stripe.com/billing/token-billing)**
12 |
13 | ## Why use Stripe AI SDK Provider?
14 |
15 | - **Automatic Usage Tracking**: Token consumption is automatically tracked and reported to Stripe for billing
16 | - **Multi-Model Support**: Access models from OpenAI, Google Gemini, and Anthropic Claude through a single API
17 | - **Built-in Billing**: Seamlessly integrate AI costs into your existing Stripe billing workflow
18 | - **Customer Attribution**: Automatically attribute usage to specific customers for accurate billing
19 | - **Production-Ready**: Enterprise-grade infrastructure with Stripe's reliability
20 | - **Transparent Costs**: Track and bill AI usage alongside your other Stripe products
21 |
22 | Learn more about Stripe's Token Billing in the [Stripe Documentation](https://docs.stripe.com/billing/token-billing).
23 |
24 | ## Setup
25 |
26 | The Stripe AI SDK Provider is available in the `@stripe/ai-sdk` package. You can install it with:
27 |
28 | ```bash
29 | npm install @stripe/ai-sdk
30 | ```
31 |
32 | ## Provider instance
33 |
34 | To create a Stripe provider instance, use the `createStripe` function:
35 |
36 | ```typescript
37 | import { createStripe } from '@stripe/ai-sdk/provider';
38 |
39 | const stripeLLM = createStripe({
40 | apiKey: process.env.STRIPE_API_KEY,
41 | customerId: 'cus_xxxxx', // Optional default customer ID
42 | });
43 | ```
44 |
45 | ### Configuration options
46 |
47 | - `apiKey` (required): Your Stripe API key from the [Stripe Dashboard](https://dashboard.stripe.com/apikeys)
48 | - `customerId` (optional): Default customer ID to attribute usage to
49 | - `baseURL` (optional): Custom base URL (defaults to `https://llm.stripe.com`)
50 | - `headers` (optional): Additional headers to include in requests
51 |
52 | ## Supported models
53 |
54 | The Stripe provider supports models from multiple providers through a unified interface. Specify models using the format `provider/model-name`:
55 |
56 | ### OpenAI models
57 |
58 | ```typescript
59 | const model = stripe('openai/gpt-5');
60 | const miniModel = stripe('openai/gpt-5-mini');
61 | const reasoningModel = stripe('openai/o3');
62 | ```
63 |
64 | **Available models:**
65 | - `openai/gpt-5`, `openai/gpt-5-mini`, `openai/gpt-5-nano`
66 | - `openai/gpt-4.1`, `openai/gpt-4.1-mini`, `openai/gpt-4.1-nano`
67 | - `openai/gpt-4o`, `openai/gpt-4o-mini`
68 | - `openai/o3`, `openai/o3-mini`, `openai/o3-pro`
69 | - `openai/o1`, `openai/o1-mini`, `openai/o1-pro`
70 |
71 | ### Google Gemini models
72 |
73 | ```typescript
74 | const model = stripe('google/gemini-2.5-pro');
75 | const fastModel = stripe('google/gemini-2.5-flash');
76 | ```
77 |
78 | **Available models:**
79 | - `google/gemini-2.5-pro`
80 | - `google/gemini-2.5-flash`, `google/gemini-2.5-flash-lite`
81 | - `google/gemini-2.0-flash`, `google/gemini-2.0-flash-lite`
82 |
83 | ### Anthropic Claude models
84 |
85 | ```typescript
86 | const model = stripe('anthropic/claude-sonnet-4');
87 | const capableModel = stripe('anthropic/claude-opus-4');
88 | ```
89 |
90 | **Available models:**
91 | - `anthropic/claude-opus-4`, `anthropic/claude-opus-4-1`
92 | - `anthropic/claude-sonnet-4`, `anthropic/claude-3-7-sonnet`
93 | - `anthropic/claude-3-5-haiku`, `anthropic/claude-3-haiku`
94 |
95 | ## Examples
96 |
97 | ### Generate text
98 |
99 | ```typescript
100 | import { createStripe } from '@stripe/ai-sdk/provider';
101 | import { generateText } from 'ai';
102 |
103 | const stripeLLM = createStripe({
104 | apiKey: process.env.STRIPE_API_KEY,
105 | customerId: 'cus_xxxxx',
106 | });
107 |
108 | const { text } = await generateText({
109 | model: stripe('openai/gpt-5'),
110 | prompt: 'What are the three primary colors?',
111 | });
112 |
113 | console.log(text);
114 | ```
115 |
116 | ### Stream text
117 |
118 | ```typescript
119 | import { createStripe } from '@stripe/ai-sdk/provider';
120 | import { streamText } from 'ai';
121 |
122 | const stripeLLM = createStripe({
123 | apiKey: process.env.STRIPE_API_KEY,
124 | customerId: 'cus_xxxxx',
125 | });
126 |
127 | const result = streamText({
128 | model: stripe('google/gemini-2.5-flash'),
129 | prompt: 'Write a short story about AI.',
130 | });
131 |
132 | for await (const chunk of result.textStream) {
133 | process.stdout.write(chunk);
134 | }
135 | ```
136 |
137 | ### Multi-turn conversations
138 |
139 | ```typescript
140 | import { createStripe } from '@stripe/ai-sdk/provider';
141 | import { generateText } from 'ai';
142 |
143 | const stripeLLM = createStripe({
144 | apiKey: process.env.STRIPE_API_KEY,
145 | customerId: 'cus_xxxxx',
146 | });
147 |
148 | const result = await generateText({
149 | model: stripe('openai/gpt-4.1'),
150 | messages: [
151 | { role: 'user', content: 'What is the capital of France?' },
152 | { role: 'assistant', content: 'The capital of France is Paris.' },
153 | { role: 'user', content: 'What is its population?' },
154 | ],
155 | });
156 |
157 | console.log(result.text);
158 | ```
159 |
160 | ## Customer ID management
161 |
162 | The Stripe provider offers flexible customer ID configuration to ensure accurate billing attribution. Customer IDs can be specified at three levels (in order of priority):
163 |
164 | ### Per-request setting (highest priority)
165 |
166 | ```typescript
167 | await generateText({
168 | model: stripe('openai/gpt-5'),
169 | prompt: 'Hello!',
170 | providerOptions: {
171 | stripe: {
172 | customerId: 'cus_request_specific',
173 | },
174 | },
175 | });
176 | ```
177 |
178 | ### Model-level setting
179 |
180 | ```typescript
181 | const model = stripe('openai/gpt-5', {
182 | customerId: 'cus_model_level',
183 | });
184 |
185 | await generateText({
186 | model,
187 | prompt: 'Hello!',
188 | });
189 | ```
190 |
191 | ### Provider-level setting
192 |
193 | ```typescript
194 | const stripeLLM = createStripe({
195 | apiKey: process.env.STRIPE_API_KEY,
196 | customerId: 'cus_provider_level',
197 | });
198 | ```
199 |
200 | ### Usage tracking
201 |
202 | Access token usage information after generation:
203 |
204 | ```typescript
205 | const result = await generateText({
206 | model: stripe('openai/gpt-5'),
207 | prompt: 'Hello!',
208 | });
209 |
210 | console.log(result.usage);
211 | // { inputTokens: 2, outputTokens: 10, totalTokens: 12 }
212 | ```
213 |
214 | ## Supported AI SDK features
215 |
216 | The Stripe provider supports the following AI SDK features:
217 |
218 | - **Text Generation**: Both streaming and non-streaming
219 | - **Multi-turn Conversations**: Complex conversation histories
220 | - **Streaming**: Real-time token streaming
221 | - **Temperature & Sampling**: All standard generation parameters
222 | - **Stop Sequences**: Custom stop sequence support
223 | - **Token Limits**: Max output tokens configuration
224 |
225 | ### Feature limitations
226 |
227 | - **Tool Calling**: Function calling and tool use aren't currently supported by the llm.stripe.com API
228 | - **Text Embeddings**: Embedding models aren't supported yet
229 | - **Image Generation**: Image models aren't supported yet
230 |
231 | ## Additional resources
232 |
233 | - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing)
234 | - [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)
235 | - [AI SDK Custom Providers Guide](https://sdk.vercel.ai/docs/providers/custom-providers)
236 | - [Example Applications](./examples/)
237 |
```
--------------------------------------------------------------------------------
/llm/token-meter/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Stripe Token Meter
2 |
3 | Generic token metering for native AI SDKs with automatic Stripe billing integration. Track and bill token usage from OpenAI, Anthropic, and Google Gemini without any framework dependencies.
4 |
5 | ## Private preview access required
6 |
7 | Stripe Billing for LLM Tokens is currently only available to organizations participating in the Billing for LLM Tokens Private Preview. If you do not have access and would like to request it, please visit:
8 |
9 | **[Request Access to Billing for LLM Tokens Private Preview](https://docs.stripe.com/billing/token-billing)**
10 |
11 | ## Why use Stripe Token Meter?
12 |
13 | - **Native SDK Support**: Works directly with native AI SDKs (OpenAI, Anthropic, Google)
14 | - **No Framework Required**: Direct integration without Vercel AI SDK or other frameworks
15 | - **Automatic Detection**: Automatically detects provider and response types
16 | - **Streaming Support**: Full support for streaming responses from all providers
17 | - **Fire-and-Forget**: Billing events are sent asynchronously without blocking
18 | - **Universal API**: Single interface works across all supported providers
19 |
20 | ## Installation
21 |
22 | ```bash
23 | npm install @stripe/token-meter
24 | ```
25 |
26 | ## Supported providers
27 |
28 | - **OpenAI**: Chat Completions, Responses API, Embeddings (streaming and non-streaming)
29 | - **Anthropic**: Messages API (streaming and non-streaming)
30 | - **Google Gemini**: GenerateContent API (streaming and non-streaming)
31 |
32 | ## Quick start
33 |
34 | ### OpenAI
35 |
36 | ```typescript
37 | import OpenAI from 'openai';
38 | import { createTokenMeter } from '@stripe/token-meter';
39 |
40 | const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
41 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
42 |
43 | // Non-streaming
44 | const response = await openai.chat.completions.create({
45 | model: 'gpt-4o-mini',
46 | messages: [{ role: 'user', content: 'Hello!' }],
47 | });
48 |
49 | meter.trackUsage(response, 'cus_xxxxx');
50 | ```
51 |
52 | ### Anthropic
53 |
54 | ```typescript
55 | import Anthropic from '@anthropic-ai/sdk';
56 | import { createTokenMeter } from '@stripe/token-meter';
57 |
58 | const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
59 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
60 |
61 | // Non-streaming
62 | const response = await anthropic.messages.create({
63 | model: 'claude-3-5-sonnet-20241022',
64 | max_tokens: 1024,
65 | messages: [{ role: 'user', content: 'Hello!' }],
66 | });
67 |
68 | meter.trackUsage(response, 'cus_xxxxx');
69 | ```
70 |
71 | ### Google Gemini
72 |
73 | ```typescript
74 | import { GoogleGenerativeAI } from '@google/generative-ai';
75 | import { createTokenMeter } from '@stripe/token-meter';
76 |
77 | const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
78 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
79 |
80 | const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });
81 | const response = await model.generateContent('Hello!');
82 |
83 | meter.trackUsage(response.response, 'cus_xxxxx');
84 | ```
85 |
86 | ## API reference
87 |
88 | ### `createTokenMeter(stripeApiKey, config?)`
89 |
90 | Creates a token meter instance for tracking usage.
91 |
92 | **Parameters:**
93 | - `stripeApiKey` (string): Your Stripe API key
94 | - `config` (optional): Configuration options
95 | - `meterEventName` (string): Custom meter event name (default: 'token-billing-tokens')
96 |
97 | **Returns:** TokenMeter instance
98 |
99 | ### `TokenMeter.trackUsage(response, customerId)`
100 |
101 | Tracks usage from a non-streaming response (fire-and-forget).
102 |
103 | **Parameters:**
104 | - `response`: The response object from OpenAI, Anthropic, or Google
105 | - `customerId` (string): Stripe customer ID to attribute usage to
106 |
107 | **Supported response types:**
108 | - `OpenAI.ChatCompletion`
109 | - `OpenAI.Responses.Response`
110 | - `OpenAI.CreateEmbeddingResponse`
111 | - `Anthropic.Messages.Message`
112 | - `GenerateContentResult` (Gemini)
113 |
114 | ### `TokenMeter.trackUsageStreamOpenAI(stream, customerId)`
115 |
116 | Wraps an OpenAI streaming response for usage tracking.
117 |
118 | **Parameters:**
119 | - `stream`: OpenAI stream (Chat Completions or Responses API)
120 | - `customerId` (string): Stripe customer ID
121 |
122 | **Returns:** The wrapped stream (can be consumed normally)
123 |
124 | **Important:** For OpenAI streaming, include `stream_options: { include_usage: true }` in your request.
125 |
126 | ### `TokenMeter.trackUsageStreamAnthropic(stream, customerId)`
127 |
128 | Wraps an Anthropic streaming response for usage tracking.
129 |
130 | **Parameters:**
131 | - `stream`: Anthropic message stream
132 | - `customerId` (string): Stripe customer ID
133 |
134 | **Returns:** The wrapped stream (can be consumed normally)
135 |
136 | ### `TokenMeter.trackUsageStreamGemini(stream, customerId, modelName)`
137 |
138 | Wraps a Google Gemini streaming response for usage tracking.
139 |
140 | **Parameters:**
141 | - `stream`: Gemini streaming result
142 | - `customerId` (string): Stripe customer ID
143 | - `modelName` (string): Model name (e.g., 'gemini-2.5-flash')
144 |
145 | **Returns:** The wrapped stream (can be consumed normally)
146 |
147 | ## Examples
148 |
149 | ### OpenAI streaming
150 |
151 | ```typescript
152 | import OpenAI from 'openai';
153 | import { createTokenMeter } from '@stripe/token-meter';
154 |
155 | const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
156 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
157 |
158 | const stream = await openai.chat.completions.create({
159 | model: 'gpt-4o-mini',
160 | messages: [{ role: 'user', content: 'Count to 5' }],
161 | stream: true,
162 | stream_options: { include_usage: true }, // Required for metering
163 | });
164 |
165 | const meteredStream = meter.trackUsageStreamOpenAI(stream, 'cus_xxxxx');
166 |
167 | for await (const chunk of meteredStream) {
168 | process.stdout.write(chunk.choices[0]?.delta?.content || '');
169 | }
170 | ```
171 |
172 | ### Anthropic streaming
173 |
174 | ```typescript
175 | import Anthropic from '@anthropic-ai/sdk';
176 | import { createTokenMeter } from '@stripe/token-meter';
177 |
178 | const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
179 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
180 |
181 | const stream = await anthropic.messages.create({
182 | model: 'claude-3-5-sonnet-20241022',
183 | max_tokens: 1024,
184 | messages: [{ role: 'user', content: 'Count to 5' }],
185 | stream: true,
186 | });
187 |
188 | const meteredStream = meter.trackUsageStreamAnthropic(stream, 'cus_xxxxx');
189 |
190 | for await (const event of meteredStream) {
191 | if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
192 | process.stdout.write(event.delta.text);
193 | }
194 | }
195 | ```
196 |
197 | ### Google Gemini streaming
198 |
199 | ```typescript
200 | import { GoogleGenerativeAI } from '@google/generative-ai';
201 | import { createTokenMeter } from '@stripe/token-meter';
202 |
203 | const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
204 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
205 |
206 | const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });
207 | const result = await model.generateContentStream('Count to 5');
208 |
209 | const meteredStream = meter.trackUsageStreamGemini(
210 | result,
211 | 'cus_xxxxx',
212 | 'gemini-2.5-flash'
213 | );
214 |
215 | for await (const chunk of meteredStream.stream) {
216 | process.stdout.write(chunk.text());
217 | }
218 | ```
219 |
220 | ### OpenAI Responses API
221 |
222 | ```typescript
223 | import OpenAI from 'openai';
224 | import { createTokenMeter } from '@stripe/token-meter';
225 |
226 | const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
227 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
228 |
229 | const response = await openai.responses.create({
230 | model: 'gpt-4o-mini',
231 | input: 'What is 2+2?',
232 | instructions: 'You are a helpful math assistant.',
233 | });
234 |
235 | meter.trackUsage(response, 'cus_xxxxx');
236 | console.log('Output:', response.output);
237 | ```
238 |
239 | ### OpenAI embeddings
240 |
241 | ```typescript
242 | import OpenAI from 'openai';
243 | import { createTokenMeter } from '@stripe/token-meter';
244 |
245 | const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
246 | const meter = createTokenMeter(process.env.STRIPE_API_KEY);
247 |
248 | const response = await openai.embeddings.create({
249 | model: 'text-embedding-3-small',
250 | input: 'Hello, world!',
251 | });
252 |
253 | meter.trackUsage(response, 'cus_xxxxx');
254 | console.log('Embedding dimensions:', response.data[0].embedding.length);
255 | ```
256 |
257 | ## How it works
258 |
259 | The token meter:
260 |
261 | 1. **Detects Provider**: Automatically identifies the AI provider from the response
262 | 2. **Extracts Usage**: Pulls token counts from the response object
263 | 3. **Reports to Stripe**: Sends meter events asynchronously to Stripe
264 | 4. **Non-Blocking**: Never interrupts your application flow
265 |
266 | For streaming responses, the meter wraps the stream and reports usage after the stream completes.
267 |
268 | ## Stripe meter events
269 |
270 | Each API call generates meter events sent to Stripe:
271 |
272 | **Input tokens event:**
273 | ```javascript
274 | {
275 | event_name: 'token-billing-tokens',
276 | payload: {
277 | stripe_customer_id: 'cus_xxxxx',
278 | value: '100',
279 | model: 'openai/gpt-4o-mini',
280 | token_type: 'input'
281 | }
282 | }
283 | ```
284 |
285 | **Output tokens event:**
286 | ```javascript
287 | {
288 | event_name: 'token-billing-tokens',
289 | payload: {
290 | stripe_customer_id: 'cus_xxxxx',
291 | value: '50',
292 | model: 'openai/gpt-4o-mini',
293 | token_type: 'output'
294 | }
295 | }
296 | ```
297 |
298 | ## Error handling
299 |
300 | The token meter handles errors gracefully:
301 |
302 | - **Stripe API Errors**: Logged to console but don't interrupt your application
303 | - **Missing Usage Data**: Handles responses without usage information
304 | - **Invalid Provider**: Logs a warning for unrecognized providers
305 |
306 | ## TypeScript support
307 |
308 | Full TypeScript support with type definitions for all providers:
309 |
310 | ```typescript
311 | import type { TokenMeter, SupportedResponse, SupportedStream } from '@stripe/token-meter';
312 | ```
313 |
314 | ## Comparison with AI SDK Meter
315 |
316 | ### Use Token Meter when
317 | - You're using native SDKs (OpenAI, Anthropic, Google) directly
318 | - You don't want to depend on Vercel AI SDK
319 | - You need maximum control over API parameters
320 | - You're working with embeddings or specialized APIs
321 |
322 | ### Use AI SDK Meter when
323 | - You're already using Vercel AI SDK
324 | - You want a unified interface across providers
325 | - You need AI SDK-specific features (tool calling abstractions, etc.)
326 | - You prefer the AI SDK's streaming abstractions
327 |
328 | ## Additional resources
329 |
330 | - [Stripe Meter Events Documentation](https://docs.stripe.com/api/billing/meter-event)
331 | - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing)
332 | - [OpenAI API Documentation](https://platform.openai.com/docs/api-reference)
333 | - [Anthropic API Documentation](https://docs.anthropic.com/claude/reference)
334 | - [Google Gemini API Documentation](https://ai.google.dev/docs)
335 | - [Example Applications](./examples/)
336 |
337 | ## License
338 |
339 | MIT
340 |
341 |
```
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
```markdown
1 | # Security Policy
2 |
3 | ### Reporting a vulnerability
4 |
5 | Please do not open GitHub issues or pull requests - this makes the problem immediately visible to everyone, including malicious actors.
6 |
7 | Security issues in this open-source project can be safely reported to Stripe's [Vulnerability Disclosure and Reward Program](https://stripe.com/docs/security/stripe#disclosure-and-reward-program).
8 | Stripe's security team will triage your report and respond according to its impact on Stripe users and systems.
9 |
```
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
```markdown
1 | # Contributing
2 |
3 | Contributions of any kind are welcome! If you've found a bug or have a feature request, please feel free to [open an issue](/issues).
4 |
5 | <!-- We will try and respond to your issue or pull request within a week. -->
6 |
7 | To make changes yourself, follow these steps:
8 |
9 | 1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository and [clone](https://help.github.com/articles/cloning-a-repository/) it locally.
10 | <!-- 1. TODO add install step(s), e.g. "Run `npm install`" -->
11 | <!-- 1. TODO add build step(s), e.g. "Build the library using `npm run build`" -->
12 | 2. Make your changes
13 | <!-- 1. TODO add test step(s), e.g. "Test your changes with `npm test`" -->
14 | 3. Submit a [pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
15 |
16 | ## Contributor License Agreement ([CLA](https://en.wikipedia.org/wiki/Contributor_License_Agreement))
17 |
18 | Once you have submitted a pull request, sign the CLA by clicking on the badge in the comment from [@CLAassistant](https://github.com/CLAassistant).
19 |
20 | <img width="910" alt="image" src="https://user-images.githubusercontent.com/62121649/198740836-70aeb322-5755-49fc-af55-93c8e8a39058.png">
21 |
22 | <br />
23 | Thanks for contributing to Stripe! :sparkles:
24 |
```
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
```markdown
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to make participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies within all project spaces, and it also applies when
49 | an individual is representing the project or its community in public spaces.
50 | Examples of representing a project or community include using an official
51 | project e-mail address, posting via an official social media account, or acting
52 | as an appointed representative at an online or offline event. Representation of
53 | a project may be further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at [email protected]. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
```
--------------------------------------------------------------------------------
/tools/python/examples/langchain/__init__.py:
--------------------------------------------------------------------------------
```python
1 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/__init__.py:
--------------------------------------------------------------------------------
```python
1 |
```
--------------------------------------------------------------------------------
/tools/python/tests/__init__.py:
--------------------------------------------------------------------------------
```python
1 |
```
--------------------------------------------------------------------------------
/tools/typescript/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
```yaml
1 | packages:
2 | - '.'
3 | - 'examples/*'
4 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/ai-sdk/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import StripeAgentToolkit from './toolkit';
2 | export {StripeAgentToolkit};
3 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/langchain/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import StripeAgentToolkit from './toolkit';
2 | export {StripeAgentToolkit};
3 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/openai/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import StripeAgentToolkit from './toolkit';
2 | export {StripeAgentToolkit};
3 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/strands/__init__.py:
--------------------------------------------------------------------------------
```python
1 | """Stripe Agent Toolkit for Strands."""
2 |
3 | from .toolkit import StripeAgentToolkit
4 |
5 | __all__ = ["StripeAgentToolkit"]
6 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/modelcontextprotocol/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import StripeAgentToolkit from './toolkit';
2 | import {registerPaidTool} from './register-paid-tool';
3 | export {StripeAgentToolkit, registerPaidTool};
4 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/ai-sdk/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "include": ["index.ts"],
7 | "exclude": ["node_modules", "dist"]
8 | }
9 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/langchain/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "include": ["index.ts"],
7 | "exclude": ["node_modules", "dist"]
8 | }
9 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/openai/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "include": ["index.ts"],
7 | "exclude": ["node_modules", "dist"]
8 | }
9 |
```
--------------------------------------------------------------------------------
/gemini-extension.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "stripe",
3 | "version": "0.1.0",
4 | "mcpServers": {
5 | "stripe": {
6 | "httpUrl": "https://mcp.stripe.com",
7 | "oauth": {
8 | "enabled": true
9 | }
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "recommendations": [
3 | "EditorConfig.editorconfig", // default
4 | "ms-python.python", // intellisense
5 | "ms-python.flake8", // linting
6 | "charliermarsh.ruff" // formatting
7 | ]
8 | }
9 |
```
--------------------------------------------------------------------------------
/llm/token-meter/types.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Type definitions for token-billing
3 | * Re-exports shared types for backward compatibility
4 | */
5 |
6 | export type {TokenUsage, UsageEvent, MeterConfig, Provider} from './meter-event-types';
7 |
8 |
```
--------------------------------------------------------------------------------
/llm/token-meter/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Main entry point for token-billing
2 |
3 | export * from './types';
4 | export {createTokenMeter} from './token-meter';
5 | export type {TokenMeter, SupportedResponse, SupportedStream} from './token-meter';
6 |
7 |
```
--------------------------------------------------------------------------------
/tools/python/requirements.txt:
--------------------------------------------------------------------------------
```
1 | twine
2 | crewai==1.4.1
3 | crewai-tools==1.4.1
4 | flake8
5 | langchain==1.0.4
6 | langchain-openai==1.0.2
7 | mypy==1.18.2
8 | pydantic>=2.12.4
9 | pyright==1.1.407
10 | python-dotenv==1.2.1
11 | ruff==0.14.4
12 | stripe==13.2.0
13 | openai==2.7.1
14 | openai-agents==0.5.0
15 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/src/imageGenerator.ts:
--------------------------------------------------------------------------------
```typescript
1 | // @ts-ignore
2 | import emojiFromText from 'emoji-from-text';
3 |
4 | export function generateImage(description: string) {
5 | const emoji = emojiFromText(description);
6 | try {
7 | return emoji[0].match.emoji.char;
8 | } catch (e) {
9 | return '⚠️ (Error generating image)';
10 | }
11 | }
12 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/jest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type {Config} from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'node',
6 | roots: ['<rootDir>/src'],
7 | testMatch: ['**/test/**/*.ts?(x)'],
8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9 | };
10 |
11 | export default config;
12 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/examples/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "noEmit": true
6 | },
7 | "ts-node": {
8 | "transpileOnly": true,
9 | "compilerOptions": {
10 | "module": "commonjs"
11 | }
12 | },
13 | "include": ["./**/*.ts"],
14 | "exclude": ["node_modules", "dist"]
15 | }
16 |
17 |
```
--------------------------------------------------------------------------------
/tools/typescript/jest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type {Config} from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'node',
6 | roots: ['<rootDir>/src'],
7 | testMatch: ['**/test/**/*.ts?(x)'],
8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9 | moduleNameMapper: {
10 | '^@/(.*)$': '<rootDir>/src/$1',
11 | },
12 | };
13 |
14 | export default config;
15 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "Node16",
5 | "moduleResolution": "Node16",
6 | "outDir": "./dist",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true
12 | },
13 | "include": ["src/**/*"],
14 | "exclude": ["node_modules"]
15 | }
16 |
```
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
```yaml
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Stripe support
4 | url: https://support.stripe.com/
5 | about: |
6 | Please only file issues here that you believe represent actual bugs or feature requests for the Stripe Agent Tools library.
7 |
8 | If you're having general trouble with your Stripe integration, please reach out to support.
9 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/tsconfig.build.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "types": ["node"]
6 | },
7 | "include": [
8 | "*.ts"
9 | ],
10 | "exclude": [
11 | "node_modules",
12 | "dist",
13 | "tests",
14 | "examples",
15 | "coverage",
16 | "**/*.test.ts",
17 | "**/*.spec.ts",
18 | "jest.config.ts",
19 | "tsup.config.ts"
20 | ]
21 | }
22 |
23 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/customer_support/env.py:
--------------------------------------------------------------------------------
```python
1 | from os import getenv
2 |
3 | from dotenv import load_dotenv
4 |
5 | # Load the environment
6 | load_dotenv()
7 |
8 |
9 | def ensure(name: str) -> str:
10 | var = getenv(name)
11 | if not var:
12 | raise ValueError(f"Missing '{name}' environment variable")
13 | return var
14 |
15 |
16 | def get_or(name: str, default: str) -> str:
17 | var = getenv(name)
18 | if not var:
19 | return default
20 | return var
21 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Stripe AI SDK Provider
3 | * Custom provider for Vercel AI SDK that integrates with Stripe's llm.stripe.com proxy
4 | */
5 |
6 | export {createStripe, stripe, type StripeProvider} from './stripe-provider';
7 | export {StripeLanguageModel, StripeProviderAccessError} from './stripe-language-model';
8 | export type {
9 | StripeLanguageModelSettings,
10 | StripeProviderConfig,
11 | StripeProviderOptions,
12 | } from './types';
13 |
14 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | # syntax=docker/dockerfile:1
2 | # check=experimental=all
3 |
4 | FROM node:22-alpine@sha256:9bef0ef1e268f60627da9ba7d7605e8831d5b56ad07487d24d1aa386336d1944
5 | RUN npm install -g typescript pnpm
6 | RUN addgroup -S group && adduser -S user -G group
7 | WORKDIR /app
8 | COPY . .
9 | RUN --mount=type=cache,target=/root/.local \
10 | pnpm install --frozen-lockfile && pnpm run build
11 |
12 | USER user
13 | ENTRYPOINT ["node", "/app/dist/index.js"]
14 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/openai/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "stripe-agent-toolkit-examples-openai",
3 | "version": "0.1.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "MIT",
11 | "dependencies": {
12 | "dotenv": "^16.4.5",
13 | "openai": "^4.86.1",
14 | "@stripe/agent-toolkit": "workspace:*"
15 | },
16 | "devDependencies": {
17 | "@types/node": "^22.7.4"
18 | }
19 | }
20 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/ai-sdk/tool.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {tool} from 'ai';
2 | import {z} from 'zod';
3 | import StripeAPI from '../shared/api';
4 |
5 | export default function StripeTool(
6 | stripeAPI: StripeAPI,
7 | method: string,
8 | description: string,
9 | schema: z.ZodObject<any, any, any, any, {[x: string]: any}>
10 | ) {
11 | return tool({
12 | description,
13 | inputSchema: schema,
14 | execute: (arg: z.output<typeof schema>) => {
15 | return stripeAPI.run(method, arg);
16 | },
17 | });
18 | }
19 |
```
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "editor.formatOnSave": true,
3 | "python.defaultInterpreterPath": "./venv/bin/python",
4 | "[python]": {
5 | "editor.defaultFormatter": "charliermarsh.ruff",
6 | "editor.codeActionsOnSave": {
7 | "source.organizeImports": "never"
8 | }
9 | },
10 | "[typescript]": {
11 | "editor.defaultFormatter": "esbenp.prettier-vscode"
12 | },
13 | "[json]": {
14 | "editor.defaultFormatter": "esbenp.prettier-vscode"
15 | },
16 | "ruff.lint.enable": false
17 | }
18 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/ai-sdk/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "stripe-agent-toolkit-examples-ai-sdk",
3 | "version": "0.1.0",
4 | "description": "",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1"
7 | },
8 | "author": "",
9 | "license": "MIT",
10 | "dependencies": {
11 | "@ai-sdk/openai": "^2.0.58",
12 | "@stripe/agent-toolkit": "workspace:*",
13 | "ai": "^5.0.89",
14 | "dotenv": "^16.4.5",
15 | "zod": "^3.25.76"
16 | },
17 | "devDependencies": {
18 | "@types/node": "^22.7.4"
19 | }
20 | }
21 |
```
--------------------------------------------------------------------------------
/tools/modelcontextprotocol/server.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
3 | "name": "com.stripe/mcp",
4 | "description": "MCP server integrating with Stripe - tools for customers, products, payments, and more.",
5 | "repository": {
6 | "url": "https://github.com/stripe/ai",
7 | "source": "github"
8 | },
9 | "version": "0.2.4",
10 | "remotes": [
11 | {
12 | "type": "streamable-http",
13 | "url": "https://mcp.stripe.com"
14 | }
15 | ]
16 | }
17 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/customer_support/pyproject.toml:
--------------------------------------------------------------------------------
```toml
1 | [project]
2 | name = "email-agent"
3 | version = "0.1.0"
4 | description = "An automated email support agent that uses AI to respond to customer support emails"
5 | requires-python = ">=3.9"
6 | dependencies = [
7 | "python-dotenv>=1.2.1",
8 | "imaplib2==3.6",
9 | "python-decouple==3.8",
10 | "openai-agents==0.5.0",
11 | "stripe-agent-toolkit>=0.6.2",
12 | "stripe>=13.2.0",
13 | "urllib3<3",
14 | "markdown==3.7"
15 | ]
16 |
17 | [tool.hatch.metadata]
18 | allow-direct-references = true
19 |
```
--------------------------------------------------------------------------------
/tools/typescript/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Default",
4 | "compilerOptions": {
5 | "outDir": "./dist",
6 | "target": "es2022",
7 | "moduleDetection": "force",
8 | "esModuleInterop": true,
9 | "skipLibCheck": true,
10 | "strict": true,
11 | "module": "NodeNext",
12 | "baseUrl": ".",
13 | "paths": {
14 | "@/*": [
15 | "src/*"
16 | ]
17 | }
18 | },
19 | "include": [
20 | "**/*.ts"
21 | ],
22 | "exclude": [
23 | "node_modules",
24 | "examples"
25 | ]
26 | }
```
--------------------------------------------------------------------------------
/tools/typescript/examples/langchain/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "stripe-agent-toolkit-examples-langchain",
3 | "version": "0.1.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "MIT",
11 | "dependencies": {
12 | "@langchain/core": "^0.3.6",
13 | "@langchain/openai": "^0.3.5",
14 | "@stripe/agent-toolkit": "workspace:*",
15 | "dotenv": "^16.4.5",
16 | "langchain": "^0.3.2"
17 | },
18 | "devDependencies": {
19 | "@types/node": "^22.7.4"
20 | }
21 | }
22 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/types.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Type definitions for AI SDK metering
3 | */
4 |
5 | import type {Provider} from './meter-event-types';
6 |
7 | /**
8 | * Configuration options for AI SDK metering
9 | */
10 | export interface AIMeterConfig {
11 | /**
12 | * Stripe API key
13 | */
14 | stripeApiKey: string;
15 |
16 | /**
17 | * Stripe customer ID for meter events
18 | */
19 | stripeCustomerId: string;
20 | }
21 |
22 | /**
23 | * Usage information extracted from AI SDK responses
24 | */
25 | export interface AIUsageInfo {
26 | provider: Provider;
27 | model: string;
28 | inputTokens: number;
29 | outputTokens: number;
30 | }
31 |
32 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/biome.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3 | "vcs": {
4 | "enabled": false,
5 | "clientKind": "git",
6 | "useIgnoreFile": false
7 | },
8 | "files": {
9 | "ignoreUnknown": false,
10 | "ignore": ["worker-configuration.d.ts"]
11 | },
12 | "formatter": {
13 | "enabled": true,
14 | "indentStyle": "tab"
15 | },
16 | "organizeImports": {
17 | "enabled": true
18 | },
19 | "linter": {
20 | "enabled": true,
21 | "rules": {
22 | "recommended": true
23 | }
24 | },
25 | "javascript": {
26 | "formatter": {
27 | "quoteStyle": "double"
28 | }
29 | }
30 | }
31 |
```
--------------------------------------------------------------------------------
/llm/token-meter/jest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type {Config} from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'node',
6 | roots: ['<rootDir>/tests'],
7 | testMatch: ['**/*.test.ts'],
8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9 | modulePaths: ['<rootDir>/node_modules'],
10 | collectCoverageFrom: [
11 | '<rootDir>/*.ts',
12 | '<rootDir>/utils/**/*.ts',
13 | '!<rootDir>/*.d.ts',
14 | '!<rootDir>/node_modules/**',
15 | ],
16 | coverageDirectory: '<rootDir>/coverage',
17 | verbose: true,
18 | rootDir: '.',
19 | };
20 |
21 | export default config;
22 |
23 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "es2021",
4 | "lib": [
5 | "es2021"
6 | ],
7 | "jsx": "react-jsx",
8 | "module": "es2022",
9 | "moduleResolution": "Bundler",
10 | "resolveJsonModule": true,
11 | "allowJs": true,
12 | "checkJs": false,
13 | "noEmit": true,
14 | "isolatedModules": true,
15 | "allowSyntheticDefaultImports": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "allowImportingTsExtensions": true,
18 | "strict": true,
19 | "skipLibCheck": true,
20 | "types": []
21 | },
22 | "include": [
23 | "worker-configuration.d.ts",
24 | "src/**/*.ts"
25 | ]
26 | }
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/examples/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "lib": ["ES2022"],
7 | "outDir": "./dist",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "resolveJsonModule": true,
13 | "types": ["node"],
14 | "noEmit": true
15 | },
16 | "ts-node": {
17 | "transpileOnly": true,
18 | "compilerOptions": {
19 | "module": "commonjs",
20 | "moduleResolution": "node"
21 | }
22 | },
23 | "include": ["./**/*.ts"],
24 | "exclude": ["node_modules", "dist"]
25 | }
26 |
27 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/invoiceItems/prompts.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {createInvoiceItemPrompt} from '@/shared/invoiceItems/createInvoiceItem';
2 |
3 | describe('createInvoiceItemPrompt', () => {
4 | it('should return the correct prompt when no customer is specified', () => {
5 | const prompt = createInvoiceItemPrompt({});
6 | expect(prompt).toContain('- customer (str)');
7 | });
8 |
9 | it('should return the correct prompt when a customer is specified', () => {
10 | const prompt = createInvoiceItemPrompt({customer: 'cus_123'});
11 | expect(prompt).toContain('context: cus_123');
12 | expect(prompt).not.toContain('- customer (str)');
13 | });
14 | });
15 |
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/customer_support/repl.py:
--------------------------------------------------------------------------------
```python
1 | import asyncio
2 |
3 | from agents import ItemHelpers, TResponseInputItem
4 |
5 | import support_agent
6 |
7 |
8 | async def main():
9 | """Simple REPL for testing your support agent"""
10 | input_items: list[TResponseInputItem] = []
11 | while True:
12 | user_input = input("Enter your message: ")
13 | input_items.append({"content": user_input, "role": "user"})
14 | result = await support_agent.run(input_items)
15 | output = ItemHelpers.text_message_outputs(result.new_items)
16 | print(f"Assistant: {output}")
17 | input_items = result.to_input_list()
18 |
19 |
20 | if __name__ == "__main__":
21 | asyncio.run(main())
22 |
```
--------------------------------------------------------------------------------
/llm/token-meter/tsconfig.build.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./dist",
6 | "rootDir": ".",
7 | "declaration": true,
8 | "declarationMap": true,
9 | "sourceMap": true
10 | },
11 | "include": [
12 | "index.ts",
13 | "token-meter.ts",
14 | "meter-event-logging.ts",
15 | "meter-event-types.ts",
16 | "types.ts",
17 | "utils/**/*.ts"
18 | ],
19 | "exclude": [
20 | "node_modules",
21 | "dist",
22 | "coverage",
23 | "tests",
24 | "examples",
25 | "**/*.test.ts",
26 | "**/*.spec.ts"
27 | ]
28 | }
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "target": "ES2022",
5 | "module": "CommonJS",
6 | "moduleResolution": "Node",
7 | "lib": ["ES2022"],
8 | "outDir": "dist",
9 | "strict": true,
10 | "esModuleInterop": true,
11 | "skipLibCheck": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "declarationMap": true,
16 | "sourceMap": true,
17 | "isolatedModules": true,
18 | "types": ["node", "jest"]
19 | },
20 | "include": [
21 | "*.ts",
22 | "tests/**/*.ts"
23 | ],
24 | "exclude": [
25 | "node_modules",
26 | "dist",
27 | "examples",
28 | "coverage"
29 | ]
30 | }
31 |
32 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/balance/parameters.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {retrieveBalanceParameters} from '@/shared/balance/retrieveBalance';
2 |
3 | describe('retrieveBalanceParameters', () => {
4 | it('should return the correct parameters if no context', () => {
5 | const parameters = retrieveBalanceParameters({});
6 |
7 | const fields = Object.keys(parameters.shape);
8 | expect(fields).toEqual([]);
9 | expect(fields.length).toBe(0);
10 | });
11 |
12 | it('should return the correct parameters if customer is specified', () => {
13 | const parameters = retrieveBalanceParameters({customer: 'cus_123'});
14 |
15 | const fields = Object.keys(parameters.shape);
16 | expect(fields).toEqual([]);
17 | expect(fields.length).toBe(0);
18 | });
19 | });
20 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/crewai/tool.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | This tool allows agents to interact with the Stripe API.
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | from typing import Any, Optional, Type
8 | from pydantic import BaseModel
9 |
10 | from crewai.tools import BaseTool
11 |
12 | from ..api import StripeAPI
13 |
14 |
15 | class StripeTool(BaseTool):
16 | """Tool for interacting with the Stripe API."""
17 |
18 | stripe_api: StripeAPI
19 | method: str
20 | name: str = ""
21 | description: str = ""
22 | args_schema: Optional[Type[BaseModel]] = None
23 |
24 | def _run(
25 | self,
26 | *args: Any,
27 | **kwargs: Any,
28 | ) -> str:
29 | """Use the Stripe API to run an operation."""
30 | return self.stripe_api.run(self.method, *args, **kwargs)
31 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/langchain/tool.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | This tool allows agents to interact with the Stripe API.
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | from typing import Any, Optional, Type
8 | from pydantic import BaseModel
9 |
10 | from langchain.tools import BaseTool
11 |
12 | from ..api import StripeAPI
13 |
14 |
15 | class StripeTool(BaseTool):
16 | """Tool for interacting with the Stripe API."""
17 |
18 | stripe_api: StripeAPI
19 | method: str
20 | name: str = ""
21 | description: str = ""
22 | args_schema: Optional[Type[BaseModel]] = None
23 |
24 | def _run(
25 | self,
26 | *args: Any,
27 | **kwargs: Any,
28 | ) -> str:
29 | """Use the Stripe API to run an operation."""
30 | return self.stripe_api.run(self.method, *args, **kwargs)
31 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/refunds/parameters.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {createRefundParameters} from '@/shared/refunds/createRefund';
2 |
3 | describe('createRefundParameters', () => {
4 | it('should return the correct parameters if no context', () => {
5 | const parameters = createRefundParameters({});
6 |
7 | const fields = Object.keys(parameters.shape);
8 | expect(fields).toEqual(['payment_intent', 'amount']);
9 | expect(fields.length).toBe(2);
10 | });
11 |
12 | it('should return the correct parameters if customer is specified', () => {
13 | const parameters = createRefundParameters({customer: 'cus_123'});
14 |
15 | const fields = Object.keys(parameters.shape);
16 | expect(fields).toEqual(['payment_intent', 'amount']);
17 | expect(fields.length).toBe(2);
18 | });
19 | });
20 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/meter-event-types.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Shared type definitions for metering
3 | */
4 |
5 | /**
6 | * Token usage information
7 | */
8 | export interface TokenUsage {
9 | inputTokens: number;
10 | outputTokens: number;
11 | }
12 |
13 | /**
14 | * Usage event data that gets logged to Stripe
15 | */
16 | export interface UsageEvent {
17 | model: string;
18 | provider: string;
19 | usage: TokenUsage;
20 | stripeCustomerId: string;
21 | }
22 |
23 | /**
24 | * Configuration options for Stripe integration
25 | */
26 | export interface MeterConfig {}
27 |
28 | /**
29 | * Provider identifier - any string representing the AI provider
30 | * Common values: 'openai', 'anthropic', 'google', 'azure', 'bedrock', etc.
31 | * The provider name is normalized to lowercase from the model's provider string.
32 | */
33 | export type Provider = string;
34 |
35 |
```
--------------------------------------------------------------------------------
/llm/token-meter/meter-event-types.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Shared type definitions for metering
3 | */
4 |
5 | /**
6 | * Token usage information
7 | */
8 | export interface TokenUsage {
9 | inputTokens: number;
10 | outputTokens: number;
11 | }
12 |
13 | /**
14 | * Usage event data that gets logged to Stripe
15 | */
16 | export interface UsageEvent {
17 | model: string;
18 | provider: string;
19 | usage: TokenUsage;
20 | stripeCustomerId: string;
21 | }
22 |
23 | /**
24 | * Configuration options for Stripe integration
25 | */
26 | export interface MeterConfig {}
27 |
28 | /**
29 | * Provider identifier - any string representing the AI provider
30 | * Common values: 'openai', 'anthropic', 'google', 'azure', 'bedrock', etc.
31 | * The provider name is normalized to lowercase from the model's provider string.
32 | */
33 | export type Provider = string;
34 |
35 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/paymentIntents/parameters.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {listPaymentIntentsParameters} from '@/shared/paymentIntents/listPaymentIntents';
2 |
3 | describe('listPaymentIntentsParameters', () => {
4 | it('should return the correct parameters if no context', () => {
5 | const parameters = listPaymentIntentsParameters({});
6 |
7 | const fields = Object.keys(parameters.shape);
8 | expect(fields).toEqual(['customer', 'limit']);
9 | expect(fields.length).toBe(2);
10 | });
11 |
12 | it('should return the correct parameters if customer is specified', () => {
13 | const parameters = listPaymentIntentsParameters({customer: 'cus_123'});
14 |
15 | const fields = Object.keys(parameters.shape);
16 | expect(fields).toEqual(['limit']);
17 | expect(fields.length).toBe(1);
18 | });
19 | });
20 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/paymentLinks/parameters.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {createPaymentLinkParameters} from '@/shared/paymentLinks/createPaymentLink';
2 |
3 | describe('createPaymentLinkParameters', () => {
4 | it('should return the correct parameters if no context', () => {
5 | const parameters = createPaymentLinkParameters({});
6 |
7 | const fields = Object.keys(parameters.shape);
8 | expect(fields).toEqual(['price', 'quantity', 'redirect_url']);
9 | expect(fields.length).toBe(3);
10 | });
11 |
12 | it('should return the correct parameters if customer is specified', () => {
13 | const parameters = createPaymentLinkParameters({customer: 'cus_123'});
14 |
15 | const fields = Object.keys(parameters.shape);
16 | expect(fields).toEqual(['price', 'quantity', 'redirect_url']);
17 | });
18 | });
19 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/meter/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "target": "ES2022",
5 | "module": "NodeNext",
6 | "moduleResolution": "NodeNext",
7 | "lib": ["ES2022"],
8 | "outDir": "./dist",
9 | "rootDir": ".",
10 | "strict": true,
11 | "esModuleInterop": true,
12 | "skipLibCheck": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "resolveJsonModule": true,
15 | "declaration": true,
16 | "declarationMap": true,
17 | "sourceMap": true,
18 | "isolatedModules": true,
19 | "types": ["jest", "node"],
20 | "baseUrl": ".",
21 | "paths": {
22 | "*": ["node_modules/*"]
23 | }
24 | },
25 | "include": [
26 | "**/*.ts"
27 | ],
28 | "exclude": [
29 | "node_modules",
30 | "dist",
31 | "coverage"
32 | ]
33 | }
34 |
35 |
```
--------------------------------------------------------------------------------
/llm/token-meter/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "target": "ES2022",
5 | "module": "NodeNext",
6 | "moduleResolution": "NodeNext",
7 | "lib": ["ES2022"],
8 | "outDir": "./dist",
9 | "rootDir": ".",
10 | "strict": true,
11 | "esModuleInterop": true,
12 | "skipLibCheck": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "resolveJsonModule": true,
15 | "declaration": true,
16 | "declarationMap": true,
17 | "sourceMap": true,
18 | "isolatedModules": true,
19 | "types": ["jest", "node"],
20 | "baseUrl": ".",
21 | "paths": {
22 | "*": ["node_modules/*"]
23 | }
24 | },
25 | "include": [
26 | "**/*.ts"
27 | ],
28 | "exclude": [
29 | "node_modules",
30 | "dist",
31 | "coverage"
32 | ]
33 | }
34 |
35 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/jest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type {Config} from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'node',
6 | roots: ['<rootDir>/provider/tests', '<rootDir>/meter/tests'],
7 | testMatch: ['**/*.test.ts'],
8 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9 | modulePaths: ['<rootDir>/node_modules'],
10 | collectCoverageFrom: [
11 | '<rootDir>/provider/**/*.ts',
12 | '<rootDir>/meter/**/*.ts',
13 | '!<rootDir>/**/*.d.ts',
14 | '!<rootDir>/node_modules/**',
15 | '!<rootDir>/**/tests/**',
16 | '!<rootDir>/**/examples/**',
17 | ],
18 | coverageDirectory: '<rootDir>/coverage',
19 | verbose: true,
20 | rootDir: '.',
21 | globals: {
22 | 'ts-jest': {
23 | isolatedModules: true,
24 | },
25 | },
26 | };
27 |
28 | export default config;
29 |
30 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/invoiceItems/parameters.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {createInvoiceItemParameters} from '@/shared/invoiceItems/createInvoiceItem';
2 |
3 | describe('createInvoiceItemParameters', () => {
4 | it('should return the correct parameters if no context', () => {
5 | const parameters = createInvoiceItemParameters({});
6 |
7 | const fields = Object.keys(parameters.shape);
8 | expect(fields).toEqual(['customer', 'price', 'invoice']);
9 | expect(fields.length).toBe(3);
10 | });
11 |
12 | it('should return the correct parameters if customer is specified', () => {
13 | const parameters = createInvoiceItemParameters({customer: 'cus_123'});
14 |
15 | const fields = Object.keys(parameters.shape);
16 | expect(fields).toEqual(['price', 'invoice']);
17 | expect(fields.length).toBe(2);
18 | });
19 | });
20 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/documentation/parameters.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {searchDocumentationParameters} from '@/shared/documentation/searchDocumentation';
2 |
3 | describe('searchDocumentationParameters', () => {
4 | it('should return the correct parameters if no context', () => {
5 | const parameters = searchDocumentationParameters({});
6 |
7 | const fields = Object.keys(parameters.shape);
8 | expect(fields).toEqual(['question', 'language']);
9 | expect(fields.length).toBe(2);
10 | });
11 |
12 | it('should return the correct parameters if customer is specified', () => {
13 | const parameters = searchDocumentationParameters({customer: 'cus_123'});
14 |
15 | const fields = Object.keys(parameters.shape);
16 | expect(fields).toEqual(['question', 'language']);
17 | expect(fields.length).toBe(2);
18 | });
19 | });
20 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/paymentIntents/prompts.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {listPaymentIntentsPrompt} from '@/shared/paymentIntents/listPaymentIntents';
2 |
3 | describe('listPaymentIntentsPrompt', () => {
4 | it('should return the correct prompt', () => {
5 | const prompt = listPaymentIntentsPrompt();
6 | expect(prompt).toContain('customer');
7 | });
8 |
9 | it('should return the correct prompt when no customer is specified', () => {
10 | const prompt = listPaymentIntentsPrompt({});
11 | expect(prompt).toContain('- customer (str, optional)');
12 | });
13 |
14 | it('should return the correct prompt when a customer is specified', () => {
15 | const prompt = listPaymentIntentsPrompt({customer: 'cus_123'});
16 | expect(prompt).toContain('context: cus_123');
17 | expect(prompt).not.toContain('- customer (str, optional)');
18 | });
19 | });
20 |
```
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "request": "launch",
10 | "name": "Jest Current File",
11 | "runtimeExecutable": "sh",
12 | "program": "${workspaceFolder}/typescript/node_modules/.bin/jest",
13 | "args": [
14 | "${relativeFile}",
15 | "--config",
16 | "${workspaceFolder}/typescript/jest.config.ts"
17 | ],
18 | "console": "integratedTerminal",
19 | "internalConsoleOptions": "openOnFirstSessionStart"
20 | }
21 | ]
22 | }
```
--------------------------------------------------------------------------------
/tools/typescript/tsup.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {defineConfig} from 'tsup';
2 |
3 | export default defineConfig([
4 | {
5 | entry: ['src/langchain/index.ts'],
6 | outDir: 'langchain',
7 | format: ['cjs', 'esm'],
8 | dts: true,
9 | sourcemap: true,
10 | },
11 | {
12 | entry: ['src/ai-sdk/index.ts'],
13 | outDir: 'ai-sdk',
14 | format: ['cjs', 'esm'],
15 | dts: true,
16 | sourcemap: true,
17 | },
18 | {
19 | entry: ['src/modelcontextprotocol/index.ts'],
20 | outDir: 'modelcontextprotocol',
21 | format: ['cjs', 'esm'],
22 | dts: true,
23 | sourcemap: true,
24 | },
25 | {
26 | entry: ['src/openai/index.ts'],
27 | outDir: 'openai',
28 | format: ['cjs', 'esm'],
29 | dts: true,
30 | sourcemap: true,
31 | },
32 | {
33 | entry: ['src/cloudflare/index.ts'],
34 | outDir: 'cloudflare',
35 | format: ['cjs', 'esm'],
36 | dts: true,
37 | sourcemap: true,
38 | external: ['cloudflare:workers'],
39 | },
40 | ]);
41 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "target": "ES2022",
5 | "module": "CommonJS",
6 | "moduleResolution": "Node",
7 | "lib": [
8 | "ES2022"
9 | ],
10 | "outDir": "dist",
11 | "strict": true,
12 | "esModuleInterop": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "resolveJsonModule": true,
16 | "declaration": true,
17 | "declarationMap": true,
18 | "sourceMap": true,
19 | "isolatedModules": true,
20 | "types": [
21 | "node",
22 | "jest"
23 | ]
24 | },
25 | "include": [
26 | "provider/**/*.ts",
27 | "meter/**/*.ts"
28 | ],
29 | "exclude": [
30 | "node_modules",
31 | "dist",
32 | "provider/examples",
33 | "meter/examples",
34 | "coverage"
35 | ]
36 | }
```
--------------------------------------------------------------------------------
/tools/python/examples/openai/web_search/main.py:
--------------------------------------------------------------------------------
```python
1 | import asyncio
2 | import os
3 |
4 | from dotenv import load_dotenv
5 | load_dotenv()
6 |
7 | from agents import Agent, Runner, WebSearchTool
8 | from stripe_agent_toolkit.openai.toolkit import StripeAgentToolkit
9 |
10 | stripe_agent_toolkit = StripeAgentToolkit(
11 | secret_key=os.getenv("STRIPE_SECRET_KEY"),
12 | configuration={},
13 | )
14 |
15 | research_agent = Agent(
16 | name="Research Agent",
17 | instructions="You are an expert at research.",
18 | tools=[WebSearchTool()],
19 | hooks=stripe_agent_toolkit.billing_hook(
20 | type="outcome",
21 | customer=os.getenv("STRIPE_CUSTOMER_ID"),
22 | meter=os.getenv("STRIPE_METER"),
23 | ),
24 | )
25 |
26 | async def main():
27 | result = await Runner.run(
28 | research_agent,
29 | "search the web for 'global gdp' and give me the latest data.",
30 | )
31 | print(result.final_output)
32 |
33 | if __name__ == "__main__":
34 | asyncio.run(main())
35 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/cloudflare/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "remote-mcp-server",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "deploy": "wrangler deploy",
7 | "dev": "wrangler dev",
8 | "format": "biome format --write",
9 | "lint:fix": "biome lint --fix",
10 | "start": "wrangler dev",
11 | "cf-typegen": "wrangler types"
12 | },
13 | "devDependencies": {
14 | "@biomejs/biome": "1.9.4",
15 | "@cloudflare/workers-types": "^4.20250515.0",
16 | "typescript": "^5.8.3",
17 | "workers-mcp": "0.1.0-3",
18 | "wrangler": "^4.15.2"
19 | },
20 | "dependencies": {
21 | "@cloudflare/workers-oauth-provider": "^0.0.5",
22 | "@modelcontextprotocol/sdk": "^1.17.1",
23 | "@stripe/agent-toolkit": "workspace:*",
24 | "@types/node": "^22.15.18",
25 | "add": "^2.0.6",
26 | "agents": "^0.0.84",
27 | "dotenv": "^16.5.0",
28 | "emoji-from-text": "^1.1.13",
29 | "hono": "^4.10.3",
30 | "stripe": "^18.1.0",
31 | "zod": "^3.25.76"
32 | },
33 | "pnpm": {}
34 | }
35 |
```
--------------------------------------------------------------------------------
/tools/python/examples/strands/main.py:
--------------------------------------------------------------------------------
```python
1 | import os
2 | from dotenv import load_dotenv
3 |
4 | from strands import Agent
5 | from stripe_agent_toolkit.strands.toolkit import StripeAgentToolkit
6 |
7 | load_dotenv()
8 |
9 | # Initialize the Stripe Agent Toolkit
10 | stripe_agent_toolkit = StripeAgentToolkit(
11 | secret_key=os.getenv("STRIPE_SECRET_KEY"),
12 | configuration={
13 | "actions": {
14 | "payment_links": {
15 | "create": True,
16 | },
17 | "products": {
18 | "create": True,
19 | },
20 | "prices": {
21 | "create": True,
22 | },
23 | }
24 | },
25 | )
26 |
27 | # Get the Stripe tools
28 | tools = stripe_agent_toolkit.get_tools()
29 |
30 | # Create agent with Stripe tools
31 | agent = Agent(
32 | tools=tools
33 | )
34 |
35 | # Test the agent
36 | response = agent("""
37 | Create a payment link for a new product called 'test' with a price
38 | of $100. Come up with a funny description about buy bots,
39 | maybe a haiku.
40 | """)
41 |
42 | print(response)
43 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/openai/hooks.py:
--------------------------------------------------------------------------------
```python
1 | from typing import Any
2 | from agents import AgentHooks, RunContextWrapper, Agent, Tool
3 | from ..api import StripeAPI
4 |
5 | class BillingHooks(AgentHooks):
6 | def __init__(self, stripe: StripeAPI, type: str, customer: str, meter: str = None, meters: dict[str, str] = None):
7 | self.type = type
8 | self.stripe = stripe
9 | self.customer = customer
10 | self.meter = meter
11 | self.meters = meters
12 |
13 | async def on_end(self, context: RunContextWrapper, agent: Agent, output: Any) -> None:
14 | if self.type == "outcome":
15 | self.stripe.create_meter_event(self.meter, self.customer)
16 |
17 | if self.type == "token":
18 | if self.meters["input"]:
19 | self.stripe.create_meter_event(self.meters["input"], self.customer, context.usage.input_tokens)
20 | if self.meters["output"]:
21 | self.stripe.create_meter_event(self.meters["output"], self.customer, context.usage.output_tokens)
22 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/langchain/tool.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {z} from 'zod';
2 | import {StructuredTool} from '@langchain/core/tools';
3 | import {CallbackManagerForToolRun} from '@langchain/core/callbacks/manager';
4 | import {RunnableConfig} from '@langchain/core/runnables';
5 | import StripeAPI from '../shared/api';
6 |
7 | class StripeTool extends StructuredTool {
8 | stripeAPI: StripeAPI;
9 |
10 | method: string;
11 |
12 | name: string;
13 |
14 | description: string;
15 |
16 | schema: z.ZodObject<any, any, any, any>;
17 |
18 | constructor(
19 | StripeAPI: StripeAPI,
20 | method: string,
21 | description: string,
22 | schema: z.ZodObject<any, any, any, any, {[x: string]: any}>
23 | ) {
24 | super();
25 |
26 | this.stripeAPI = StripeAPI;
27 | this.method = method;
28 | this.name = method;
29 | this.description = description;
30 | this.schema = schema;
31 | }
32 |
33 | _call(
34 | arg: z.output<typeof this.schema>,
35 | _runManager?: CallbackManagerForToolRun,
36 | _parentConfig?: RunnableConfig
37 | ): Promise<any> {
38 | return this.stripeAPI.run(this.method, arg);
39 | }
40 | }
41 |
42 | export default StripeTool;
43 |
```
--------------------------------------------------------------------------------
/tools/python/pyproject.toml:
--------------------------------------------------------------------------------
```toml
1 | [project]
2 | name = "stripe-agent-toolkit"
3 | version = "0.6.2"
4 | description = "Stripe Agent Toolkit"
5 | readme = "README.md"
6 | license = {file = "LICENSE"}
7 | authors = [
8 | {name = "Stripe", email = "[email protected]"}
9 | ]
10 | keywords = ["stripe", "api", "payments"]
11 |
12 | [project.urls]
13 | "Bug Tracker" = "https://github.com/stripe/ai/issues"
14 | "Source Code" = "https://github.com/stripe/ai"
15 |
16 | [tool.setuptools.packages.find]
17 | include = ["stripe_agent_toolkit*"]
18 | exclude = ["tests*", "examples*"]
19 |
20 | [tool.ruff]
21 | # same as our black config
22 | line-length = 79
23 | extend-exclude = ["build"]
24 |
25 | [tool.ruff.format]
26 | # currently the default value, but opt-out in the future
27 | docstring-code-format = false
28 |
29 | [tool.pyright]
30 | include = [
31 | "*",
32 | ]
33 | exclude = ["build", "**/__pycache__"]
34 | reportMissingTypeArgument = true
35 | reportUnnecessaryCast = true
36 | reportUnnecessaryComparison = true
37 | reportUnnecessaryContains = true
38 | reportUnnecessaryIsInstance = true
39 | reportPrivateImportUsage = true
40 | reportUnnecessaryTypeIgnoreComment = true
41 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/langchain/toolkit.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {BaseToolkit} from '@langchain/core/tools';
2 | import StripeTool from './tool';
3 | import StripeAPI from '../shared/api';
4 | import tools from '../shared/tools';
5 | import {isToolAllowed, type Configuration} from '../shared/configuration';
6 |
7 | class StripeAgentToolkit implements BaseToolkit {
8 | private _stripe: StripeAPI;
9 |
10 | tools: StripeTool[];
11 |
12 | constructor({
13 | secretKey,
14 | configuration,
15 | }: {
16 | secretKey: string;
17 | configuration: Configuration;
18 | }) {
19 | this._stripe = new StripeAPI(secretKey, configuration.context);
20 |
21 | const context = configuration.context || {};
22 | const filteredTools = tools(context).filter((tool) =>
23 | isToolAllowed(tool, configuration)
24 | );
25 |
26 | this.tools = filteredTools.map(
27 | (tool) =>
28 | new StripeTool(
29 | this._stripe,
30 | tool.method,
31 | tool.description,
32 | tool.inputSchema
33 | )
34 | );
35 | }
36 |
37 | getTools(): StripeTool[] {
38 | return this.tools;
39 | }
40 | }
41 |
42 | export default StripeAgentToolkit;
43 |
```
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
```yaml
1 | name: Feature request
2 | description: Suggest an idea for this library
3 | labels: ["feature-request"]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | Thanks for taking the time to fill out this feature request!
9 | - type: textarea
10 | id: problem
11 | attributes:
12 | label: Is your feature request related to a problem? Please describe.
13 | description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
14 | - type: textarea
15 | id: solution
16 | attributes:
17 | label: Describe the solution you'd like
18 | description: A clear and concise description of what you want to happen.
19 | - type: textarea
20 | id: alternatives
21 | attributes:
22 | label: Describe alternatives you've considered
23 | description: A clear and concise description of any alternative solutions or features you've considered.
24 | - type: textarea
25 | id: context
26 | attributes:
27 | label: Additional context
28 | description: Add any other context about the feature request here.
29 |
```
--------------------------------------------------------------------------------
/.github/workflows/npm_release_shared.yml:
--------------------------------------------------------------------------------
```yaml
1 | name: NPM Release
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | working_directory:
7 | description: 'Package to release'
8 | required: true
9 | type: choice
10 | options:
11 | - './tools/typescript'
12 | - './tools/modelcontextprotocol'
13 | - './llm/ai-sdk'
14 | - './llm/token-meter'
15 |
16 | jobs:
17 | npm-release:
18 | runs-on: ubuntu-latest
19 | defaults:
20 | run:
21 | working-directory: ${{ inputs.working_directory }}
22 | permissions:
23 | contents: read
24 | id-token: write
25 | steps:
26 | - uses: actions/checkout@v4
27 |
28 | - name: pnpm
29 | uses: pnpm/action-setup@v4
30 | with:
31 | version: 9.11.0
32 |
33 | # Setup .npmrc file to publish to npm
34 | - uses: actions/setup-node@v4
35 | with:
36 | node-version: "20.x"
37 | registry-url: "https://registry.npmjs.org"
38 |
39 | - run: pnpm install
40 | - run: pnpm run --if-present test
41 | - run: pnpm run --if-present build
42 | - run: npm publish --ignore-scripts --access public
43 | env:
44 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
45 |
```
--------------------------------------------------------------------------------
/tools/python/examples/langchain/main.py:
--------------------------------------------------------------------------------
```python
1 | import os
2 | from dotenv import load_dotenv
3 |
4 | from langchain import hub
5 | from langchain_openai import ChatOpenAI
6 |
7 | from langgraph.prebuilt import create_react_agent
8 |
9 | from stripe_agent_toolkit.langchain.toolkit import StripeAgentToolkit
10 |
11 | load_dotenv()
12 |
13 | llm = ChatOpenAI(
14 | model="gpt-4o",
15 | )
16 |
17 | stripe_agent_toolkit = StripeAgentToolkit(
18 | secret_key=os.getenv("STRIPE_SECRET_KEY"),
19 | configuration={
20 | "actions": {
21 | "payment_links": {
22 | "create": True,
23 | },
24 | "products": {
25 | "create": True,
26 | },
27 | "prices": {
28 | "create": True,
29 | },
30 | }
31 | },
32 | )
33 |
34 | tools = []
35 | tools.extend(stripe_agent_toolkit.get_tools())
36 |
37 | langgraph_agent_executor = create_react_agent(llm, tools)
38 |
39 | input_state = {
40 | "messages": """
41 | Create a payment link for a new product called 'test' with a price
42 | of $100. Come up with a funny description about buy bots,
43 | maybe a haiku.
44 | """,
45 | }
46 |
47 | output_state = langgraph_agent_executor.invoke(input_state)
48 |
49 | print(output_state["messages"][-1].content)
50 |
```
--------------------------------------------------------------------------------
/llm/ai-sdk/provider/types.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Type definitions for Stripe AI SDK Provider
3 | */
4 |
5 | /**
6 | * Settings for Stripe language models
7 | */
8 | export interface StripeLanguageModelSettings {
9 | /**
10 | * Stripe customer ID to associate with usage.
11 | * Can be overridden per-call via providerOptions.
12 | */
13 | customerId?: string;
14 |
15 | /**
16 | * Additional custom headers to include in requests
17 | */
18 | headers?: Record<string, string>;
19 | }
20 |
21 | /**
22 | * Configuration for the Stripe provider
23 | */
24 | export interface StripeProviderConfig {
25 | /**
26 | * Base URL for API calls (defaults to https://llm.stripe.com)
27 | */
28 | baseURL?: string;
29 |
30 | /**
31 | * Stripe API key for authentication
32 | */
33 | apiKey?: string;
34 |
35 | /**
36 | * Default Stripe customer ID to associate with usage
37 | */
38 | customerId?: string;
39 |
40 | /**
41 | * Custom headers for requests
42 | */
43 | headers?: Record<string, string>;
44 | }
45 |
46 | /**
47 | * Provider-specific options that can be passed at call time
48 | */
49 | export interface StripeProviderOptions {
50 | /**
51 | * Override customer ID for this specific call
52 | */
53 | customerId?: string;
54 |
55 | /**
56 | * Additional headers for this specific call
57 | */
58 | headers?: Record<string, string>;
59 | }
60 |
61 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/crewai/toolkit.py:
--------------------------------------------------------------------------------
```python
1 | """Stripe Agent Toolkit."""
2 |
3 | from typing import List, Optional
4 | from pydantic import PrivateAttr
5 |
6 | from ..api import StripeAPI
7 | from ..tools import tools
8 | from ..configuration import Configuration, is_tool_allowed
9 | from .tool import StripeTool
10 |
11 |
12 | class StripeAgentToolkit:
13 | _tools: List = PrivateAttr(default=[])
14 |
15 | def __init__(
16 | self, secret_key: str, configuration: Optional[Configuration] = None
17 | ):
18 | super().__init__()
19 |
20 | context = configuration.get("context") if configuration else None
21 |
22 | stripe_api = StripeAPI(secret_key=secret_key, context=context)
23 |
24 | filtered_tools = [
25 | tool for tool in tools if is_tool_allowed(tool, configuration)
26 | ]
27 |
28 | self._tools = [
29 | StripeTool(
30 | name=tool["method"],
31 | description=tool["description"],
32 | method=tool["method"],
33 | stripe_api=stripe_api,
34 | args_schema=tool.get("args_schema", None),
35 | )
36 | for tool in filtered_tools
37 | ]
38 |
39 | def get_tools(self) -> List:
40 | """Get the tools in the toolkit."""
41 | return self._tools
42 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/langchain/toolkit.py:
--------------------------------------------------------------------------------
```python
1 | """Stripe Agent Toolkit."""
2 |
3 | from typing import List, Optional
4 | from pydantic import PrivateAttr
5 |
6 | from ..api import StripeAPI
7 | from ..tools import tools
8 | from ..configuration import Configuration, Context, is_tool_allowed
9 | from .tool import StripeTool
10 |
11 |
12 | class StripeAgentToolkit:
13 | _tools: List = PrivateAttr(default=[])
14 |
15 | def __init__(
16 | self, secret_key: str, configuration: Optional[Configuration] = None
17 | ):
18 | super().__init__()
19 |
20 | context = configuration.get("context") if configuration else None
21 |
22 | stripe_api = StripeAPI(secret_key=secret_key, context=context)
23 |
24 | filtered_tools = [
25 | tool for tool in tools if is_tool_allowed(tool, configuration)
26 | ]
27 |
28 | self._tools = [
29 | StripeTool(
30 | name=tool["method"],
31 | description=tool["description"],
32 | method=tool["method"],
33 | stripe_api=stripe_api,
34 | args_schema=tool.get("args_schema", None),
35 | )
36 | for tool in filtered_tools
37 | ]
38 |
39 | def get_tools(self) -> List:
40 | """Get the tools in the toolkit."""
41 | return self._tools
42 |
```
--------------------------------------------------------------------------------
/tools/typescript/examples/ai-sdk/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {StripeAgentToolkit} from '@stripe/agent-toolkit/ai-sdk';
2 | import {openai} from '@ai-sdk/openai';
3 | import {generateText, wrapLanguageModel, stepCountIs} from 'ai';
4 |
5 | require('dotenv').config();
6 |
7 | const stripeAgentToolkit = new StripeAgentToolkit({
8 | secretKey: process.env.STRIPE_SECRET_KEY!,
9 | configuration: {
10 | actions: {
11 | paymentLinks: {
12 | create: true,
13 | },
14 | products: {
15 | create: true,
16 | },
17 | prices: {
18 | create: true,
19 | },
20 | },
21 | },
22 | });
23 |
24 | const model = wrapLanguageModel({
25 | model: openai('gpt-5'),
26 | middleware: stripeAgentToolkit.middleware({
27 | billing: {
28 | customer: process.env.STRIPE_CUSTOMER_ID!,
29 | meters: {
30 | input: process.env.STRIPE_METER_INPUT!,
31 | output: process.env.STRIPE_METER_OUTPUT!,
32 | },
33 | },
34 | }),
35 | });
36 |
37 | (async () => {
38 | const result = await generateText({
39 | model: model,
40 |
41 | tools: {
42 | ...stripeAgentToolkit.getTools(),
43 | },
44 |
45 | stopWhen: stepCountIs(5),
46 |
47 | prompt:
48 | 'Create a payment link for a new product called "test" with a price of $100. Come up with a funny description about buy bots, maybe a haiku.',
49 | });
50 |
51 | console.log(result);
52 | })();
53 |
```
--------------------------------------------------------------------------------
/tools/python/stripe_agent_toolkit/strands/toolkit.py:
--------------------------------------------------------------------------------
```python
1 | """Stripe Agent Toolkit."""
2 |
3 | from typing import List, Optional, Dict
4 | from strands.tools.tools import PythonAgentTool as StrandTool
5 |
6 | from ..api import StripeAPI
7 | from ..tools import tools
8 | from ..configuration import Configuration, is_tool_allowed
9 | from .tool import StripeTool
10 | from .hooks import BillingHooks
11 |
12 |
13 | class StripeAgentToolkit:
14 | def __init__(
15 | self, secret_key: str, configuration: Optional[Configuration] = None
16 | ):
17 | context = configuration.get("context") if configuration else None
18 |
19 | self._stripe_api = StripeAPI(secret_key=secret_key, context=context)
20 |
21 | filtered_tools = [
22 | tool for tool in tools if is_tool_allowed(tool, configuration)
23 | ]
24 |
25 | self._tools = [
26 | StripeTool(self._stripe_api, tool)
27 | for tool in filtered_tools
28 | ]
29 |
30 | def get_tools(self) -> List[StrandTool]:
31 | """Get the tools in the toolkit."""
32 | return self._tools
33 |
34 | def billing_hook(
35 | self,
36 | type: Optional[str] = None,
37 | customer: Optional[str] = None,
38 | meter: Optional[str] = None,
39 | meters: Optional[Dict[str, str]] = None
40 | ) -> BillingHooks:
41 | return BillingHooks(self._stripe_api, type, customer, meter, meters)
42 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/balance/functions.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {retrieveBalance} from '@/shared/balance/retrieveBalance';
2 |
3 | const Stripe = jest.fn().mockImplementation(() => ({
4 | balance: {
5 | retrieve: jest.fn(),
6 | },
7 | }));
8 |
9 | let stripe: ReturnType<typeof Stripe>;
10 |
11 | beforeEach(() => {
12 | stripe = new Stripe('fake-api-key');
13 | });
14 |
15 | describe('retrieveBalance', () => {
16 | it('should retrieve the balance and return it', async () => {
17 | const mockBalance = {available: [{amount: 1000, currency: 'usd'}]};
18 |
19 | const context = {};
20 |
21 | stripe.balance.retrieve.mockResolvedValue(mockBalance);
22 |
23 | const result = await retrieveBalance(stripe, context, {});
24 |
25 | expect(stripe.balance.retrieve).toHaveBeenCalledWith({}, undefined);
26 | expect(result).toEqual(mockBalance);
27 | });
28 |
29 | it('should specify the connected account if included in context', async () => {
30 | const mockBalance = {available: [{amount: 1000, currency: 'usd'}]};
31 |
32 | const context = {
33 | account: 'acct_123456',
34 | };
35 |
36 | stripe.balance.retrieve.mockResolvedValue(mockBalance);
37 |
38 | const result = await retrieveBalance(stripe, context, {});
39 |
40 | expect(stripe.balance.retrieve).toHaveBeenCalledWith(
41 | {},
42 | {
43 | stripeAccount: context.account,
44 | }
45 | );
46 | expect(result).toEqual(mockBalance);
47 | });
48 | });
49 |
```
--------------------------------------------------------------------------------
/tools/typescript/src/test/shared/paymentLinks/prompts.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import {createPaymentLinkPrompt} from '@/shared/paymentLinks/createPaymentLink';
2 |
3 | describe('createPaymentLinkPrompt', () => {
4 | it('should return the correct prompt', () => {
5 | const prompt = createPaymentLinkPrompt({});
6 |
7 | expect(prompt).toContain('This tool will create a payment link in Stripe.');
8 | expect(prompt).toContain(
9 | 'price (str): The ID of the price to create the payment link for.'
10 | );
11 | expect(prompt).toContain(
12 | 'quantity (int): The quantity of the product to include in the payment link.'
13 | );
14 | expect(prompt).toContain(
15 | 'redirect_url (str, optional): The URL to redirect to after the payment is completed.'
16 | );
17 | });
18 |
19 | it('should return the correct prompt with customer context', () => {
20 | const prompt = createPaymentLinkPrompt({customer: 'cus_123'});
21 |
22 | expect(prompt).toContain('This tool will create a payment link in Stripe.');
23 | expect(prompt).toContain(
24 | 'price (str): The ID of the price to create the payment link for.'
25 | );
26 | expect(prompt).toContain(
27 | 'quantity (int): The quantity of the product to include in the payment link.'
28 | );
29 | expect(prompt).toContain(
30 | 'redirect_url (str, optional): The URL to redirect to after the payment is completed.'
31 | );
32 | });
33 | });
34 |
```