The best way to monetize AI applications & MCP, using x402, CDP Smart Wallets & Paymaster
Overview
The best way to read tweets onchain. A pay-per-use AI app - users pay 0.01 USDC per MCP query via x402, with CDP Smart Wallets, passkeys, and gas sponsorship on Base. 1. (Smart Wallet with passkeys or non-custodial wallets) 2. through a chat interface 3. automatically via x402 4. after successful payment 5. generated by AI Perfect for developers wanting to build with Web3 payments (x402) - 🔐 : Smart Wallets with Passkeys (CDP) or non-custodial wallets - 💳 : HTTP 402 Payment Required implementation for API access - 🔑 : Biometric login with Smart Wallets (most secure, no seed phrases) - ⛽ : Transaction fee sponsorship via paymaster for Smart Wallets - 🤖 : Generative UI with React component registry - 🔗 : Model Context Protocol for extensible AI functionality - 🌐 : Supports both Base testnet (default) and Base mainnet - 🛡️ : Clean architecture with proper error handling - 🎨 : AI can generate and render React components on demand - Node.
README
Star us ->
The best way to read tweets onchain. A pay-per-use AI chat app - users pay 0.01 USDC on Base for every query, with Coinbase Smart Wallets (passkeys) or any browser wallet, and MCP servers for tools and data.
See it in action
What it does
Tweazy is a Next.js template for a pay-per-use AI app:
- Connect a wallet - a Coinbase Smart Wallet with passkeys, or any injected browser wallet (MetaMask, Rabby, Coinbase Wallet, …).
- Ask a question in the chat.
- Pay 0.01 USDC on Base. Every query opens a payment step first; the message is only sent after the USDC transfer goes through.
- Get the answer, rendered with generative UI (charts and data cards) by Tambo AI.
- Add your own MCP servers at
/mcp-config(for example a Twitter/X data server) so the AI can call their tools.
Use it as a starting point for monetized AI apps with onchain payments.
Features
- Two wallet options: Coinbase Smart Wallet (passkeys, no seed phrase) or any injected wallet via wagmi.
- Per-query USDC payments on Base, set in
src/lib/config.ts(0.01 USDC by default). - Tambo AI generative UI with a React component registry (
src/lib/tambo.ts). - MCP support: user-configured MCP servers (HTTP or SSE), stored in the browser.
- Base Sepolia by default, Base mainnet with one env var.
Quick start
Prerequisites
- Node.js 24+ (see
.nvmrc) and npm - A Tambo AI API key
- A wallet address to receive payments
Setup
git clone https://github.com/aaronjmars/tweazy
cd tweazy
npm install
cp example.env.local .env.local # then fill in the values below
npm run dev
Open http://localhost:3000.
Scripts
npm run dev # dev server
npm run build # production build
npm run start # serve the production build
npm run lint # eslint
npm run format:check # biome (npm run format to fix)
npm run init # npx tambo init
Configuration
Secrets go in .env.local. Everything else (RPC URLs, USDC contracts, chain IDs, price) lives in src/lib/config.ts.
| Var | Required | Notes |
|---|---|---|
NEXT_PUBLIC_TAMBO_API_KEY |
yes | Tambo AI API key. |
NEXT_PUBLIC_PAYMENT_RECIPIENT |
yes | Wallet address that receives the 0.01 USDC payments. |
NEXT_PUBLIC_NETWORK_MODE |
no | testnet (default, Base Sepolia) or mainnet (Base). |
CDP_API_KEY_NAME, CDP_API_KEY_PRIVATE_KEY, CDP_WALLET_SECRET |
no | Coinbase CDP credentials for the /api/cdp/* routes. Without them, create-wallet, balance and fund-wallet return mock data. |
TWEAZY_ALLOW_MOCK_PAYMENT |
no | Set to 1 to let /api/cdp/transfer return a mock success when CDP is not configured. Local development only - never on a deployment that serves paid queries. |
Networks
| Mode | Network | Chain ID | USDC contract |
|---|---|---|---|
testnet (default) |
Base Sepolia | 84532 | 0x036CbD53842c5426634e7929541eC2318f3dCF7e |
mainnet |
Base | 8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
RPC URLs, contracts and chain IDs switch automatically with NEXT_PUBLIC_NETWORK_MODE. If the connected wallet is on the wrong chain, the app asks it to switch.
How it works
sequenceDiagram
participant User
participant App
participant Base
participant AI as Tambo AI + MCP
User->>App: Ask question
App->>User: Payment modal (0.01 USDC)
User->>Base: USDC transfer to the recipient
Base-->>App: Transaction confirmed
App->>AI: Send the query
AI-->>App: Response + generative UI
App->>User: Display answer
- The payment gate lives in
src/components/EnhancedMessageInput.tsx: every query opensPaymentModalbefore it is sent. src/lib/payment.tssends the USDC transfer with the right wallet: wagmiwriteContractfor injected wallets, the Coinbase Wallet SDK provider for Smart Wallets (src/lib/smart-wallet.ts).src/components/WalletProvider.tsxholds the two-wallet context.
Project structure
src/
├── app/
│ ├── api/cdp/ # CDP wallet routes (create-wallet, balance, fund-wallet, transfer)
│ ├── mcp-config/ # MCP server configuration page
│ ├── layout.tsx
│ └── page.tsx # Chat app (Tambo + MCP providers)
├── components/
│ ├── ui/ # Chat thread, messages, graph, data cards
│ ├── WalletProvider.tsx # Two-wallet context
│ ├── WalletSelector.tsx
│ ├── PaymentModal.tsx # Payment confirmation UI
│ └── EnhancedMessageInput.tsx # Chat input with the payment gate
├── hooks/usePayment.ts
└── lib/
├── config.ts # Network + app config
├── payment.ts # USDC transfers for both wallet types
├── smart-wallet.ts # Coinbase Smart Wallet (passkeys)
├── cdp-wallet.ts # Client for the /api/cdp routes
├── mcp-utils.ts # MCP server list (localStorage)
└── tambo.ts # Tambo component registry
API routes
POST /api/cdp/create-wallet- create a CDP wallet (mock address when CDP is not configured)POST /api/cdp/balance- USDC balance (mock balance when CDP is not configured)POST /api/cdp/fund-wallet- fund a wallet from the CDP faucet (Base Sepolia only; mock when CDP is not configured)POST /api/cdp/transfer- not implemented yet: returns 501 when CDP is configured, 503 when it is not (or a mock success withTWEAZY_ALLOW_MOCK_PAYMENT=1)
Security notes
- Defaults to testnet - Base Sepolia test tokens have no real value. Check
NEXT_PUBLIC_NETWORK_MODEbefore you deploy. - Mainnet moves real USDC.
- Secrets stay in env vars; non-secrets in
src/lib/config.ts. - Smart Wallets use passkeys; injected wallets keep user-controlled keys.
See SECURITY.md to report a vulnerability.
Troubleshooting
- “Payment recipient not configured” - set
NEXT_PUBLIC_PAYMENT_RECIPIENTin.env.localto a valid address. - “Tambo API key not found” - get a key at tambo.co/dashboard and set
NEXT_PUBLIC_TAMBO_API_KEY. - “Insufficient balance” - on testnet, get Base Sepolia ETH from a faucet for gas and testnet USDC (
0x036CbD53842c5426634e7929541eC2318f3dCF7e) for payments. - Wrong network - switch the wallet to Base Sepolia (84532) or Base (8453), matching
NEXT_PUBLIC_NETWORK_MODE.
Contributing
Fork, branch, and open a PR. Before you push, run npm run lint, npm run format:check and npm run build. Use conventional commits (feat: ..., fix: ...). See CONTRIBUTING.md.
Resources
- Tambo AI (GitHub) - generative UI with MCP support
- x402 - HTTP 402 payments
- Model Context Protocol
- Coinbase Developer Platform, Base, wagmi, viem
License
MIT, see LICENSE.
Built by Aaron Elijah Mars, founder of Aeon and MiroShark - @aaronjmars
Install
This server does not publish a one-line install command.
Open the repository installation guide New to MCP? Start with the mcpskill.org guide →
